[sysprof] Land Sysprof 2.x



commit 29c4ec495f0d0e290e4fdf8e7dcef802cdb48351
Author: Christian Hergert <chergert redhat com>
Date:   Wed Apr 13 05:24:03 2016 -0700

    Land Sysprof 2.x
    
    This is a major redesign a modernization of Sysprof. The core data
    structures and design are largely the same, but it has been ported to
    Gtk3 and has lots of additions that should make your profiling experience
    smoother. Especially for those that are new to profiling.
    
    There are some very simple help docs added, but we really need the
    experts to come in and write some documentation here.

 AUTHORS                                     |    4 +-
 COPYING.gpl-2                               |  340 +
 DESIGN.md                                   |   27 +
 Makefile.am                                 |  159 +-
 NEWS                                        |    7 -
 TODO                                        |   25 +
 autogen.sh                                  |   40 +-
 build-aux/tap-test                          |    5 +
 build-aux/test-driver                       |  148 +
 configure.ac                                |  188 +-
 daemon/Makefile.am                          |   14 +
 daemon/sd-bus-helper.c                      |  188 +
 daemon/sd-bus-helper.h                      |   36 +
 daemon/sysprofd.c                           |  347 +
 data/Makefile.am                            |   86 +
 data/icons/Makefile.am                      |   29 +
 data/org.gnome.Sysprof2.conf.in             |   16 +
 data/org.gnome.Sysprof2.desktop             |   13 +
 data/org.gnome.Sysprof2.service.in          |    5 +
 data/org.gnome.Sysprof2.xml                 |   24 +
 data/org.gnome.sysprof2.gschema.xml         |   34 +
 data/org.gnome.sysprof2.policy.in           |   22 +
 data/sysprof-mime.xml                       |    7 +
 data/sysprof.pc.in                          |   11 +
 data/sysprof2.service.in                    |    8 +
 git.mk                                      |  333 +
 gresources.mk                               |   62 +
 help/C/index.page                           |   18 +
 help/C/introduction.page                    |   57 +
 help/C/legal.xml                            |   12 +
 help/C/profiling.page                       |  140 +
 help/Makefile.am                            |   18 +
 lib/Makefile.am                             |  128 +
 lib/binfile.c                               |  530 --
 lib/collector.c                             |  806 ---
 lib/collector.h                             |   46 -
 lib/demangle.c                              | 9595 ---------------------------
 lib/elfparser.c                             |  814 ---
 lib/footreedatalist.c                       |  577 --
 lib/footreedatalist.h                       |   82 -
 lib/footreestore.c                          | 3363 ----------
 lib/footreestore.h                          |  158 -
 lib/profile.c                               |  605 --
 lib/profile.h                               |   78 -
 lib/resources/libsysprof.gresource.xml      |   11 +
 lib/resources/ui/sp-callgraph-view.ui       |  198 +
 lib/resources/ui/sp-empty-state-view.ui     |   64 +
 lib/resources/ui/sp-failed-state-view.ui    |   64 +
 lib/resources/ui/sp-process-model-row.ui    |   41 +
 lib/resources/ui/sp-profiler-menu-button.ui |  221 +
 lib/resources/ui/sp-recording-state-view.ui |   64 +
 lib/sfile.c                                 | 1180 ----
 lib/sfile.h                                 |  169 -
 lib/sformat.c                               |  646 --
 lib/sformat.h                               |   67 -
 lib/signal-handler.c                        |  215 -
 lib/signal-handler.h                        |   27 -
 lib/sp-address.c                            |   91 +
 lib/sp-address.h                            |   59 +
 lib/sp-callgraph-profile-private.h          |   31 +
 lib/sp-callgraph-profile.c                  |  376 ++
 lib/sp-callgraph-profile.h                  |   36 +
 lib/sp-callgraph-view.c                     |  881 +++
 lib/sp-callgraph-view.h                     |   44 +
 lib/sp-capture-reader.c                     |  686 ++
 lib/sp-capture-reader.h                     |   65 +
 lib/sp-capture-types.h                      |  155 +
 lib/sp-capture-writer.c                     |  954 +++
 lib/sp-capture-writer.h                     |  108 +
 lib/sp-cell-renderer-percent.c              |  135 +
 lib/sp-cell-renderer-percent.h              |   55 +
 lib/sp-clock.c                              |   51 +
 lib/sp-clock.h                              |   54 +
 lib/sp-elf-symbol-resolver.c                |  276 +
 lib/sp-elf-symbol-resolver.h                |   34 +
 lib/sp-empty-state-view.c                   |   41 +
 lib/sp-empty-state-view.h                   |   40 +
 lib/sp-error.c                              |   30 +
 lib/sp-error.h                              |   32 +
 lib/sp-failed-state-view.c                  |   42 +
 lib/sp-failed-state-view.h                  |   43 +
 lib/sp-gjs-source.c                         |  245 +
 lib/sp-gjs-source.h                         |   34 +
 lib/sp-jitmap-symbol-resolver.c             |  121 +
 lib/sp-jitmap-symbol-resolver.h             |   34 +
 lib/sp-kernel-symbol-resolver.c             |   79 +
 lib/sp-kernel-symbol-resolver.h             |   34 +
 lib/sp-kernel-symbol.c                      |  205 +
 lib/sp-kernel-symbol.h                      |   36 +
 lib/sp-line-reader.c                        |  124 +
 lib/sp-line-reader.h                        |   38 +
 lib/sp-map-lookaside.c                      |  119 +
 lib/sp-map-lookaside.h                      |   50 +
 lib/sp-model-filter.c                       |  472 ++
 lib/sp-model-filter.h                       |   48 +
 lib/sp-perf-counter.c                       |  671 ++
 lib/sp-perf-counter.h                       |  138 +
 lib/sp-perf-source.c                        |  459 ++
 lib/sp-perf-source.h                        |   36 +
 lib/sp-proc-source.c                        |  347 +
 lib/sp-proc-source.h                        |   36 +
 lib/sp-process-model-item.c                 |  191 +
 lib/sp-process-model-item.h                 |   40 +
 lib/sp-process-model-row.c                  |  209 +
 lib/sp-process-model-row.h                  |   46 +
 lib/sp-process-model.c                      |  293 +
 lib/sp-process-model.h                      |   35 +
 lib/sp-profile.c                            |   81 +
 lib/sp-profile.h                            |   59 +
 lib/sp-profiler-menu-button.c               |  857 +++
 lib/sp-profiler-menu-button.h               |   44 +
 lib/sp-profiler.c                           |  983 +++
 lib/sp-profiler.h                           |   92 +
 lib/sp-recording-state-view.c               |  193 +
 lib/sp-recording-state-view.h               |   43 +
 lib/sp-scrolled-window.c                    |  280 +
 lib/sp-scrolled-window.h                    |   45 +
 lib/sp-source.c                             |  137 +
 lib/sp-source.h                             |  133 +
 lib/sp-symbol-resolver.c                    |   72 +
 lib/sp-symbol-resolver.h                    |   55 +
 lib/sysprof-version.h.in                    |   97 +
 lib/sysprof.h                               |   59 +
 lib/testdemangle.c                          |    7 -
 lib/testelf.c                               |  100 -
 lib/testunwind.c                            |   27 -
 lib/tracker.c                               | 1127 ----
 lib/tracker.h                               |   29 -
 lib/treeviewutils.c                         |  362 -
 lib/treeviewutils.h                         |   55 -
 lib/unwind.c                                |  399 --
 lib/unwind.h                                |    3 -
 lib/util.h                                  |   40 -
 lib/util/binfile.c                          |  540 ++
 lib/{ => util}/binfile.h                    |   18 +-
 lib/util/demangle.cpp                       |   40 +
 lib/util/demangle.h                         |   30 +
 lib/util/elfparser.c                        |  811 +++
 lib/{ => util}/elfparser.h                  |    0
 lib/{ => util}/stackstash.c                 |  238 +-
 lib/{ => util}/stackstash.h                 |   57 +-
 lib/util/util.h                             |   32 +
 lib/watch.c                                 |  328 -
 lib/watch.h                                 |   40 -
 lib/xmlstore.c                              |  156 -
 lib/xmlstore.h                              |   58 -
 m4/Makefile.am                              |    1 +
 m4/appstream-xml.m4                         |   86 +
 m4/ax_append_compile_flags.m4               |   67 +
 m4/ax_append_flag.m4                        |   71 +
 m4/ax_append_link_flags.m4                  |   65 +
 m4/ax_check_compile_flag.m4                 |   74 +
 m4/ax_check_enable_debug.m4                 |  124 +
 m4/ax_check_link_flag.m4                    |   74 +
 m4/ax_compiler_flags.m4                     |  158 +
 m4/ax_compiler_flags_cflags.m4              |  133 +
 m4/ax_compiler_flags_cxxflags.m4            |  129 +
 m4/ax_compiler_flags_gir.m4                 |   60 +
 m4/ax_compiler_flags_ldflags.m4             |   75 +
 m4/ax_compiler_vendor.m4                    |   87 +
 m4/ax_cxx_compile_stdcxx_0x.m4              |  111 +
 m4/ax_cxx_compile_stdcxx_11.m4              |  172 +
 m4/ax_generate_changelog.m4                 |   99 +
 m4/ax_is_release.m4                         |   69 +
 m4/ax_require_defined.m4                    |   37 +
 m4/codeset.m4                               |   23 +
 m4/extern-inline.m4                         |  101 +
 m4/fcntl-o.m4                               |  134 +
 m4/gettext.m4                               |  405 ++
 m4/glib-gettext.m4                          |  436 ++
 m4/glibc2.m4                                |   31 +
 m4/glibc21.m4                               |   34 +
 m4/gsettings.m4                             |   83 +
 m4/iconv.m4                                 |  271 +
 m4/intdiv0.m4                               |   87 +
 m4/intl.m4                                  |  304 +
 m4/intldir.m4                               |   19 +
 m4/intlmacosx.m4                            |   56 +
 m4/intltool.m4                              |  212 +
 m4/intmax.m4                                |   36 +
 m4/introspection.m4                         |   96 +
 m4/inttypes-pri.m4                          |   42 +
 m4/inttypes_h.m4                            |   29 +
 m4/lcmessage.m4                             |   35 +
 m4/lib-ld.m4                                |  119 +
 m4/lib-link.m4                              |  777 +++
 m4/lib-prefix.m4                            |  224 +
 m4/libtool.m4                               | 8372 +++++++++++++++++++++++
 m4/lock.m4                                  |   42 +
 m4/longlong.m4                              |  113 +
 m4/ltoptions.m4                             |  437 ++
 m4/ltsugar.m4                               |  124 +
 m4/ltversion.m4                             |   23 +
 m4/lt~obsolete.m4                           |   99 +
 m4/nls.m4                                   |   32 +
 m4/pkg.m4                                   |  214 +
 m4/po.m4                                    |  453 ++
 m4/printf-posix.m4                          |   48 +
 m4/progtest.m4                              |   91 +
 m4/size_max.m4                              |   79 +
 m4/stdint_h.m4                              |   27 +
 m4/threadlib.m4                             |  389 ++
 m4/uintmax_t.m4                             |   30 +
 m4/vala.m4                                  |  135 +
 m4/vapigen.m4                               |  101 +
 m4/visibility.m4                            |   77 +
 m4/wchar_t.m4                               |   24 +
 m4/wint_t.m4                                |   32 +
 m4/xsize.m4                                 |   12 +
 m4/yelp.m4                                  |  213 +
 src/Makefile.am                             |   38 +
 src/resources/gtk/menus.ui                  |   51 +
 src/resources/sysprof.gresource.xml         |   21 +
 src/resources/theme/shared.css              |   12 +
 src/resources/ui/sp-window.ui               |  174 +
 src/sp-application.c                        |  271 +
 src/sp-application.h                        |   34 +
 src/sp-credits.h                            |   38 +
 src/sp-window-settings.c                    |  175 +
 src/sp-window-settings.h                    |   30 +
 src/sp-window.c                             |  853 +++
 src/sp-window.h                             |   52 +
 src/sysprof.c                               | 1733 +-----
 src/sysprof.glade                           |  926 ---
 sysprof.doap                                |    5 +
 tests/Makefile.am                           |   37 +
 tests/test-capture.c                        |  455 ++
 tests/test-model-filter.c                   |  119 +
 tools/Makefile.am                           |   19 +
 tools/sysprof-cli.c                         |  310 +-
 tools/sysprof-dump.c                        |  153 +
 231 files changed, 35480 insertions(+), 24797 deletions(-)
---
diff --git a/AUTHORS b/AUTHORS
index a8d0fae..1e844dd 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1 +1,3 @@
-Søren Sandmann (sandmann redhat com)
+# Generated by Makefile. Do not edit.
+
+Christian Hergert
diff --git a/COPYING.gpl-2 b/COPYING.gpl-2
new file mode 100644
index 0000000..d60c31a
--- /dev/null
+++ b/COPYING.gpl-2
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  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
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  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.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the 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 a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE 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.
+
+                    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
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the 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 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision 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, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This 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 Library General
+Public License instead of this License.
diff --git a/DESIGN.md b/DESIGN.md
new file mode 100644
index 0000000..44e2dde
--- /dev/null
+++ b/DESIGN.md
@@ -0,0 +1,27 @@
+# Sysprof 2.x
+
+## Design
+
+### libsysprof-2
+
+This library provides various UI components and profiling tools as a library.
+It is intended to be used from IDEs such as GNOME Builder.
+
+### sysprofd
+
+Sometimes, your current user does not have the required capabilities
+such as (`CAP_SYS_ADMIN`) to access performance counters. This daemon provides
+a way to get access to those counters while going through the normal
+authorization flow users are familiar with.
+
+### sysprof-cli
+
+This is a command line tool to help you capture in an automated fashion or
+when you don't have access to a UI or want to remove the UI overhead from
+system traces.
+
+### sysprof
+
+This is the tranditional Sysprof interface. It uses libsysprof-2 to setup
+and manage performance counters and display results.
+
diff --git a/Makefile.am b/Makefile.am
index 8be948d..b5aeb76 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,122 +1,37 @@
-ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
-
-#SUBDIRS = $(MODULE_SUBDIR)
-#DIST_SUBDIRS = module
-
-bin_PROGRAMS = sysprof-cli
-
-if BUILD_GUI
-bin_PROGRAMS += sysprof 
-endif
-
-SYSPROF_CORE =                                 \
-       binfile.h                               \
-       binfile.c                               \
-       collector.c                             \
-       collector.h                             \
-       demangle.c                              \
-       elfparser.c                             \
-       elfparser.h                             \
-       profile.h                               \
-       profile.c                               \
-       sfile.h                                 \
-       sfile.c                                 \
-       sformat.h                               \
-       sformat.c                               \
-       stackstash.h                            \
-       stackstash.c                            \
-       tracker.h                               \
-       tracker.c                               \
-       unwind.h                                \
-       unwind.c                                \
-       watch.h                                 \
-       watch.c                                 \
-                                               \
-       util.h
-
-#      module/sysprof-module.h                 
-
-#
-# GUI version
-#
-if BUILD_GUI
-
-sysprof_SOURCES =                              \
-       $(SYSPROF_CORE)                         \
-       footreestore.c                          \
-       footreestore.h                          \
-       footreedatalist.h                       \
-       footreedatalist.c                       \
-       treeviewutils.h                         \
-       treeviewutils.c                         \
-       sysprof.c
-
-sysprof_CPPFLAGS =                             \
-       $(GUI_DEP_CFLAGS)                       \
-       -DDATADIR=\"$(pkgdatadir)\"             \
-       -DPIXMAPDIR=\"$(pixmapsdir)\"
-
-sysprof_LDADD = $(GUI_DEP_LIBS)
-
-endif
-
-udevdir = $(sysconfdir)/udev/rules.d
-dist_udev_DATA = 60-sysprof.rules
-
-pixmapsdir = $(datadir)/pixmaps
-
-dist_pkgdata_DATA = sysprof.glade
-dist_pixmaps_DATA = sysprof-icon-16.png sysprof-icon-24.png sysprof-icon-32.png sysprof-icon-48.png 
sysprof-icon-256.png
-
-#
-# Command line version
-#
-
-sysprof_cli_SOURCES =                          \
-       $(SYSPROF_CORE)                         \
-       signal-handler.h                        \
-       signal-handler.c                        \
-       sysprof-cli.c
-
-sysprof_cli_CPPFLAGS =                         \
-       $(CORE_DEP_CFLAGS)
-
-sysprof_cli_LDADD = $(CORE_DEP_LIBS)
-
-EXTRA_DIST =                                   \
-       sysprof-icon-source.svg
-
-# 
-# Test programs
-#
-noinst_PROGRAMS = testelf testunwind testdemangle
-
-# testunwind
-testunwind_SOURCES =   \
-       testunwind.c    \
-       demangle.c      \
-       elfparser.c     \
-       elfparser.h     \
-       unwind.c        \
-       unwind.h
-testunwind_CPPFLAGS = $(CORE_DEP_CFLAGS)
-testunwind_LDADD = $(CORE_DEP_LIBS)
-
-# testelf
-testelf_SOURCES =      \
-       testelf.c       \
-       demangle.c      \
-       elfparser.c     \
-       elfparser.h
-
-testelf_CPPFLAGS = $(CORE_DEP_CFLAGS)
-testelf_LDADD = $(CORE_DEP_LIBS)
-
-# testdemangle
-testdemangle_SOURCES = \
-       testdemangle.c  \
-       elfparser.c     \
-       elfparser.h     \
-       demangle.c
-testdemangle_CPPFLAGS = $(CORE_DEP_CFLAGS)
-testdemangle_LDADD = $(CORE_DEP_LIBS)
+SUBDIRS = daemon data help lib po src tools tests
+
+EXTRA_DIST = AUTHORS
+
+DISTCHECK_CONFIGURE_FLAGS = --with-systemdsystemunitdir='$(prefix)/etc/systemd/system'
+
+AUTHORS:
+       $(AM_V_GEN)if test -d "$(srcdir)/.git"; \
+       then \
+               echo Creating $@ && \
+               ( cd "$(top_srcdir)" && \
+                 echo '# Generated by Makefile. Do not edit.'; echo; \
+                 git log --no-merges --pretty=format:"%an" $(SUBDIRS) \
+                 | sort | uniq ) > $  tmp \
+               && mv -f $  tmp $@ \
+               || ( rm -f $  tmp ; \
+                    echo Failed to generate $@ >&2 ); \
+       else touch $@; fi
+
+# Generate the ChangeLog.
+ GENERATE_CHANGELOG_RULES@
+dist-hook: dist-ChangeLog
+
+GITIGNOREFILES = \
+       **/*.swp \
+       *.o \
+       aclocal.m4 \
+       build-aux \
+       ChangeLog \
+       config \
+       config.h.in \
+       gtk-doc.m4 \
+       gtk-doc.make \
+       INSTALL \
+       $(NULL)
+
+-include $(top_srcdir)/git.mk
diff --git a/NEWS b/NEWS
index b0b7720..e69de29 100644
--- a/NEWS
+++ b/NEWS
@@ -1,7 +0,0 @@
-- New 'everything' object
-- New commandline version [Lorenzo Colitti]
-- Assign time spent in kernel to the user process responsible
-- New screenshot window
-- Device based on udev [Kristian Hoegsberg]
-- Port to RHEL4 [Bastien Nocera]
-- Performance improvements
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..5812353
--- /dev/null
+++ b/TODO
@@ -0,0 +1,25 @@
+# TODO
+
+ - Follow fork/threads
+
+   Currently, when watching a pid, we do not have a way to follow forks.
+   We need to watch FORK/EXIT events and create/dispose additional perf
+   streams from the kernel.
+
+ - Add cpu/mem/net data source
+
+ - Add frame types for generic counters
+
+ - Add support for visualizations other than the callgraph.
+
+   1) I'd like to see a graph of call depth over time.
+   2) line graphs for cpu/mem/net.
+   3) disk I/O
+
+   etc.
+
+   One quick way to put together the UI is to just use ListBox for the
+   rows. Then we need a "graph" child that allows drawing. The nice thing
+   here is that we get pixel caching for free. Resizing the row height
+   gets a little annoying though.
+
diff --git a/autogen.sh b/autogen.sh
index 095dd7c..abadb9a 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,21 +1,37 @@
 #!/bin/sh
 # Run this to generate all the initial makefiles, etc.
-
-test -n "$srcdir" || srcdir=`dirname "$0"`
+test -n "$srcdir" || srcdir=$(dirname "$0")
 test -n "$srcdir" || srcdir=.
 
-olddir=`pwd`
-cd "$srcdir"
+olddir=$(pwd)
 
-mkdir m4
+cd $srcdir
 
-AUTORECONF=`which autoreconf`
-if test -z $AUTORECONF; then
-        echo "*** No autoreconf found, please install it ***"
-        exit 1
-else
-        autoreconf --force --install --verbose || exit $?
+(test -f configure.ac) || {
+       echo "*** ERROR: Directory '$srcdir' does not look like the top-level project directory ***"
+       exit 1
+}
+
+# shellcheck disable=SC2016
+PKG_NAME=$(autoconf --trace 'AC_INIT:$1' configure.ac)
+
+if [ "$#" = 0 -a "x$NOCONFIGURE" = "x" ]; then
+       echo "*** WARNING: I am going to run 'configure' with no arguments." >&2
+       echo "*** If you wish to pass any to it, please specify them on the" >&2
+       echo "*** '$0' command line." >&2
+       echo "" >&2
 fi
 
+aclocal --install || exit 1
+autoreconf --verbose --force --install || exit 1
+
 cd "$olddir"
-test -n "$NOCONFIGURE" || "$srcdir/configure" "$@"
+if [ "$NOCONFIGURE" = "" ]; then
+       $srcdir/configure "$@" || exit 1
+
+       if [ "$1" = "--help" ]; then exit 0 else
+               echo "Now type 'make' to compile $PKG_NAME" || exit 1
+       fi
+else
+       echo "Skipping configure process."
+fi
diff --git a/build-aux/tap-test b/build-aux/tap-test
new file mode 100755
index 0000000..481e333
--- /dev/null
+++ b/build-aux/tap-test
@@ -0,0 +1,5 @@
+#! /bin/sh
+
+# run a GTest in tap mode. The test binary is passed as $1
+
+$1 -k --tap
diff --git a/build-aux/test-driver b/build-aux/test-driver
new file mode 100755
index 0000000..8e575b0
--- /dev/null
+++ b/build-aux/test-driver
@@ -0,0 +1,148 @@
+#! /bin/sh
+# test-driver - basic testsuite driver script.
+
+scriptversion=2013-07-13.22; # UTC
+
+# Copyright (C) 2011-2014 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake gnu org> or send patches to
+# <automake-patches gnu org>.
+
+# Make unconditional expansion of undefined variables an error.  This
+# helps a lot in preventing typo-related bugs.
+set -u
+
+usage_error ()
+{
+  echo "$0: $*" >&2
+  print_usage >&2
+  exit 2
+}
+
+print_usage ()
+{
+  cat <<END
+Usage:
+  test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
+              [--expect-failure={yes|no}] [--color-tests={yes|no}]
+              [--enable-hard-errors={yes|no}] [--]
+              TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
+The '--test-name', '--log-file' and '--trs-file' options are mandatory.
+END
+}
+
+test_name= # Used for reporting.
+log_file=  # Where to save the output of the test script.
+trs_file=  # Where to save the metadata of the test run.
+expect_failure=no
+color_tests=no
+enable_hard_errors=yes
+while test $# -gt 0; do
+  case $1 in
+  --help) print_usage; exit $?;;
+  --version) echo "test-driver $scriptversion"; exit $?;;
+  --test-name) test_name=$2; shift;;
+  --log-file) log_file=$2; shift;;
+  --trs-file) trs_file=$2; shift;;
+  --color-tests) color_tests=$2; shift;;
+  --expect-failure) expect_failure=$2; shift;;
+  --enable-hard-errors) enable_hard_errors=$2; shift;;
+  --) shift; break;;
+  -*) usage_error "invalid option: '$1'";;
+   *) break;;
+  esac
+  shift
+done
+
+missing_opts=
+test x"$test_name" = x && missing_opts="$missing_opts --test-name"
+test x"$log_file"  = x && missing_opts="$missing_opts --log-file"
+test x"$trs_file"  = x && missing_opts="$missing_opts --trs-file"
+if test x"$missing_opts" != x; then
+  usage_error "the following mandatory options are missing:$missing_opts"
+fi
+
+if test $# -eq 0; then
+  usage_error "missing argument"
+fi
+
+if test $color_tests = yes; then
+  # Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
+  red='' # Red.
+  grn='' # Green.
+  lgn='' # Light green.
+  blu='' # Blue.
+  mgn='' # Magenta.
+  std=''     # No color.
+else
+  red= grn= lgn= blu= mgn= std=
+fi
+
+do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
+trap "st=129; $do_exit" 1
+trap "st=130; $do_exit" 2
+trap "st=141; $do_exit" 13
+trap "st=143; $do_exit" 15
+
+# Test script is run here.
+"$@" >$log_file 2>&1
+estatus=$?
+
+if test $enable_hard_errors = no && test $estatus -eq 99; then
+  tweaked_estatus=1
+else
+  tweaked_estatus=$estatus
+fi
+
+case $tweaked_estatus:$expect_failure in
+  0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
+  0:*)   col=$grn res=PASS  recheck=no  gcopy=no;;
+  77:*)  col=$blu res=SKIP  recheck=no  gcopy=yes;;
+  99:*)  col=$mgn res=ERROR recheck=yes gcopy=yes;;
+  *:yes) col=$lgn res=XFAIL recheck=no  gcopy=yes;;
+  *:*)   col=$red res=FAIL  recheck=yes gcopy=yes;;
+esac
+
+# Report the test outcome and exit status in the logs, so that one can
+# know whether the test passed or failed simply by looking at the '.log'
+# file, without the need of also peaking into the corresponding '.trs'
+# file (automake bug#11814).
+echo "$res $test_name (exit status: $estatus)" >>$log_file
+
+# Report outcome to console.
+echo "${col}${res}${std}: $test_name"
+
+# Register the test result, and other relevant metadata.
+echo ":test-result: $res" > $trs_file
+echo ":global-test-result: $res" >> $trs_file
+echo ":recheck: $recheck" >> $trs_file
+echo ":copy-in-global-log: $gcopy" >> $trs_file
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/configure.ac b/configure.ac
index ad3b786..124649d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,34 +1,113 @@
-AC_PREREQ([2.63])
+AC_PREREQ([2.69])
 
-AC_INIT([sysprof], [1.3.1])
 
+dnl ***********************************************************************
+dnl Define Versioning Information
+dnl ***********************************************************************
+m4_define([major_version],[3])
+m4_define([minor_version],[19])
+m4_define([micro_version],[90])
+m4_define([package_version],[major_version.minor_version.micro_version])
+m4_define([bug_report_url],[https://bugzilla.gnome.org/enter_bug.cgi?product=sysprof])
+m4_define([api_version],[2])
+
+AX_IS_RELEASE([micro-version])
+
+
+dnl ***********************************************************************
+dnl Initialize autoconf
+dnl ***********************************************************************
+AC_INIT([sysprof],[package_version],[bug_report_url])
 AC_CONFIG_HEADERS([config.h])
-AC_CONFIG_SRCDIR([sysprof.glade])
+AC_CONFIG_SRCDIR([data/sysprof.pc.in])
 AC_CONFIG_MACRO_DIR([m4])
 AC_CONFIG_AUX_DIR([build-aux])
+AC_SUBST([ACLOCAL_AMFLAGS], "-I m4")
+AC_CANONICAL_HOST
+
+
+dnl ***********************************************************************
+dnl Make version information available to autoconf files
+dnl ***********************************************************************
+AC_SUBST([MAJOR_VERSION],major_version)
+AC_SUBST([MINOR_VERSION],minor_version)
+AC_SUBST([MICRO_VERSION],micro_version)
+AC_SUBST([API_VERSION],api_version)
+
 
-AM_INIT_AUTOMAKE([1.10 -Wall no-define])
+dnl ***********************************************************************
+dnl Initialize automake
+dnl ***********************************************************************
+AM_SILENT_RULES([yes])
+AM_INIT_AUTOMAKE([1.11 foreign subdir-objects tar-ustar no-dist-gzip dist-xz -Wno-portability])
 AM_MAINTAINER_MODE([enable])
+AX_GENERATE_CHANGELOG
 
-# Support silent build rules, requires at least automake-1.11. Disable
-# by either passing --disable-silent-rules to configure or passing V=1
-# to make
-m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 
-# Check for programs
+dnl ***********************************************************************
+dnl Add extra debugging with --enable-debug and --enable-compile-warnings
+dnl ***********************************************************************
+AX_CHECK_ENABLE_DEBUG([no],[]
+                      [G_DISABLE_ASSERT G_DISABLE_CHECKS G_DISABLE_CAST_CHECKS])
+AX_COMPILER_FLAGS
+
+
+dnl ***********************************************************************
+dnl Internationalization
+dnl ***********************************************************************
+GETTEXT_PACKAGE=AC_PACKAGE_TARNAME
+AC_SUBST([GETTEXT_PACKAGE])
+AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE], ["$GETTEXT_PACKAGE"], [GETTEXT package name])
+
+AM_GNU_GETTEXT_VERSION([0.19.6])
+AM_GNU_GETTEXT([external])
+
+
+dnl ***********************************************************************
+dnl Check for required programs
+dnl ***********************************************************************
+AX_COMPILER_FLAGS_CXXFLAGS
 AC_PROG_CC
-AM_PROG_CC_C_O
 AC_PROG_INSTALL
-
-changequote(,)dnl
-if test "x$GCC" = "xyes"; then
-  case " $CFLAGS " in
-  *[\ \        ]-Wall[\ \      ]*) ;;
-  *) CFLAGS="$CFLAGS -Wall" ;;
-  esac
+AX_CXX_COMPILE_STDCXX_0X
+AC_PATH_PROG([GLIB_GENMARSHAL],[glib-genmarshal])
+AC_PATH_PROG([GLIB_MKENUMS],[glib-mkenums])
+AC_PATH_PROG([GLIB_COMPILE_RESOURCES],[glib-compile-resources])
+PKG_PROG_PKG_CONFIG([0.22])
+GLIB_GSETTINGS
+GOBJECT_INTROSPECTION_CHECK([1.42.0])
+VAPIGEN_CHECK
+
+
+dnl ***********************************************************************
+dnl Check for required packages
+dnl ***********************************************************************
+PKG_CHECK_MODULES(SYSPROF, [gio-2.0 >= 2.44
+                            gtk+-3.0 >= 3.16
+                            polkit-gobject-1])
+PKG_CHECK_MODULES(SYSTEMD, [libsystemd >= 222],
+                           [have_systemd=yes],
+                           [have_systemd=no])
+
+
+# we require systemd for sysprofd
+AM_CONDITIONAL(ENABLE_SYSPROFD, [test x$have_systemd = xyes])
+
+
+# where to place systemd units if necessary
+AC_ARG_WITH([systemdsystemunitdir],
+            AS_HELP_STRING([--with-systemdsystemunitdir=DIR],
+                           [Directory for systemd service files]),
+            [],
+            [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)])
+if test "x$with_systemdsystemunitdir" != "xno"; then
+  AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
 fi
-changequote([,])dnl
 
+
+dnl ***********************************************************************
+dnl Override location of debug symbols for system libraries
+dnl ***********************************************************************
 debugdir=${libdir}/debug
 
 # Separate debug dir
@@ -48,37 +127,70 @@ AC_DEFUN([AC_DEFINE_DIR], [
 ])
 
 AC_ARG_WITH(separate-debug-dir,
-[  --with-separate-debug-dir=path   Look for global separate debug info in this path [LIBDIR/debug]],
-[debugdir="${withval}"])
+            [  --with-separate-debug-dir=path   Look for global separate debug info in this path 
[LIBDIR/debug]],
+            [debugdir="${withval}"])
        
 AC_DEFINE_DIR(DEBUGDIR, debugdir,
               [Look for global separate debug info in this path])
 
-# Kernel version
-KMAJOR=`uname -r | cut -d"." -f 1`
-KMINOR=`uname -r | cut -d"." -f 2`
-KMICRO=`uname -r | cut -d"." -f 3 | cut -d"-" -f 1`
+AC_SUBST([LIBEXECDIR], `eval echo "${libexecdir}"`)
 
-# Pkgconfig dependencies
 
-core_dep="glib-2.0 >= 2.6.0"
-gui_dep="gtk+-2.0 > 2.6.0 gdk-pixbuf-2.0 pangoft2 libglade-2.0"
+dnl ***********************************************************************
+dnl User documentation
+dnl ***********************************************************************
+YELP_HELP_INIT
 
-PKG_CHECK_MODULES(CORE_DEP, $core_dep, [], AC_MSG_ERROR([sysprof dependencies not satisfied]))
 
-build_gui=yes
-PKG_CHECK_MODULES(GUI_DEP, $gui_dep, [], build_gui=no)
+dnl ***********************************************************************
+dnl Initialize Libtool
+dnl ***********************************************************************
+LT_PREREQ([2.2])
+LT_INIT
 
-AM_CONDITIONAL([BUILD_GUI], [test "$build_gui" = yes])
 
-# emit files
+dnl ***********************************************************************
+dnl Process .in Files
+dnl ***********************************************************************
+AC_CONFIG_FILES([
+       Makefile
 
-AC_SUBST(CORE_DEP_LIBS)
-AC_SUBST(GUI_DEP_LIBS)
-AC_SUBST(MODULE_SUBDIR)
+       lib/Makefile
+       lib/sysprof-version.h
 
-AC_CONFIG_FILES([
-Makefile
-])
+       daemon/Makefile
+
+       data/Makefile
+       data/icons/Makefile
+       data/sysprof-$API_VERSION.pc:data/sysprof.pc.in
+       data/org.gnome.Sysprof2.conf
+       data/org.gnome.sysprof2.policy
+
+       help/Makefile
 
+       po/Makefile.in
+
+       src/Makefile
+
+       tests/Makefile
+
+       tools/Makefile
+],[],
+[API_VERSION='$API_VERSION'])
 AC_OUTPUT
+
+
+echo ""
+echo " ${PACKAGE} - ${VERSION}"
+echo ""
+echo " Options"
+echo ""
+echo "  Prefix ............................... : ${prefix}"
+echo "  Libdir ............................... : ${libdir}"
+echo "  Libexecdir ........................... : ${libexecdir}"
+echo ""
+echo "  Debug Directory ...................... : ${debugdir}"
+echo ""
+echo "  Sysprofd ............................. : ${have_systemd}"
+echo "  Systemd System Units ................. : ${with_systemdsystemunitdir}"
+echo ""
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
new file mode 100644
index 0000000..c7eaaad
--- /dev/null
+++ b/daemon/Makefile.am
@@ -0,0 +1,14 @@
+if ENABLE_SYSPROFD
+
+pkglibexec_PROGRAMS = sysprofd
+
+sysprofd_SOURCES = \
+       sysprofd.c \
+       sd-bus-helper.c \
+       sd-bus-helper.h
+
+sysprofd_LDADD = $(SYSTEMD_LIBS)
+
+endif
+
+-include $(top_srcdir)/git.mk
diff --git a/daemon/sd-bus-helper.c b/daemon/sd-bus-helper.c
new file mode 100644
index 0000000..1444a07
--- /dev/null
+++ b/daemon/sd-bus-helper.c
@@ -0,0 +1,188 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd 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
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <assert.h>
+#include <errno.h>
+
+#include "sd-bus-helper.h"
+
+/*
+ * Various macros to simplify lifing code from sd-bus.
+ */
+#define assert_return(expr,val) do { if (!(expr)) return (val); } while (0)
+#define _cleanup_(f) __attribute__((cleanup(f)))
+#define STRV_FOREACH_PAIR(x, y, l) \
+  for ((x) = (l), (y) = (x+1); (x) && *(x) && *(y); (x) += 2, (y) = (x + 1))
+
+/*
+ * To support systemd 222, we need a couple helpers that were added
+ * in 229. If we update code from systemd in the future, we can probably
+ * drop these helpres.
+ */
+
+static void
+_sd_bus_message_unrefp (sd_bus_message **m)
+{
+  if (m && *m)
+    {
+      sd_bus_message_unref (*m);
+      *m = NULL;
+    }
+}
+
+static void
+_sd_bus_creds_unrefp (sd_bus_creds **c)
+{
+  if (c && *c)
+    {
+      sd_bus_creds_unref (*c);
+      *c = NULL;
+    }
+}
+
+/*
+ * Begin verbatim code from systemd. Please try to keep this in sync until
+ * systemd exposes helpers for polkit integration.
+ */
+static int
+check_good_user (sd_bus_message *m,
+                 uid_t           good_user)
+{
+  _cleanup_(_sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+  uid_t sender_uid;
+  int r;
+
+  assert (m);
+
+  if (good_user == UID_INVALID)
+    return 0;
+
+  r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds);
+  if (r < 0)
+    return r;
+
+  /* Don't trust augmented credentials for authorization */
+  assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM);
+
+  r = sd_bus_creds_get_euid(creds, &sender_uid);
+  if (r < 0)
+    return r;
+
+  return sender_uid == good_user;
+}
+
+int
+bus_test_polkit (sd_bus_message  *call,
+                 int              capability,
+                 const char      *action,
+                 const char     **details,
+                 uid_t            good_user,
+                 bool            *_challenge,
+                 sd_bus_error    *e)
+{
+  int r;
+
+  assert (call);
+  assert (action);
+
+  /* Tests non-interactively! */
+
+  r = check_good_user(call, good_user);
+  if (r != 0)
+    return r;
+
+  r = sd_bus_query_sender_privilege(call, capability);
+  if (r < 0)
+    return r;
+  else if (r > 0)
+    return 1;
+  else {
+    _cleanup_(_sd_bus_message_unrefp) sd_bus_message *request = NULL;
+    _cleanup_(_sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+    int authorized = false, challenge = false;
+    const char *sender, **k, **v;
+
+    sender = sd_bus_message_get_sender(call);
+    if (!sender)
+      return -EBADMSG;
+
+    r = sd_bus_message_new_method_call(sd_bus_message_get_bus (call),
+                                       &request,
+                                       "org.freedesktop.PolicyKit1",
+                                       "/org/freedesktop/PolicyKit1/Authority",
+                                       "org.freedesktop.PolicyKit1.Authority",
+                                       "CheckAuthorization");
+    if (r < 0)
+      return r;
+
+    r = sd_bus_message_append(request,
+                              "(sa{sv})s",
+                              "system-bus-name", 1, "name", "s", sender,
+                              action);
+    if (r < 0)
+      return r;
+
+    r = sd_bus_message_open_container(request, 'a', "{ss}");
+    if (r < 0)
+      return r;
+
+    STRV_FOREACH_PAIR(k, v, details) {
+      r = sd_bus_message_append(request, "{ss}", *k, *v);
+      if (r < 0)
+        return r;
+    }
+
+    r = sd_bus_message_close_container(request);
+    if (r < 0)
+      return r;
+
+    r = sd_bus_message_append(request, "us", 0, NULL);
+    if (r < 0)
+      return r;
+
+    r = sd_bus_call(sd_bus_message_get_bus(call), request, 0, e, &reply);
+    if (r < 0) {
+      /* Treat no PK available as access denied */
+      if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
+        sd_bus_error_free(e);
+        return -EACCES;
+      }
+
+      return r;
+    }
+
+    r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
+    if (r < 0)
+      return r;
+
+    r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
+    if (r < 0)
+      return r;
+
+    if (authorized)
+      return 1;
+
+    if (_challenge) {
+      *_challenge = challenge;
+      return 0;
+    }
+  }
+
+  return -EACCES;
+}
diff --git a/daemon/sd-bus-helper.h b/daemon/sd-bus-helper.h
new file mode 100644
index 0000000..58e2b9b
--- /dev/null
+++ b/daemon/sd-bus-helper.h
@@ -0,0 +1,36 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd 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
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#ifndef SD_BUS_HELPER_H
+#define SD_BUS_HELPER_H
+
+#include <stdbool.h>
+#include <systemd/sd-bus.h>
+
+#define UID_INVALID ((uid_t)-1)
+
+int bus_test_polkit (sd_bus_message  *call,
+                     int              capability,
+                     const char      *action,
+                     const char     **details,
+                     uid_t            good_user,
+                     bool            *_challenge,
+                     sd_bus_error    *e);
+
+#endif /* SD_BUS_HELPER_H */
diff --git a/daemon/sysprofd.c b/daemon/sysprofd.c
new file mode 100644
index 0000000..1700456
--- /dev/null
+++ b/daemon/sysprofd.c
@@ -0,0 +1,347 @@
+/* sysprofd.c
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <linux/capability.h>
+#include <linux/perf_event.h>
+#include <stdlib.h>
+#include <sys/syscall.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "sd-bus-helper.h"
+
+#define BUS_TIMEOUT_USEC (1000000L * 10L)
+
+static int
+_perf_event_open (struct perf_event_attr *attr,
+                  pid_t                   pid,
+                  int                     cpu,
+                  int                     group_fd,
+                  unsigned long           flags)
+{
+  assert (attr != NULL);
+
+  /* Quick sanity check */
+  if (attr->sample_period < 100000)
+    return -EINVAL;
+
+  return syscall (__NR_perf_event_open, attr, pid, cpu, group_fd, flags);
+}
+
+#if 0
+#define GOTO(l) do { \
+  fprintf (stderr, "GOTO: %s:%d: " #l "\n", __FUNCTION__, __LINE__); \
+  goto l; \
+} while (0)
+#else
+#define GOTO(l) goto l
+#endif
+
+static int
+sysprofd_perf_event_open (sd_bus_message *msg,
+                          void           *user_data,
+                          sd_bus_error   *error)
+{
+  struct perf_event_attr attr = { 0 };
+  sd_bus_message *reply = NULL;
+  sd_bus_message *kvpair;
+  uint64_t flags = 0;
+  int disabled = 0;
+  int32_t wakeup_events = 149;
+  int32_t cpu = -1;
+  int32_t pid = -1;
+  bool challenge = false;
+  int32_t type = 0;
+  uint64_t sample_period = 0;
+  uint64_t sample_type = 0;
+  uint64_t config = 0;
+  int clockid = CLOCK_MONOTONIC_RAW;
+  int comm = 0;
+  int mmap_ = 0;
+  int task = 0;
+  int exclude_idle = 0;
+  int fd = -1;
+  int use_clockid = 0;
+  int r;
+
+  assert (msg);
+
+  r = sd_bus_message_enter_container (msg, SD_BUS_TYPE_ARRAY, "{sv}");
+  if (r < 0)
+    return r;
+
+  for (;;)
+    {
+      const char *name = NULL;
+
+      r = sd_bus_message_enter_container (msg, SD_BUS_TYPE_DICT_ENTRY, "sv");
+      if (r < 0)
+        return r;
+
+      if (r == 0)
+        break;
+
+      r = sd_bus_message_read (msg, "s", &name);
+      if (r < 0)
+        goto cleanup;
+
+      r = sd_bus_message_enter_container (msg, SD_BUS_TYPE_VARIANT, NULL);
+      if (r < 0)
+        goto cleanup;
+
+      if (strcmp (name, "disabled") == 0)
+        {
+          r = sd_bus_message_read (msg, "b", &disabled);
+          if (r < 0)
+            GOTO (cleanup);
+        }
+      else if (strcmp (name, "wakeup_events") == 0)
+        {
+          r = sd_bus_message_read (msg, "u", &wakeup_events);
+          if (r < 0)
+            GOTO (cleanup);
+        }
+      else if (strcmp (name, "clockid") == 0)
+        {
+          r = sd_bus_message_read (msg, "i", &clockid);
+          if (r < 0)
+            GOTO (cleanup);
+        }
+      else if (strcmp (name, "comm") == 0)
+        {
+          r = sd_bus_message_read (msg, "b", &comm);
+          if (r < 0)
+            GOTO (cleanup);
+        }
+      else if (strcmp (name, "exclude_idle") == 0)
+        {
+          r = sd_bus_message_read (msg, "b", &exclude_idle);
+          if (r < 0)
+            GOTO (cleanup);
+        }
+      else if (strcmp (name, "mmap") == 0)
+        {
+          r = sd_bus_message_read (msg, "b", &mmap_);
+          if (r < 0)
+            GOTO (cleanup);
+        }
+      else if (strcmp (name, "config") == 0)
+        {
+          r = sd_bus_message_read (msg, "t", &config);
+          if (r < 0)
+            GOTO (cleanup);
+        }
+      else if (strcmp (name, "sample_period") == 0)
+        {
+          r = sd_bus_message_read (msg, "t", &sample_period);
+          if (r < 0)
+            GOTO (cleanup);
+        }
+      else if (strcmp (name, "sample_type") == 0)
+        {
+          r = sd_bus_message_read (msg, "t", &sample_type);
+          if (r < 0)
+            GOTO (cleanup);
+        }
+      else if (strcmp (name, "task") == 0)
+        {
+          r = sd_bus_message_read (msg, "b", &task);
+          if (r < 0)
+            GOTO (cleanup);
+        }
+      else if (strcmp (name, "type") == 0)
+        {
+          r = sd_bus_message_read (msg, "u", &type);
+          if (r < 0)
+            GOTO (cleanup);
+        }
+      else if (strcmp (name, "use_clockid") == 0)
+        {
+          r = sd_bus_message_read (msg, "b", &use_clockid);
+          if (r < 0)
+            GOTO (cleanup);
+        }
+
+      r = sd_bus_message_exit_container (msg);
+      if (r < 0)
+        goto cleanup;
+
+      sd_bus_message_exit_container (msg);
+      if (r < 0)
+        goto cleanup;
+
+    cleanup:
+      if (r < 0)
+        return r;
+    }
+
+  r = sd_bus_message_exit_container (msg);
+  if (r < 0)
+    return r;
+
+  r = sd_bus_message_read (msg, "iit", &pid, &cpu, &flags);
+  if (r < 0)
+    return r;
+
+  if (pid < -1 || cpu < -1)
+    return -EINVAL;
+
+  r = sd_bus_message_new_method_return (msg, &reply);
+  if (r < 0)
+    return r;
+
+  /* Authorize peer */
+  r = bus_test_polkit (msg,
+                       CAP_SYS_ADMIN,
+                       "org.gnome.sysprof2.perf-event-open",
+                       NULL,
+                       UID_INVALID,
+                       &challenge,
+                       error);
+  if (r < 0)
+    return r;
+  else if (r == 0)
+    return -EACCES;
+
+  if (!use_clockid || clockid < 0)
+    clockid = CLOCK_MONOTONIC_RAW;
+
+  attr.comm = !!comm;
+  attr.config = config;
+  attr.disabled = disabled;
+  attr.exclude_idle = !!exclude_idle;
+  attr.mmap = !!mmap_;
+  attr.sample_period = sample_period;
+  attr.sample_type = sample_type;
+  attr.size = sizeof attr;
+  attr.task = !!task;
+  attr.type = type;
+  attr.clockid = clockid;
+  attr.use_clockid = use_clockid;
+  attr.wakeup_events = wakeup_events;
+
+  fd = _perf_event_open (&attr, pid, cpu, -1, 0);
+  if (fd < 0)
+    {
+      fprintf (stderr,
+               "Failed to open perf event stream: %s\n",
+               strerror (errno));
+      return -EINVAL;
+    }
+
+  sd_bus_message_append_basic (reply, SD_BUS_TYPE_UNIX_FD, &fd);
+  r = sd_bus_send (NULL, reply, NULL);
+  sd_bus_message_unref (reply);
+
+  close (fd);
+
+  return r;
+}
+
+static const sd_bus_vtable sysprofd_vtable[] = {
+  SD_BUS_VTABLE_START (0),
+  SD_BUS_METHOD ("PerfEventOpen", "a{sv}iit", "h", sysprofd_perf_event_open, SD_BUS_VTABLE_UNPRIVILEGED),
+  SD_BUS_VTABLE_END
+};
+
+int
+main (int   argc,
+      char *argv[])
+{
+  sd_bus_slot *slot = NULL;
+  sd_bus *bus = NULL;
+  int r;
+
+  /* Connect to the system bus */
+  r = sd_bus_default_system (&bus);
+  if (r < 0)
+    {
+      fprintf (stderr,
+               "Failed to connect to system bus: %s\n",
+               strerror (-r));
+      goto failure;
+    }
+
+  /* Install our object */
+  r = sd_bus_add_object_vtable (bus,
+                                &slot,
+                                "/org/gnome/Sysprof2",
+                                "org.gnome.Sysprof2",
+                                sysprofd_vtable,
+                                NULL);
+  if (r < 0)
+    {
+      fprintf (stderr,
+               "Failed to install object on bus: %s\n",
+               strerror (-r));
+      goto failure;
+    }
+
+  /* Request our well-known name on the bus */
+  r = sd_bus_request_name (bus, "org.gnome.Sysprof2", 0);
+  if (r < 0)
+    {
+      fprintf (stderr,
+               "Failed to register name on the bus: %s\n",
+               strerror (-r));
+      goto failure;
+    }
+
+  for (;;)
+    {
+      /* Process requests */
+      r = sd_bus_process (bus, NULL);
+      if (r < 0)
+        {
+          fprintf (stderr,
+                   "Failed to process bus: %s\n",
+                   strerror (-r));
+          goto failure;
+        }
+
+      /* If we processed a request, continue processing */
+      if (r > 0)
+        continue;
+
+      /* Wait for the next request to process */
+      r = sd_bus_wait (bus, BUS_TIMEOUT_USEC);
+      if (r < 0)
+        {
+          fprintf (stderr,
+                   "Failed to wait on bus: %s\n",
+                   strerror (-r));
+          goto failure;
+        }
+
+      /*
+       * If we timed out, we can expire, we will be auto-started by
+       * systemd or dbus on the next activation request.
+       */
+      if (r == 0)
+        break;
+    }
+
+failure:
+  sd_bus_slot_unref (slot);
+  sd_bus_unref (bus);
+
+  return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/data/Makefile.am b/data/Makefile.am
new file mode 100644
index 0000000..d76e65c
--- /dev/null
+++ b/data/Makefile.am
@@ -0,0 +1,86 @@
+SUBDIRS = icons
+
+mimedir = $(datadir)/mime/packages
+mime_DATA = sysprof-mime.xml
+
+desktopdir = $(datadir)/applications
+desktop_DATA = org.gnome.Sysprof2.desktop
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = sysprof-$(API_VERSION).pc
+
+gsettings_SCHEMAS = org.gnome.sysprof2.gschema.xml
+
+.PRECIOUS: $(gsettings_SCHEMAS)
+
+ GSETTINGS_RULES@
+
+EXTRA_DIST = \
+       sysprof.pc.in \
+       org.gnome.Sysprof2.desktop \
+       $(mime_DATA) \
+       $(gsettings_SCHEMAS) \
+       $(NULL)
+
+DISTCLEANFILES = $(pkgconfig_DATA)
+GITIGNOREFILES = $(dbusservice_DATA)
+
+
+if ENABLE_SYSPROFD
+
+dbusservicedir = $(datadir)/dbus-1/system-services
+dbusservice_in_files = org.gnome.Sysprof2.service.in
+dbusservice_DATA = $(dbusservice_in_files:.service.in=.service)
+
+$(dbusservice_DATA): $(dbusservice_in_files) Makefile
+       @sed -e "s|\ sysprofdprivdir\@|$(libexecdir)/$(PACKAGE)|" $< > $@
+
+dbusconfdir = $(datadir)/dbus-1/system.d
+dbusconf_in_files = org.gnome.Sysprof2.conf.in
+dbusconf_DATA = $(dbusconf_in_files:.conf.in=.conf)
+
+systemdservice_in_files = sysprof2.service.in
+systemdservicedir = $(systemdsystemunitdir)
+systemdservice_DATA = $(systemdservice_in_files:.service.in=.service)
+
+$(systemdservice_DATA): $(systemdservice_in_files) Makefile
+       @sed -e "s|\ sysprofdprivdir\@|$(libexecdir)/$(PACKAGE)|" $< > $@
+
+polkitdir = $(datadir)/polkit-1/actions
+polkit_in_files = org.gnome.sysprof2.policy.in
+polkit_DATA = $(polkit_in_files:.policy.in=.policy)
+
+DISTCLEANFILES += \
+       $(systemdservice_DATA) \
+       $(dbusservice_DATA) \
+       $(NULL)
+
+EXTRA_DIST += \
+       org.gnome.Sysprof2.xml \
+       $(dbusservice_in_files) \
+       $(dbusconf_in_files) \
+       $(systemdservice_in_files) \
+       $(polkit_in_files) \
+       $(NULL)
+
+GITIGNOREFILES += $(systemdservice_DATA)
+
+endif
+
+
+install-data-local: install-mimeDATA
+       if [ -f $(DESTDIR)$(datadir)/mime/packages/freedesktop.org.xml ] ; then \
+         if which update-mime-database>/dev/null 2>&1; then \
+           update-mime-database $(DESTDIR)$(datadir)/mime; \
+         fi \
+       fi
+
+uninstall-local:
+       if [ -f $(DESTDIR)$(datadir)/mime/packages/freedesktop.org.xml ] ; then \
+         if which update-mime-database>/dev/null 2>&1; then \
+           update-mime-database $(DESTDIR)$(datadir)/mime; \
+         fi \
+       fi
+
+
+-include $(top_srcdir)/git.mk
diff --git a/data/icons/Makefile.am b/data/icons/Makefile.am
new file mode 100644
index 0000000..e4674db
--- /dev/null
+++ b/data/icons/Makefile.am
@@ -0,0 +1,29 @@
+icondir = $(datadir)/icons/hicolor
+
+nobase_icon_DATA = \
+       16x16/apps/sysprof.png \
+       24x24/apps/sysprof.png \
+       32x32/apps/sysprof.png \
+       48x48/apps/sysprof.png \
+       256x256/apps/sysprof.png \
+       scalable/apps/sysprof-symbolic.svg \
+       $(NULL)
+
+EXTRA_DIST = \
+       $(nobase_icon_DATA) \
+       sysprof-source.svg
+
+gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor
+
+install-data-hook: update-icon-cache
+uninstall-hook: update-icon-cache
+update-icon-cache:
+       @-if test -z "$(DESTDIR)"; then \
+               echo "Updating Gtk icon cache."; \
+               $(gtk_update_icon_cache); \
+       else \
+               echo "*** Icon cache not updated.  After (un)install, run this:"; \
+               echo "***   $(gtk_update_icon_cache)"; \
+       fi
+
+-include $(top_srcdir)/git.mk
diff --git a/data/org.gnome.Sysprof2.conf.in b/data/org.gnome.Sysprof2.conf.in
new file mode 100644
index 0000000..ec693bb
--- /dev/null
+++ b/data/org.gnome.Sysprof2.conf.in
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd";>
+<busconfig>
+  <!-- Only root can own the service -->
+  <policy user="root">
+    <allow own="org.gnome.Sysprof2"/>
+  </policy>
+
+  <!-- Anyone can send messages to the owner of org.gnome.Sysprof2 -->
+  <policy context="default">
+    <allow send_destination="org.gnome.Sysprof2"/>
+  </policy>
+</busconfig>
diff --git a/data/org.gnome.Sysprof2.desktop b/data/org.gnome.Sysprof2.desktop
new file mode 100644
index 0000000..7dc0a20
--- /dev/null
+++ b/data/org.gnome.Sysprof2.desktop
@@ -0,0 +1,13 @@
+[Desktop Entry]
+Version=1.0
+Name=Sysprof
+GenericName=Profiler
+Comment=Profile an application or entire system.
+Exec=sysprof %u
+TryExec=sysprof
+Icon=sysprof
+StartupNotify=true
+Terminal=false
+Type=Application
+Categories=GNOME;Development;
+MimeType=application/x-sysprof-capture;
diff --git a/data/org.gnome.Sysprof2.service.in b/data/org.gnome.Sysprof2.service.in
new file mode 100644
index 0000000..3455b65
--- /dev/null
+++ b/data/org.gnome.Sysprof2.service.in
@@ -0,0 +1,5 @@
+[D-BUS Service]
+Name=org.gnome.Sysprof2
+Exec= sysprofdprivdir@/sysprofd
+User=root
+SystemdService=sysprof2.service
diff --git a/data/org.gnome.Sysprof2.xml b/data/org.gnome.Sysprof2.xml
new file mode 100644
index 0000000..46e87e1
--- /dev/null
+++ b/data/org.gnome.Sysprof2.xml
@@ -0,0 +1,24 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd";>
+<node>
+ <interface name="org.gnome.Sysprof2">
+  <!--
+    PerfEventOpen:
+    @options: key-value pair of attributes for the perf_event_open() syscall.
+    @pid: the process id to monitor, or -1 for system-wide.
+    @cpu: affinity to cpu.
+    @flags: flags for perf_event_open() syscall.
+    @perf_stream_fd: (out): A fd to communicate with perf.
+
+    Performs the perf_event_open() syscall with elevated privileges and passes
+    the resulting fd back to the calling process.
+  -->
+  <method name="PerfEventOpen">
+   <arg name="options" type="a{sv}" direction="in"/>
+   <arg name="pid" type="i" direction="in"/>
+   <arg name="cpu" type="i" direction="in"/>
+   <arg name="flags" type="t" direction="in"/>
+   <arg name="perf_stream_fd" type="h" direction="out"/>
+  </method>
+ </interface>
+</node>
diff --git a/data/org.gnome.sysprof2.gschema.xml b/data/org.gnome.sysprof2.gschema.xml
new file mode 100644
index 0000000..8e9dc42
--- /dev/null
+++ b/data/org.gnome.sysprof2.gschema.xml
@@ -0,0 +1,34 @@
+<schemalist>
+  <schema id="org.gnome.sysprof2" path="/org/gnome/sysprof/" gettext-domain="sysprof">
+    <key name="window-size" type="(ii)">
+      <default>(-1, -1)</default>
+      <summary>Window size</summary>
+      <description>Window size (width and height).</description>
+    </key>
+    <key name="window-position" type="(ii)">
+      <default>(-1,-1)</default>
+      <summary>Window position</summary>
+      <description>Window position (x and y).</description>
+    </key>
+    <key name="window-maximized" type="b">
+      <default>true</default>
+      <summary>Window maximized</summary>
+      <description>Window maximized state</description>
+    </key>
+    <key name="last-spawn-argv" type="s">
+      <default>''</default>
+      <summary>Last Spawn Program</summary>
+      <description>The last spawned program, which will be set in the UI upon restart of the 
application.</description>
+    </key>
+    <key name="last-spawn-inherit-env" type="b">
+      <default>true</default>
+      <summary>Last Spawn Inherit Environment</summary>
+      <description>If the last spawned environment inherits the parent environment.</description>
+    </key>
+    <key name="last-spawn-env" type="as">
+      <default>[]</default>
+      <summary>Last Spawn Environment</summary>
+      <description>The last spawned environment, which will be set in the UI upon restart of the 
application.</description>
+    </key>
+  </schema>
+</schemalist>
diff --git a/data/org.gnome.sysprof2.policy.in b/data/org.gnome.sysprof2.policy.in
new file mode 100644
index 0000000..5ba36e1
--- /dev/null
+++ b/data/org.gnome.sysprof2.policy.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd";>
+
+<policyconfig>
+  <vendor>The sysprof Project</vendor>
+  <vendor_url>https://wiki.gnome.org/Apps/Sysprof</vendor_url>
+  <icon_name>sysprof</icon_name>
+
+  <action id="org.gnome.sysprof2.perf-event-open">
+    <description>Open a perf event stream</description>
+    <message>Authentication is required to access system performance counters.</message>
+    <defaults>
+      <allow_any>auth_admin_keep</allow_any>
+      <allow_inactive>auth_admin_keep</allow_inactive>
+      <allow_active>auth_admin_keep</allow_active>
+    </defaults>
+  </action>
+
+</policyconfig>
diff --git a/data/sysprof-mime.xml b/data/sysprof-mime.xml
new file mode 100644
index 0000000..5f7e2d9
--- /dev/null
+++ b/data/sysprof-mime.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info";>
+  <mime-type type="application/x-sysprof-capture">
+    <comment>Sysprof Capture</comment>
+    <glob pattern="*.syscap"/>
+  </mime-type>
+</mime-info>
diff --git a/data/sysprof.pc.in b/data/sysprof.pc.in
new file mode 100644
index 0000000..bfdb998
--- /dev/null
+++ b/data/sysprof.pc.in
@@ -0,0 +1,11 @@
+prefix= prefix@
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${exec_prefix}/include
+
+Name: libsysprof- API_VERSION@
+Description: The sysprof library for integrating profiling into IDEs
+Version: @VERSION@
+Libs: -L${libdir} -lsysprof- API_VERSION@
+Cflags: -I${includedir}/sysprof- API_VERSION@
+Requires: gio-2.0 gtk+-3.0
diff --git a/data/sysprof2.service.in b/data/sysprof2.service.in
new file mode 100644
index 0000000..9ee4632
--- /dev/null
+++ b/data/sysprof2.service.in
@@ -0,0 +1,8 @@
+[Unit]
+Description=Sysprof Daemon
+
+[Service]
+Type=dbus
+BusName=org.gnome.Sysprof2
+ExecStart= sysprofdprivdir@/sysprofd
+
diff --git a/git.mk b/git.mk
new file mode 100644
index 0000000..9d4bf25
--- /dev/null
+++ b/git.mk
@@ -0,0 +1,333 @@
+# git.mk, a small Makefile to autogenerate .gitignore files
+# for autotools-based projects.
+#
+# Copyright 2009, Red Hat, Inc.
+# Copyright 2010,2011,2012,2013 Behdad Esfahbod
+# Written by Behdad Esfahbod
+#
+# Copying and distribution of this file, with or without modification,
+# is permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+#
+# The latest version of this file can be downloaded from:
+GIT_MK_URL = https://raw.githubusercontent.com/behdad/git.mk/master/git.mk
+#
+# Bugs, etc, should be reported upstream at:
+#   https://github.com/behdad/git.mk
+#
+# To use in your project, import this file in your git repo's toplevel,
+# then do "make -f git.mk".  This modifies all Makefile.am files in
+# your project to -include git.mk.  Remember to add that line to new
+# Makefile.am files you create in your project, or just rerun the
+# "make -f git.mk".
+#
+# This enables automatic .gitignore generation.  If you need to ignore
+# more files, add them to the GITIGNOREFILES variable in your Makefile.am.
+# But think twice before doing that.  If a file has to be in .gitignore,
+# chances are very high that it's a generated file and should be in one
+# of MOSTLYCLEANFILES, CLEANFILES, DISTCLEANFILES, or MAINTAINERCLEANFILES.
+#
+# The only case that you need to manually add a file to GITIGNOREFILES is
+# when remove files in one of mostlyclean-local, clean-local, distclean-local,
+# or maintainer-clean-local make targets.
+#
+# Note that for files like editor backup, etc, there are better places to
+# ignore them.  See "man gitignore".
+#
+# If "make maintainer-clean" removes the files but they are not recognized
+# by this script (that is, if "git status" shows untracked files still), send
+# me the output of "git status" as well as your Makefile.am and Makefile for
+# the directories involved and I'll diagnose.
+#
+# For a list of toplevel files that should be in MAINTAINERCLEANFILES, see
+# Makefile.am.sample in the git.mk git repo.
+#
+# Don't EXTRA_DIST this file.  It is supposed to only live in git clones,
+# not tarballs.  It serves no useful purpose in tarballs and clutters the
+# build dir.
+#
+# This file knows how to handle autoconf, automake, libtool, gtk-doc,
+# gnome-doc-utils, yelp.m4, mallard, intltool, gsettings, dejagnu, appdata,
+# appstream.
+#
+# This makefile provides the following targets:
+#
+# - all: "make all" will build all gitignore files.
+# - gitignore: makes all gitignore files in the current dir and subdirs.
+# - .gitignore: make gitignore file for the current dir.
+# - gitignore-recurse: makes all gitignore files in the subdirs.
+#
+# KNOWN ISSUES:
+#
+# - Recursive configure doesn't work as $(top_srcdir)/git.mk inside the
+#   submodule doesn't find us.  If you have configure.{in,ac} files in
+#   subdirs, add a proxy git.mk file in those dirs that simply does:
+#   "include $(top_srcdir)/../git.mk".  Add more ..'s to your taste.
+#   And add those files to git.  See vte/gnome-pty-helper/git.mk for
+#   example.
+#
+
+
+
+###############################################################################
+# Variables user modules may want to add to toplevel MAINTAINERCLEANFILES:
+###############################################################################
+
+#
+# Most autotools-using modules should be fine including this variable in their
+# toplevel MAINTAINERCLEANFILES:
+GITIGNORE_MAINTAINERCLEANFILES_TOPLEVEL = \
+       $(srcdir)/aclocal.m4 \
+       $(srcdir)/autoscan.log \
+       $(srcdir)/configure.scan \
+       `AUX_DIR=$(srcdir)/$$(cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_AUX_DIR:$$1' ./configure.ac); \
+        test "x$$AUX_DIR" = "x$(srcdir)/" && AUX_DIR=$(srcdir); \
+        for x in \
+               ar-lib \
+               compile \
+               config.guess \
+               config.sub \
+               depcomp \
+               install-sh \
+               ltmain.sh \
+               missing \
+               mkinstalldirs \
+               test-driver \
+               ylwrap \
+        ; do echo "$$AUX_DIR/$$x"; done` \
+       `cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_HEADERS:$$1' ./configure.ac | \
+       head -n 1 | while read f; do echo "$(srcdir)/$$f.in"; done`
+#
+# All modules should also be fine including the following variable, which
+# removes automake-generated Makefile.in files:
+GITIGNORE_MAINTAINERCLEANFILES_MAKEFILE_IN = \
+       `cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_FILES:$$1' ./configure.ac | \
+       while read f; do \
+         case $$f in Makefile|*/Makefile) \
+           test -f "$(srcdir)/$$f.am" && echo "$(srcdir)/$$f.in";; esac; \
+       done`
+#
+# Modules that use libtool and use  AC_CONFIG_MACRO_DIR() may also include this,
+# though it's harmless to include regardless.
+GITIGNORE_MAINTAINERCLEANFILES_M4_LIBTOOL = \
+       `MACRO_DIR=$(srcdir)/$$(cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_MACRO_DIR:$$1' 
./configure.ac); \
+        if test "x$$MACRO_DIR" != "x$(srcdir)/"; then \
+               for x in \
+                       libtool.m4 \
+                       ltoptions.m4 \
+                       ltsugar.m4 \
+                       ltversion.m4 \
+                       lt~obsolete.m4 \
+               ; do echo "$$MACRO_DIR/$$x"; done; \
+        fi`
+
+
+
+###############################################################################
+# Default rule is to install ourselves in all Makefile.am files:
+###############################################################################
+
+git-all: git-mk-install
+
+git-mk-install:
+       @echo "Installing git makefile"
+       @any_failed=; \
+               find "`test -z "$(top_srcdir)" && echo . || echo "$(top_srcdir)"`" -name Makefile.am | while 
read x; do \
+               if grep 'include .*/git.mk' $$x >/dev/null; then \
+                       echo "$$x already includes git.mk"; \
+               else \
+                       failed=; \
+                       echo "Updating $$x"; \
+                       { cat $$x; \
+                         echo ''; \
+                         echo '-include $$(top_srcdir)/git.mk'; \
+                       } > $$x.tmp || failed=1; \
+                       if test x$$failed = x; then \
+                               mv $$x.tmp $$x || failed=1; \
+                       fi; \
+                       if test x$$failed = x; then : else \
+                               echo "Failed updating $$x"; >&2 \
+                               any_failed=1; \
+                       fi; \
+       fi; done; test -z "$$any_failed"
+
+git-mk-update:
+       wget $(GIT_MK_URL) -O $(top_srcdir)/git.mk
+
+.PHONY: git-all git-mk-install git-mk-update
+
+
+
+###############################################################################
+# Actual .gitignore generation:
+###############################################################################
+
+$(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk
+       @echo "git.mk: Generating $@"
+       @{ \
+               if test "x$(DOC_MODULE)" = x -o "x$(DOC_MAIN_SGML_FILE)" = x; then :; else \
+                       for x in \
+                               $(DOC_MODULE)-decl-list.txt \
+                               $(DOC_MODULE)-decl.txt \
+                               tmpl/$(DOC_MODULE)-unused.sgml \
+                               "tmpl/*.bak" \
+                               xml html \
+                       ; do echo "/$$x"; done; \
+                       FLAVOR=$$(cd $(top_srcdir); $(AUTOCONF) --trace 'GTK_DOC_CHECK:$$2' ./configure.ac); \
+                       case $$FLAVOR in *no-tmpl*) echo /tmpl;; esac; \
+               fi; \
+               if test "x$(DOC_MODULE)$(DOC_ID)" = x -o "x$(DOC_LINGUAS)" = x; then :; else \
+                       for lc in $(DOC_LINGUAS); do \
+                               for x in \
+                                       $(if $(DOC_MODULE),$(DOC_MODULE).xml) \
+                                       $(DOC_PAGES) \
+                                       $(DOC_INCLUDES) \
+                               ; do echo "/$$lc/$$x"; done; \
+                       done; \
+                       for x in \
+                               $(_DOC_OMF_ALL) \
+                               $(_DOC_DSK_ALL) \
+                               $(_DOC_HTML_ALL) \
+                               $(_DOC_MOFILES) \
+                               $(DOC_H_FILE) \
+                               "*/.xml2po.mo" \
+                               "*/*.omf.out" \
+                       ; do echo /$$x; done; \
+               fi; \
+               if test "x$(HELP_ID)" = x -o "x$(HELP_LINGUAS)" = x; then :; else \
+                       for lc in $(HELP_LINGUAS); do \
+                               for x in \
+                                       $(HELP_FILES) \
+                                       "$$lc.stamp" \
+                                       "$$lc.mo" \
+                               ; do echo "/$$lc/$$x"; done; \
+                       done; \
+               fi; \
+               if test "x$(gsettings_SCHEMAS)" = x; then :; else \
+                       for x in \
+                               $(gsettings_SCHEMAS:.xml=.valid) \
+                               $(gsettings__enum_file) \
+                       ; do echo "/$$x"; done; \
+               fi; \
+               if test "x$(appdata_XML)" = x; then :; else \
+                       for x in \
+                               $(appdata_XML:.xml=.valid) \
+                       ; do echo "/$$x"; done; \
+               fi; \
+               if test "x$(appstream_XML)" = x; then :; else \
+                       for x in \
+                               $(appstream_XML:.xml=.valid) \
+                       ; do echo "/$$x"; done; \
+               fi; \
+               if test -f $(srcdir)/po/Makefile.in.in; then \
+                       for x in \
+                               po/Makefile.in.in \
+                               po/Makefile.in.in~ \
+                               po/Makefile.in \
+                               po/Makefile \
+                               po/Makevars.template \
+                               po/POTFILES \
+                               po/Rules-quot \
+                               po/stamp-it \
+                               po/.intltool-merge-cache \
+                               "po/*.gmo" \
+                               "po/*.header" \
+                               "po/*.mo" \
+                               "po/*.sed" \
+                               "po/*.sin" \
+                               po/$(GETTEXT_PACKAGE).pot \
+                               intltool-extract.in \
+                               intltool-merge.in \
+                               intltool-update.in \
+                       ; do echo "/$$x"; done; \
+               fi; \
+               if test -f $(srcdir)/configure; then \
+                       for x in \
+                               autom4te.cache \
+                               configure \
+                               config.h \
+                               stamp-h1 \
+                               libtool \
+                               config.lt \
+                       ; do echo "/$$x"; done; \
+               fi; \
+               if test "x$(DEJATOOL)" = x; then :; else \
+                       for x in \
+                               $(DEJATOOL) \
+                       ; do echo "/$$x.sum"; echo "/$$x.log"; done; \
+                       echo /site.exp; \
+               fi; \
+               if test "x$(am__dirstamp)" = x; then :; else \
+                       echo "$(am__dirstamp)"; \
+               fi; \
+               if test "x$(LTCOMPILE)" = x -a "x$(LTCXXCOMPILE)" = x -a "x$(GTKDOC_RUN)" = x; then :; else \
+                       for x in \
+                               "*.lo" \
+                               ".libs" "_libs" \
+                       ; do echo "$$x"; done; \
+               fi; \
+               for x in \
+                       .gitignore \
+                       $(GITIGNOREFILES) \
+                       $(CLEANFILES) \
+                       $(PROGRAMS) $(check_PROGRAMS) $(EXTRA_PROGRAMS) \
+                       $(LIBRARIES) $(check_LIBRARIES) $(EXTRA_LIBRARIES) \
+                       $(LTLIBRARIES) $(check_LTLIBRARIES) $(EXTRA_LTLIBRARIES) \
+                       so_locations \
+                       $(MOSTLYCLEANFILES) \
+                       $(TEST_LOGS) \
+                       $(TEST_LOGS:.log=.trs) \
+                       $(TEST_SUITE_LOG) \
+                       $(TESTS:=.test) \
+                       "*.gcda" \
+                       "*.gcno" \
+                       $(DISTCLEANFILES) \
+                       $(am__CONFIG_DISTCLEAN_FILES) \
+                       $(CONFIG_CLEAN_FILES) \
+                       TAGS ID GTAGS GRTAGS GSYMS GPATH tags \
+                       "*.tab.c" \
+                       $(MAINTAINERCLEANFILES) \
+                       $(BUILT_SOURCES) \
+                       $(patsubst %.vala,%.c,$(filter %.vala,$(SOURCES))) \
+                       $(filter %_vala.stamp,$(DIST_COMMON)) \
+                       $(filter %.vapi,$(DIST_COMMON)) \
+                       $(filter $(addprefix %,$(notdir $(patsubst %.vapi,%.h,$(filter 
%.vapi,$(DIST_COMMON))))),$(DIST_COMMON)) \
+                       Makefile \
+                       Makefile.in \
+                       "*.orig" \
+                       "*.rej" \
+                       "*.bak" \
+                       "*~" \
+                       ".*.sw[nop]" \
+                       ".dirstamp" \
+               ; do echo "/$$x"; done; \
+               for x in \
+                       "*.$(OBJEXT)" \
+                       $(DEPDIR) \
+               ; do echo "$$x"; done; \
+       } | \
+       sed "s ^/`echo "$(srcdir)" | sed 's/\(.\)/[\1]/g'`/@/@" | \
+       sed 's@/[.]/@/@g' | \
+       LC_ALL=C sort | uniq > $  tmp && \
+       mv $  tmp $@;
+
+all: $(srcdir)/.gitignore gitignore-recurse-maybe
+gitignore: $(srcdir)/.gitignore gitignore-recurse
+
+gitignore-recurse-maybe:
+       @for subdir in $(DIST_SUBDIRS); do \
+         case " $(SUBDIRS) " in \
+           *" $$subdir "*) :;; \
+           *) test "$$subdir" = . -o -e "$$subdir/.git" || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) gitignore 
|| echo "Skipping $$subdir");; \
+         esac; \
+       done
+gitignore-recurse:
+       @for subdir in $(DIST_SUBDIRS); do \
+           test "$$subdir" = . -o -e "$$subdir/.git" || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) gitignore || 
echo "Skipping $$subdir"); \
+       done
+
+maintainer-clean: gitignore-clean
+gitignore-clean:
+       -rm -f $(srcdir)/.gitignore
+
+.PHONY: gitignore-clean gitignore gitignore-recurse gitignore-recurse-maybe
diff --git a/gresources.mk b/gresources.mk
new file mode 100644
index 0000000..d1b849b
--- /dev/null
+++ b/gresources.mk
@@ -0,0 +1,62 @@
+# Rules for generating gresources using glib-compile-resources
+#
+# Define:
+#      glib_resources_h = header template file
+#      glib_resources_c = source template file
+#      glib_resources_xml = path to *.gresource.xml
+#      glib_resources_namespace = c prefix for resources
+#
+# before including Makefile.am.resources. You will also need to have
+# the following targets already defined:
+#
+#      CLEANFILES
+#      DISTCLEANFILES
+#      BUILT_SOURCES
+#      EXTRA_DIST
+#
+# Author: Christian Hergert <christian hergert me>
+
+# Basic sanity checks
+$(if $(GLIB_COMPILE_RESOURCES),,$(error Need to define GLIB_COMPILE_RESOURCES))
+
+$(if $(or $(glib_resources_h), \
+          $(glib_resources_c)),, \
+    $(error Need to define glib_resources_h and glib_resources_c))
+
+$(if $(glib_resources_xml),,$(error Need to define glib_resources_xml))
+$(if $(glib_resources_namespace),,$(error Need to define glib_resources_namespace))
+
+resources_xml=$(addprefix $(srcdir)/,$(glib_resources_xml))
+resources_srcdir=$(dir $(resources_xml))
+
+DISTCLEANFILES += $(glib_resources_h) $(glib_resources_c)
+BUILT_SOURCES += $(glib_resources_h) $(glib_resources_c)
+CLEANFILES += stamp-resources $(glib_resources_c) $(glib_resources_h)
+EXTRA_DIST += \
+       $(glib_resources_xml) \
+       $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(resources_srcdir) --generate-dependencies 
$(resources_xml)) \
+       $(NULL)
+
+stamp-resources: $(glib_resources_c) $(resources_xml)
+       $(AM_V_GEN)$(GLIB_COMPILE_RESOURCES) \
+               --target=xgen-gr.h \
+               --sourcedir=$(resources_srcdir) \
+               --generate-header \
+               --c-name $(glib_resources_namespace) \
+               $(resources_xml) \
+       && (cmp -s xgen-gr.h $(glib_resources_h) || cp -f xgen-gr.h $(glib_resources_h)) \
+       && rm -f xgen-gr.h \
+       && echo timestamp > $(@F)
+
+$(glib_resources_h): stamp-resources
+       @true
+
+$(glib_resources_c): $(resources_xml) $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(resources_srcdir) 
--generate-dependencies $(resources_xml))
+       $(AM_V_GEN)$(GLIB_COMPILE_RESOURCES) \
+               --target=xgen-gr.c \
+               --sourcedir=$(resources_srcdir) \
+               --generate-source \
+               --c-name $(glib_resources_namespace) \
+               $(resources_xml) \
+       && (cmp -s xgen-gr.c $(glib_resources_c) || cp -f xgen-gr.c $(glib_resources_c)) \
+       && rm -f xgen-gr.c
diff --git a/help/C/index.page b/help/C/index.page
new file mode 100644
index 0000000..56596f1
--- /dev/null
+++ b/help/C/index.page
@@ -0,0 +1,18 @@
+<page xmlns="http://projectmallard.org/1.0/";
+      xmlns:its="http://www.w3.org/2005/11/its";
+      type="guide"
+      id="index">
+
+  <info>
+    <revision pkgversion="3.20" date="2016-01-23" status="stub" />
+
+    <include href="legal.xml" xmlns="http://www.w3.org/2001/XInclude"/>
+  </info>
+
+  <title>Sysprof</title>
+
+  <section id="profiling" style="2column">
+    <title>Profiling</title>
+  </section>
+
+</page>
diff --git a/help/C/introduction.page b/help/C/introduction.page
new file mode 100644
index 0000000..3cf93b1
--- /dev/null
+++ b/help/C/introduction.page
@@ -0,0 +1,57 @@
+<page xmlns="http://projectmallard.org/1.0/";
+      xmlns:its="http://www.w3.org/2005/11/its";
+      type="topic"
+      id="introduction">
+
+  <info>
+    <link type="guide" xref="index"/>
+<!--
+    <link type="guide" xref="index#features"/>
+    <link type="seealso" xref="anotherpageid"/>
+-->
+    <revision pkgversion="3.20" date="2016-04-04" status="stub" />
+
+    <credit type="author">
+      <name>Christian Hergert</name>
+      <email its:translate="no">christian hergert me</email>
+      <years>2016</years>
+    </credit>
+ 
+    <include href="legal.xml" xmlns="http://www.w3.org/2001/XInclude"/>
+
+    <desc>Welcome to <app>Sysprof</app>!</desc>
+  </info>
+
+  <title>Introduction</title>
+
+  <p><app>Sysprof</app> is a system profiler for Linux that targets
+  the GNOME desktop.</p>
+
+  <section id="what-is-a-profiler">
+    <info>
+      <link type="guide" xref="index"/>
+      <desc>Differences between tracing and sampling</desc>
+    </info>
+    <title>What is a Profiler?</title>
+
+    <p>A profiler is an application that records information about an
+application or system while it runs. That information can be explored to
+gain insight into how the application could be changed to perform
+better.</p>
+
+    <p>Two common categories of software profilers exist, commonly referred
+to as either tracing or sampling profilers. What is meant by tracing
+profiler is that every function call executed by the program is known to the
+profiler. A sampling profiler works by inspecting the state of the
+program on a regular frequency and therefore does not see every function
+call executed by the program.</p>
+
+    <p>Both tracing and sampling profilers have their advantages. A
+notable advtantage of a sampling profiler is that the overhead is much
+less than that of a tracing profiler, making it easier to use for
+software that requires interactivity.</p>
+
+    <p><app>Sysprof</app> is a sampling profiler.</p>
+  </section>
+
+</page>
diff --git a/help/C/legal.xml b/help/C/legal.xml
new file mode 100644
index 0000000..42fd3db
--- /dev/null
+++ b/help/C/legal.xml
@@ -0,0 +1,12 @@
+<license xmlns="http://projectmallard.org/1.0/";
+         href="http://creativecommons.org/licenses/by-sa/4.0/";>
+
+  <p>This work is licensed under a
+  <link href="http://creativecommons.org/licenses/by-sa/4.0/";>Creative Commons
+  Attribution-ShareAlike 4.0 International</link> license.</p>
+
+  <p>As a special exception, the copyright holders give you permission to copy,
+  modify, and distribute the example code contained in this documentation under
+  the terms of your choosing, without restriction.</p>
+
+</license>
diff --git a/help/C/profiling.page b/help/C/profiling.page
new file mode 100644
index 0000000..4b0a666
--- /dev/null
+++ b/help/C/profiling.page
@@ -0,0 +1,140 @@
+<page xmlns="http://projectmallard.org/1.0/";
+      xmlns:its="http://www.w3.org/2005/11/its";
+      type="topic"
+      id="profiling">
+
+  <section id="system-profiling">
+    <info>
+      <link type="guide" xref="index#profiling"/>
+    </info>
+    <title>How to profile your system</title>
+    <p>When <app>Sysprof</app> profiles your system, it records stack
+information for all applications executing, including the Linux kernel. This
+can sometimes be confusing if you only want to look at a single process.  If
+your application does not interact much with the host system, you may have more
+success with <link href="profiling#new-process-profiling">profiling an existing
+process</link>.</p>
+
+    <p>To profile your entire system, ensure the target button is set to
+<em>All Processes</em> and click <em>Record</em>.</p>
+
+    <p>At this point, you may be asked to <em>authorize</em> access to
+profile the system. This is required as the Linux kernel's perf
+implementation requires root to perform whole-system profiling.</p>
+
+    <p>During the profiling session, you will see the number of
+seconds the profile has been active. Clicking the <em>Record</em>
+button again will stop the profiling session. Afterwhich, the callgraph
+will be displayed.</p>
+
+    <note>
+      <p>If you find that the <app>sysprof</app> application is showing up in
+your profiling callgraph, you might consider recording the profiling session
+with <cmd>sysprof-cli</cmd>. This is a command line program that will capture
+your profiling session to disk to be viewed at a later time.</p>
+    </note>
+
+    <p>See <link href="profiling#interpreting-results">interpreting
+results</link> for more guidance.</p>
+
+  </section>
+
+  <section id="existing-process-profiling">
+    <info>
+      <link type="guide" xref="index#profiling"/>
+    </info>
+    <title>Profile an existing process</title>
+    <p>With <app>Sysprof</app>, you can profile one or more existing
+processes on your system. First, select the <em>profiling target</em>
+button next to the <em>Record</em> button. Select <em>Existing Process</em>
+in the popover that is displayed. Next, select as many processes as you'd
+like to profile. Processes selected for profiling will have a checkmark
+next to their name.</p>
+
+    <p>After selecting your target processes, click the <em>Record</em>
+button to start profiling.</p>
+
+    <p>When you have completed, click the <em>Record</em> button again
+to stop profiling.</p>
+
+    <p>See <link href="profiling#interpreting-results">interpreting
+results</link> for more guidance.</p>
+
+  </section>
+
+  <section id="new-process-profiling">
+    <info>
+      <link type="guide" xref="index#profiling"/>
+    </info>
+    <title>Profile a new process</title>
+
+    <p>Often times, you may need to spawn a new process to profile.
+First, select the <em>profiling target</em> button next to the
+<em>Record</em> button. Next, select <em>New Process</em> and fill
+out the necessary information to spawn the process.</p>
+
+    <note>
+      <p>If you are spawning a process that requires access to your current
+display, such as a GTK+ application, you will want to make sure <em>Inherit
+current environment</em> is set.</p>
+    </note>
+
+  </section>
+
+  <section id="sysprof-cli">
+    <info>
+      <link type="guide" xref="index#profiling"/>
+    </info>
+    <title>Profiling with the sysprof-cli command line tool</title>
+
+    <p>For minimal overhead, you might consider using the <cmd>sysprof-cli</cmd>
+command line tool. When run without any arguments, it will record your entire
+system and save the output to <file>capture.syscap</file>. This file can be
+opened with the <app>Sysprof</app> application to view the callgraph.</p>
+
+    <p>You can also attach to an existing process using
+<cmd>sysprof-cli -p pid</cmd>.</p>
+
+    <p>If you would like to spawn a new process, use <cmd>sysprof-cli -c
+'command'</cmd> to specify a command to be launched. The command will inherit
+the current environment.</p>
+
+  </section>
+
+  <section id="interpreting-results">
+    <info>
+      <link type="guide" xref="index#profiling"/>
+    </info>
+    <title>Interpreting results</title>
+
+    <p>The profiling results in <app>Sysprof</app> are split into three
+sections. On the top left is a list of all the functions profiled. They
+are sorted by how often they were called during the sampling frequency.</p>
+
+    <note>
+      <p>It is important to note that the amount of time spent in each function
+is not captured. That would require a tracing profiler to accurately record.
+The percentage is calculated by determining how often that function showed
+up in the current stacktrace when a sample was recorded.</p>
+    </note>
+
+    <p>After selecting a function from the functions list, all of the recorded
+callers of that function will be displayed on the bottom left. They are also
+sorted by the percentage of samples that included that function in the
+stacktrace.</p>
+
+    <p>On the right, are all of the decendants of a selected function. You can
+select a function either from the functions list, or the callers list.</p>
+
+    <p>You can jump into a function by activating a row in the tree of descendants
+with a double-click or by pressing <key>Enter</key> or <key>Spacebar</key>.</p>
+
+    <note>
+      <p>If you see <em>- - kernel - -</em> in your results, that means that the
+application transitioned into or from the Linux kernel. There can be many reasons
+for this such as a <em>syscall</em> or <em>signal</em>.</p>
+    </note>
+
+  </section>
+
+</page>
diff --git a/help/Makefile.am b/help/Makefile.am
new file mode 100644
index 0000000..292360e
--- /dev/null
+++ b/help/Makefile.am
@@ -0,0 +1,18 @@
+ YELP_HELP_RULES@
+
+HELP_ID = sysprof
+
+# Media files
+HELP_MEDIA =
+
+# Help pages
+HELP_FILES = \
+       index.page \
+       introduction.page \
+       profiling.page \
+       legal.xml
+
+# Translated languages
+HELP_LINGUAS = 
+
+-include $(top_srcdir)/git.mk
diff --git a/lib/Makefile.am b/lib/Makefile.am
new file mode 100644
index 0000000..ef78257
--- /dev/null
+++ b/lib/Makefile.am
@@ -0,0 +1,128 @@
+EXTRA_DIST =
+CLEANFILES =
+DISTCLEANFILES =
+BUILT_SOURCES =
+
+lib_LTLIBRARIES = libsysprof- API_VERSION@.la
+
+nodist_libsysprof_ API_VERSION@_la_SOURCES = \
+       sp-resources.c \
+       sp-resources.h
+
+headersdir = $(includedir)/sysprof- API_VERSION@
+headers_DATA = \
+       sysprof.h \
+       sysprof-version.h \
+       sp-address.h \
+       sp-callgraph-profile.h \
+       sp-callgraph-view.h \
+       sp-capture-reader.h \
+       sp-capture-writer.h \
+       sp-capture-types.h \
+       sp-cell-renderer-percent.h \
+       sp-clock.h \
+       sp-elf-symbol-resolver.h \
+       sp-empty-state-view.h \
+       sp-failed-state-view.h \
+       sp-error.h \
+       sp-gjs-source.h \
+       sp-jitmap-symbol-resolver.h \
+       sp-kernel-symbol.h \
+       sp-kernel-symbol-resolver.h \
+       sp-map-lookaside.h \
+       sp-model-filter.h \
+       sp-perf-source.h \
+       sp-proc-source.h \
+       sp-process-model.h \
+       sp-process-model-item.h \
+       sp-process-model-row.h \
+       sp-profile.h \
+       sp-profiler.h \
+       sp-profiler-menu-button.h \
+       sp-recording-state-view.h \
+       sp-source.h \
+       sp-symbol-resolver.h \
+       $(NULL)
+
+libsysprof_ API_VERSION@_la_SOURCES = \
+       $(headers_DATA) \
+       sp-address.c \
+       sp-callgraph-profile.c \
+       sp-callgraph-profile-private.h \
+       sp-callgraph-view.c \
+       sp-capture-reader.c \
+       sp-capture-writer.c \
+       sp-cell-renderer-percent.c \
+       sp-clock.c \
+       sp-elf-symbol-resolver.c \
+       sp-empty-state-view.c \
+       sp-failed-state-view.c \
+       sp-error.c \
+       sp-gjs-source.c \
+       sp-jitmap-symbol-resolver.c \
+       sp-kernel-symbol.c \
+       sp-kernel-symbol-resolver.c \
+       sp-line-reader.c \
+       sp-line-reader.h \
+       sp-map-lookaside.c \
+       sp-model-filter.c \
+       sp-perf-counter.c \
+       sp-perf-counter.h \
+       sp-perf-source.c \
+       sp-proc-source.c \
+       sp-process-model.c \
+       sp-process-model-item.c \
+       sp-process-model-row.c \
+       sp-profile.c \
+       sp-profiler.c \
+       sp-profiler-menu-button.c \
+       sp-recording-state-view.c \
+       sp-scrolled-window.c \
+       sp-scrolled-window.h \
+       sp-source.c \
+       sp-symbol-resolver.c \
+       util/binfile.c \
+       util/binfile.h \
+       util/demangle.cpp \
+       util/demangle.h \
+       util/elfparser.c \
+       util/elfparser.h \
+       util/stackstash.c \
+       util/stackstash.h \
+       util/util.h \
+       $(NULL)
+
+
+libsysprof_ API_VERSION@_la_CFLAGS = \
+       -I$(srcdir)/util \
+       $(SYSPROF_CFLAGS) \
+       $(WARN_CFLAGS) \
+       $(NULL)
+
+libsysprof_ API_VERSION@_la_CXXFLAGS = \
+       -I$(srcdir)/util \
+       $(SYSPROF_CFLAGS) \
+       $(WARN_CXXFLAGS) \
+       $(NULL)
+
+if ENABLE_SYSPROFD
+libsysprof_ API_VERSION@_la_CFLAGS += -DENABLE_SYSPROFD
+endif
+
+libsysprof_ API_VERSION@_la_LIBADD = \
+       $(SYSPROF_LIBS) \
+       $(NULL)
+
+libsysprof_ API_VERSION@_la_LDFLAGS = \
+       $(WARN_LDFLAGS) \
+       $(NULL)
+
+
+glib_resources_xml = resources/libsysprof.gresource.xml
+glib_resources_c = sp-resources.c
+glib_resources_h = sp-resources.h
+glib_resources_namespace = sp
+include $(top_srcdir)/gresources.mk
+
+
+-include $(top_srcdir)/git.mk
diff --git a/lib/resources/libsysprof.gresource.xml b/lib/resources/libsysprof.gresource.xml
new file mode 100644
index 0000000..3beeed9
--- /dev/null
+++ b/lib/resources/libsysprof.gresource.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<gresources>
+  <gresource prefix="/org/gnome/sysprof">
+    <file compressed="true">ui/sp-callgraph-view.ui</file>
+    <file compressed="true">ui/sp-empty-state-view.ui</file>
+    <file compressed="true">ui/sp-failed-state-view.ui</file>
+    <file compressed="true">ui/sp-process-model-row.ui</file>
+    <file compressed="true">ui/sp-profiler-menu-button.ui</file>
+    <file compressed="true">ui/sp-recording-state-view.ui</file>
+  </gresource>
+</gresources>
diff --git a/lib/resources/ui/sp-callgraph-view.ui b/lib/resources/ui/sp-callgraph-view.ui
new file mode 100644
index 0000000..2bce8d3
--- /dev/null
+++ b/lib/resources/ui/sp-callgraph-view.ui
@@ -0,0 +1,198 @@
+<interface>
+  <template class="SpCallgraphView" parent="GtkBin">
+    <child>
+      <object class="GtkPaned">
+        <property name="orientation">horizontal</property>
+        <property name="position">450</property>
+        <property name="visible">true</property>
+        <child>
+          <object class="GtkPaned">
+            <property name="orientation">vertical</property>
+            <property name="visible">true</property>
+            <child>
+              <object class="GtkScrolledWindow">
+                <property name="visible">true</property>
+                <child>
+                  <object class="GtkTreeView" id="functions_view">
+                    <property name="fixed-height-mode">true</property>
+                    <property name="visible">true</property>
+                    <child>
+                      <object class="GtkTreeViewColumn" id="function_name_column">
+                        <property name="expand">true</property>
+                        <property name="sizing">fixed</property>
+                        <property name="sort-column-id">0</property>
+                        <property name="title" translatable="yes">Functions</property>
+                        <child>
+                          <object class="GtkCellRendererText">
+                            <property name="ellipsize">middle</property>
+                          </object>
+                          <attributes>
+                            <attribute name="text">0</attribute>
+                          </attributes>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkTreeViewColumn" id="function_self_column">
+                        <property name="expand">false</property>
+                        <property name="sizing">fixed</property>
+                        <property name="sort-column-id">1</property>
+                        <property name="title" translatable="yes">Self</property>
+                        <child>
+                          <object class="SpCellRendererPercent">
+                            <property name="xpad">6</property>
+                          </object>
+                          <attributes>
+                            <attribute name="percent">1</attribute>
+                          </attributes>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkTreeViewColumn" id="function_total_column">
+                        <property name="expand">false</property>
+                        <property name="sizing">fixed</property>
+                        <property name="sort-column-id">2</property>
+                        <property name="title" translatable="yes">Total</property>
+                        <child>
+                          <object class="SpCellRendererPercent">
+                            <property name="xpad">6</property>
+                          </object>
+                          <attributes>
+                            <attribute name="percent">2</attribute>
+                          </attributes>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="resize">true</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkScrolledWindow">
+                <property name="visible">true</property>
+                <child>
+                  <object class="GtkTreeView" id="callers_view">
+                    <property name="visible">true</property>
+                    <child>
+                      <object class="GtkTreeViewColumn" id="callers_name_column">
+                        <property name="expand">true</property>
+                        <property name="sizing">fixed</property>
+                        <property name="sort-column-id">0</property>
+                        <property name="title" translatable="yes">Callers</property>
+                        <child>
+                          <object class="GtkCellRendererText">
+                            <property name="ellipsize">middle</property>
+                          </object>
+                          <attributes>
+                            <attribute name="text">0</attribute>
+                          </attributes>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkTreeViewColumn" id="callers_self_column">
+                        <property name="expand">false</property>
+                        <property name="sizing">fixed</property>
+                        <property name="sort-column-id">1</property>
+                        <property name="title" translatable="yes">Self</property>
+                        <child>
+                          <object class="SpCellRendererPercent">
+                            <property name="xpad">6</property>
+                          </object>
+                          <attributes>
+                            <attribute name="percent">1</attribute>
+                          </attributes>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkTreeViewColumn" id="callers_total_column">
+                        <property name="expand">false</property>
+                        <property name="sizing">fixed</property>
+                        <property name="sort-column-id">2</property>
+                        <property name="title" translatable="yes">Total</property>
+                        <child>
+                          <object class="SpCellRendererPercent">
+                            <property name="xpad">6</property>
+                          </object>
+                          <attributes>
+                            <attribute name="percent">2</attribute>
+                          </attributes>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="resize">true</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow">
+            <property name="visible">true</property>
+            <child>
+              <object class="GtkTreeView" id="descendants_view">
+                <property name="visible">true</property>
+                <child>
+                  <object class="GtkTreeViewColumn" id="descendants_name_column">
+                    <property name="expand">true</property>
+                    <property name="sizing">fixed</property>
+                    <property name="sort-column-id">0</property>
+                    <property name="title" translatable="yes">Descendants</property>
+                    <child>
+                      <object class="GtkCellRendererText">
+                        <property name="ellipsize">middle</property>
+                      </object>
+                      <attributes>
+                        <attribute name="text">0</attribute>
+                      </attributes>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkTreeViewColumn" id="descendants_self_column">
+                    <property name="expand">false</property>
+                    <property name="sizing">fixed</property>
+                    <property name="sort-column-id">1</property>
+                    <property name="title" translatable="yes">Self</property>
+                    <child>
+                      <object class="SpCellRendererPercent">
+                        <property name="xpad">6</property>
+                      </object>
+                      <attributes>
+                        <attribute name="percent">1</attribute>
+                      </attributes>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkTreeViewColumn" id="descendants_total_column">
+                    <property name="expand">false</property>
+                    <property name="sizing">fixed</property>
+                    <property name="sort-column-id">2</property>
+                    <property name="title" translatable="yes">Cumulative</property>
+                    <child>
+                      <object class="SpCellRendererPercent">
+                        <property name="xpad">6</property>
+                      </object>
+                      <attributes>
+                        <attribute name="percent">2</attribute>
+                      </attributes>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/lib/resources/ui/sp-empty-state-view.ui b/lib/resources/ui/sp-empty-state-view.ui
new file mode 100644
index 0000000..fd61eb4
--- /dev/null
+++ b/lib/resources/ui/sp-empty-state-view.ui
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="SpEmptyStateView" parent="GtkBin">
+    <child>
+      <object class="GtkBox">
+        <property name="border-width">36</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <property name="visible">true</property>
+        <child type="center">
+          <object class="GtkImage">
+            <property name="icon-name">sysprof-symbolic</property>
+            <property name="pixel-size">256</property>
+            <property name="visible">true</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+          </object>
+        </child>
+        <child>
+          <object class="GtkLabel">
+            <property name="label" translatable="yes">Welcome to Sysprof</property>
+            <property name="visible">true</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+            <attributes>
+              <attribute name="scale" value="2"/>
+              <attribute name="weight" value="bold"/>
+            </attributes>
+          </object>
+          <packing>
+            <property name="pack-type">end</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel">
+            <property name="label" translatable="yes">Start profiling your system with the 
&lt;b&gt;Record&lt;/b&gt; button above</property>
+            <property name="use-markup">true</property>
+            <property name="visible">true</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+          </object>
+          <packing>
+            <property name="pack-type">end</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel">
+            <property name="vexpand">true</property>
+            <property name="visible">true</property>
+          </object>
+          <packing>
+            <property name="position">0</property>
+            <property name="pack-type">end</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/lib/resources/ui/sp-failed-state-view.ui b/lib/resources/ui/sp-failed-state-view.ui
new file mode 100644
index 0000000..ba2f17e
--- /dev/null
+++ b/lib/resources/ui/sp-failed-state-view.ui
@@ -0,0 +1,64 @@
+<?xml version="1.0"?>
+<interface>
+  <template class="SpFailedStateView" parent="GtkBin">
+    <child>
+      <object class="GtkBox">
+        <property name="border-width">36</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <property name="visible">true</property>
+        <child type="center">
+          <object class="GtkImage">
+            <property name="icon-name">computer-fail-symbolic</property>
+            <property name="pixel-size">256</property>
+            <property name="visible">true</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+          </object>
+        </child>
+        <child>
+          <object class="GtkLabel">
+            <property name="label" translatable="yes">Ouch, that hurt!</property>
+            <property name="visible">true</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+            <attributes>
+              <attribute name="scale" value="2"/>
+              <attribute name="weight" value="bold"/>
+            </attributes>
+          </object>
+          <packing>
+            <property name="pack-type">end</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel">
+            <property name="label" translatable="yes">Something unexpectedly went wrong while trying to 
profile your system.</property>
+            <property name="use-markup">true</property>
+            <property name="visible">true</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+          </object>
+          <packing>
+            <property name="pack-type">end</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel">
+            <property name="vexpand">true</property>
+            <property name="visible">true</property>
+          </object>
+          <packing>
+            <property name="position">0</property>
+            <property name="pack-type">end</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/lib/resources/ui/sp-process-model-row.ui b/lib/resources/ui/sp-process-model-row.ui
new file mode 100644
index 0000000..8f65dd8
--- /dev/null
+++ b/lib/resources/ui/sp-process-model-row.ui
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<interface>
+  <template class="SpProcessModelRow" parent="GtkListBoxRow">
+    <child>
+      <object class="GtkBox">
+        <property name="visible">true</property>
+        <property name="spacing">6</property>
+        <child>
+          <object class="GtkImage" id="image">
+            <!-- Todo -->
+          </object>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label">
+            <property name="hexpand">false</property>
+            <property name="visible">true</property>
+            <property name="ellipsize">middle</property>
+            <property name="xalign">0.0</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkImage" id="check">
+            <property name="hexpand">false</property>
+            <property name="icon-name">object-select-symbolic</property>
+            <property name="visible">false</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkLabel" id="pid">
+            <property name="hexpand">true</property>
+            <property name="visible">true</property>
+            <property name="xalign">1.0</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/lib/resources/ui/sp-profiler-menu-button.ui b/lib/resources/ui/sp-profiler-menu-button.ui
new file mode 100644
index 0000000..bbb8d36
--- /dev/null
+++ b/lib/resources/ui/sp-profiler-menu-button.ui
@@ -0,0 +1,221 @@
+<?xml version="1.0"?>
+<interface>
+  <template class="SpProfilerMenuButton" parent="GtkMenuButton">
+    <property name="popover">popover</property>
+    <property name="width-request">150</property>
+    <child>
+      <object class="GtkBox">
+        <property name="orientation">horizontal</property>
+        <property name="spacing">6</property>
+        <property name="visible">true</property>
+        <child>
+          <object class="GtkLabel" id="label">
+            <property name="ellipsize">end</property>
+            <property name="hexpand">true</property>
+            <property name="visible">true</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkImage">
+            <property name="icon-name">pan-down-symbolic</property>
+            <property name="visible">true</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+  <object class="SpProcessModel" id="process_model">
+  </object>
+  <object class="GtkPopover" id="popover">
+    <child>
+      <object class="GtkBox">
+        <property name="orientation">vertical</property>
+        <property name="visible">true</property>
+        <child>
+          <object class="GtkStackSwitcher">
+            <property name="border-width">6</property>
+            <property name="halign">center</property>
+            <property name="orientation">horizontal</property>
+            <property name="stack">stack</property>
+            <property name="visible">true</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkBox">
+            <property name="visible">true</property>
+            <property name="hexpand">true</property>
+            <property name="margin">10</property>
+            <child type="center">
+              <object class="GtkLabel">
+                <property name="hexpand">true</property>
+                <property name="label" translatable="yes">Profile my _entire system</property>
+                <property name="use-underline">true</property>
+                <property name="visible">true</property>
+                <property name="xalign">1</property>
+                <property name="mnemonic-widget">whole_system_switch</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkSwitch" id="whole_system_switch">
+                <property name="visible">true</property>
+              </object>
+              <packing>
+                <property name="pack-type">end</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkStack" id="stack">
+            <property name="hhomogeneous">true</property>
+            <property name="vhomogeneous">false</property>
+            <property name="interpolate-size">true</property>
+            <property name="visible">true</property>
+            <property name="border-width">10</property>
+            <child>
+              <object class="GtkBox" id="processes_box">
+                <property name="orientation">vertical</property>
+                <property name="visible">true</property>
+                <style>
+                  <class name="linked"/>
+                </style>
+                <child>
+                  <object class="GtkEntry" id="process_filter_entry">
+                    <property name="placeholder-text" translatable="yes">Search</property>
+                    <property name="visible">true</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="SpScrolledWindow">
+                    <property name="min-content-width">100</property>
+                    <property name="max-content-width">400</property>
+                    <property name="max-content-height">450</property>
+                    <property name="shadow-type">in</property>
+                    <property name="visible">true</property>
+                    <child>
+                      <object class="GtkListBox" id="process_list_box">
+                        <property name="visible">true</property>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="name">existing</property>
+                <property name="title" translatable="yes">Existing Process</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkBox">
+                <property name="orientation">vertical</property>
+                <property name="spacing">12</property>
+                <property name="visible">true</property>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="label" translatable="yes">Command Line</property>
+                    <property name="visible">true</property>
+                    <property name="xalign">0.0</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                    <attributes>
+                      <attribute name="weight" value="bold"/>
+                    </attributes>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkEntry" id="spawn_entry">
+                    <property name="visible">true</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="label" translatable="yes">Environment</property>
+                    <property name="visible">true</property>
+                    <property name="xalign">0.0</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                    <attributes>
+                      <attribute name="weight" value="bold"/>
+                    </attributes>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="inherit_environ">
+                    <property name="active">true</property>
+                    <property name="label" translatable="yes">Inherit current environment</property>
+                    <property name="visible">true</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="SpScrolledWindow">
+                    <property name="shadow-type">in</property>
+                    <property name="min-content-height">100</property>
+                    <property name="max-content-height">400</property>
+                    <property name="visible">true</property>
+                    <child>
+                      <object class="GtkTreeView" id="env_tree_view">
+                        <property name="model">environment_model</property>
+                        <property name="visible">true</property>
+                        <child>
+                          <object class="GtkTreeViewColumn" id="env_key_column">
+                            <property name="expand">true</property>
+                            <property name="resizable">true</property>
+                            <property name="title" translatable="yes">Key</property>
+                            <child>
+                              <object class="GtkCellRendererText" id="key_cell">
+                                <property name="editable">true</property>
+                              </object>
+                              <attributes>
+                                <attribute name="text">0</attribute>
+                              </attributes>
+                            </child>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkTreeViewColumn" id="env_value_column">
+                            <property name="expand">true</property>
+                            <property name="resizable">true</property>
+                            <property name="title" translatable="yes">Value</property>
+                            <child>
+                              <object class="GtkCellRendererText" id="value_cell">
+                                <property name="editable">true</property>
+                              </object>
+                              <attributes>
+                                <attribute name="text">1</attribute>
+                              </attributes>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="name">spawn</property>
+                <property name="title" translatable="yes">New Process</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
+  <object class="GtkListStore" id="environment_model">
+    <columns>
+      <column type="gchararray"/>
+      <column type="gchararray"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0"></col>
+        <col id="1"></col>
+      </row>
+    </data>
+  </object>
+</interface>
diff --git a/lib/resources/ui/sp-recording-state-view.ui b/lib/resources/ui/sp-recording-state-view.ui
new file mode 100644
index 0000000..0e15477
--- /dev/null
+++ b/lib/resources/ui/sp-recording-state-view.ui
@@ -0,0 +1,64 @@
+<?xml version="1.0"?>
+<interface>
+  <template class="SpRecordingStateView" parent="GtkBin">
+    <child>
+      <object class="GtkBox">
+        <property name="border-width">36</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <property name="visible">true</property>
+        <child type="center">
+          <object class="GtkImage">
+            <property name="icon-name">sysprof-symbolic</property>
+            <property name="pixel-size">256</property>
+            <property name="visible">true</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+          </object>
+        </child>
+        <child>
+          <object class="GtkLabel" id="elapsed">
+            <property name="label" translatable="yes">00:00</property>
+            <property name="visible">true</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+            <attributes>
+              <attribute name="scale" value="4"/>
+              <attribute name="weight" value="bold"/>
+            </attributes>
+          </object>
+          <packing>
+            <property name="pack-type">end</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel">
+            <property name="label" translatable="yes">Did you know you can use &lt;a 
href="help:sysprof"&gt;sysprof-cli&lt;/a&gt; to record?</property>
+            <property name="use-markup">true</property>
+            <property name="visible">true</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+          </object>
+          <packing>
+            <property name="pack-type">end</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel">
+            <property name="vexpand">true</property>
+            <property name="visible">true</property>
+          </object>
+          <packing>
+            <property name="position">0</property>
+            <property name="pack-type">end</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/lib/sp-address.c b/lib/sp-address.c
new file mode 100644
index 0000000..b431235
--- /dev/null
+++ b/lib/sp-address.c
@@ -0,0 +1,91 @@
+/* sp-address.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#include <linux/perf_event.h>
+
+#include "sp-address.h"
+
+gboolean
+sp_address_is_context_switch (SpAddress         address,
+                              SpAddressContext *context)
+{
+  SpAddressContext dummy;
+
+  if (context == NULL)
+    context = &dummy;
+
+  switch (address)
+    {
+    case PERF_CONTEXT_HV:
+      *context = SP_ADDRESS_CONTEXT_HYPERVISOR;
+      return TRUE;
+
+    case PERF_CONTEXT_KERNEL:
+      *context = SP_ADDRESS_CONTEXT_KERNEL;
+      return TRUE;
+
+    case PERF_CONTEXT_USER:
+      *context = SP_ADDRESS_CONTEXT_USER;
+      return TRUE;
+
+    case PERF_CONTEXT_GUEST:
+      *context = SP_ADDRESS_CONTEXT_GUEST;
+      return TRUE;
+
+    case PERF_CONTEXT_GUEST_KERNEL:
+      *context = SP_ADDRESS_CONTEXT_GUEST_KERNEL;
+      return TRUE;
+
+    case PERF_CONTEXT_GUEST_USER:
+      *context = SP_ADDRESS_CONTEXT_GUEST_USER;
+      return TRUE;
+
+    default:
+      *context = SP_ADDRESS_CONTEXT_NONE;
+      return FALSE;
+    }
+}
+
+const gchar *
+sp_address_context_to_string (SpAddressContext context)
+{
+  switch (context)
+    {
+      case SP_ADDRESS_CONTEXT_HYPERVISOR:
+        return "- - hypervisor - -";
+
+      case SP_ADDRESS_CONTEXT_KERNEL:
+        return "- - kernel - -";
+
+      case SP_ADDRESS_CONTEXT_USER:
+        return "- - user - -";
+
+      case SP_ADDRESS_CONTEXT_GUEST:
+        return "- - guest - -";
+
+      case SP_ADDRESS_CONTEXT_GUEST_KERNEL:
+        return "- - guest kernel - -";
+
+      case SP_ADDRESS_CONTEXT_GUEST_USER:
+        return "- - guest user - -";
+
+      case SP_ADDRESS_CONTEXT_NONE:
+      default:
+        return "- - unknown - -";
+    }
+}
diff --git a/lib/sp-address.h b/lib/sp-address.h
new file mode 100644
index 0000000..8234842
--- /dev/null
+++ b/lib/sp-address.h
@@ -0,0 +1,59 @@
+/* sp-address.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_ADDRESS_H
+#define SP_ADDRESS_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef guint64 SpAddress;
+
+G_STATIC_ASSERT (sizeof (SpAddress) >= sizeof (gpointer));
+
+typedef enum
+{
+  SP_ADDRESS_CONTEXT_NONE = 0,
+  SP_ADDRESS_CONTEXT_HYPERVISOR,
+  SP_ADDRESS_CONTEXT_KERNEL,
+  SP_ADDRESS_CONTEXT_USER,
+  SP_ADDRESS_CONTEXT_GUEST,
+  SP_ADDRESS_CONTEXT_GUEST_KERNEL,
+  SP_ADDRESS_CONTEXT_GUEST_USER,
+} SpAddressContext;
+
+gboolean     sp_address_is_context_switch (SpAddress         address,
+                                           SpAddressContext *context);
+const gchar *sp_address_context_to_string (SpAddressContext  context);
+
+static inline gint
+sp_address_compare (SpAddress a,
+                    SpAddress b)
+{
+  if (a < b)
+    return -1;
+  else if (a == b)
+    return 0;
+  else
+    return 1;
+}
+
+G_END_DECLS
+
+#endif /* SP_ADDRESS_H */
diff --git a/lib/sp-callgraph-profile-private.h b/lib/sp-callgraph-profile-private.h
new file mode 100644
index 0000000..f7955c1
--- /dev/null
+++ b/lib/sp-callgraph-profile-private.h
@@ -0,0 +1,31 @@
+/* sp-callgraph-profile-private.h
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_CALLGRAPH_PROFILE_PRIVATE_H
+#define SP_CALLGRAPH_PROFILE_PRIVATE_H
+
+#include "sp-callgraph-profile.h"
+#include "stackstash.h"
+
+G_BEGIN_DECLS
+
+StackStash *sp_callgraph_profile_get_stash (SpCallgraphProfile *self);
+
+G_END_DECLS
+
+#endif /* SP_CALLGRAPH_PROFILE_PRIVATE_H */
diff --git a/lib/sp-callgraph-profile.c b/lib/sp-callgraph-profile.c
new file mode 100644
index 0000000..996c53e
--- /dev/null
+++ b/lib/sp-callgraph-profile.c
@@ -0,0 +1,376 @@
+/* sp-callgraph-profile.c
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+/* Sysprof -- Sampling, systemwide CPU profiler
+ * Copyright 2009-2012 Soeren Sandmann and others
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <glib/gi18n.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "sp-address.h"
+#include "sp-callgraph-profile.h"
+#include "sp-callgraph-profile-private.h"
+#include "sp-capture-reader.h"
+#include "sp-elf-symbol-resolver.h"
+#include "sp-jitmap-symbol-resolver.h"
+#include "sp-map-lookaside.h"
+#include "sp-kernel-symbol-resolver.h"
+
+#include "stackstash.h"
+
+struct _SpCallgraphProfile
+{
+  GObject          parent_instance;
+
+  SpCaptureReader *reader;
+  GStringChunk    *symbols;
+  StackStash      *stash;
+  GHashTable      *tags;
+};
+
+static void profile_iface_init (SpProfileInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (SpCallgraphProfile, sp_callgraph_profile, G_TYPE_OBJECT, 0,
+                        G_IMPLEMENT_INTERFACE (SP_TYPE_PROFILE, profile_iface_init))
+
+SpProfile *
+sp_callgraph_profile_new (void)
+{
+  return g_object_new (SP_TYPE_CALLGRAPH_PROFILE, NULL);
+}
+
+static void
+sp_callgraph_profile_finalize (GObject *object)
+{
+  SpCallgraphProfile *self = (SpCallgraphProfile *)object;
+
+  g_clear_pointer (&self->symbols, g_string_chunk_free);
+  g_clear_pointer (&self->stash, stack_stash_unref);
+  g_clear_pointer (&self->reader, sp_capture_reader_unref);
+  g_clear_pointer (&self->tags, g_hash_table_unref);
+
+  G_OBJECT_CLASS (sp_callgraph_profile_parent_class)->finalize (object);
+}
+
+static void
+sp_callgraph_profile_class_init (SpCallgraphProfileClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = sp_callgraph_profile_finalize;
+}
+
+static void
+sp_callgraph_profile_init (SpCallgraphProfile *self)
+{
+  self->symbols = g_string_chunk_new (getpagesize ());
+  self->tags = g_hash_table_new (g_str_hash, g_str_equal);
+}
+
+static void
+sp_callgraph_profile_set_reader (SpProfile       *profile,
+                                 SpCaptureReader *reader)
+{
+  SpCallgraphProfile *self = (SpCallgraphProfile *)profile;
+
+  g_assert (SP_IS_CALLGRAPH_PROFILE (self));
+  g_assert (reader != NULL);
+
+  g_clear_pointer (&self->reader, sp_capture_reader_unref);
+  self->reader = sp_capture_reader_ref (reader);
+}
+
+static const gchar *
+sp_callgraph_profile_intern_string_take (SpCallgraphProfile *self,
+                                         gchar              *str)
+{
+  const gchar *ret;
+
+  g_assert (SP_IS_CALLGRAPH_PROFILE (self));
+  g_assert (str != NULL);
+
+  ret = g_string_chunk_insert_const (self->symbols, str);
+  g_free (str);
+  return ret;
+}
+
+static const gchar *
+sp_callgraph_profile_intern_string (SpCallgraphProfile *self,
+                                    const gchar        *str)
+{
+  g_assert (SP_IS_CALLGRAPH_PROFILE (self));
+  g_assert (str != NULL);
+
+  return g_string_chunk_insert_const (self->symbols, str);
+}
+
+static void
+sp_callgraph_profile_generate_worker (GTask        *task,
+                                      gpointer      source_object,
+                                      gpointer      task_data,
+                                      GCancellable *cancellable)
+{
+  SpCallgraphProfile *self = source_object;
+  SpCaptureReader *reader = task_data;
+  g_autoptr(GArray) resolved = NULL;
+  g_autoptr(GHashTable) maps_by_pid = NULL;
+  g_autoptr(GHashTable) cmdlines = NULL;
+  g_autoptr(GPtrArray) resolvers = NULL;
+  SpCaptureFrameType type;
+  StackStash *stash;
+  StackStash *resolved_stash;
+  gboolean ret = FALSE;
+  guint j;
+
+  g_assert (G_IS_TASK (task));
+  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  maps_by_pid = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)sp_map_lookaside_free);
+  cmdlines = g_hash_table_new (NULL, NULL);
+
+  stash = stack_stash_new (NULL);
+  resolved_stash = stack_stash_new (NULL);
+
+  resolvers = g_ptr_array_new_with_free_func (g_object_unref);
+  g_ptr_array_add (resolvers, sp_kernel_symbol_resolver_new ());
+  g_ptr_array_add (resolvers, sp_elf_symbol_resolver_new ());
+  g_ptr_array_add (resolvers, sp_jitmap_symbol_resolver_new ());
+
+  for (j = 0; j < resolvers->len; j++)
+    {
+      SpSymbolResolver *resolver = g_ptr_array_index (resolvers, j);
+
+      sp_capture_reader_reset (reader);
+      sp_symbol_resolver_load (resolver, reader);
+    }
+
+  sp_capture_reader_reset (reader);
+
+  /*
+   * The resolved pointer array is where we stash the names for the
+   * instruction pointers to pass to the stash stack. All the strings
+   * need to be deduplicated so that pointer comparison works as if we
+   * did instruction-pointer comparison.
+   */
+  resolved = g_array_new (FALSE, TRUE, sizeof (guint64));
+
+  while (sp_capture_reader_peek_type (reader, &type))
+    {
+      const SpCaptureProcess *pr;
+      const gchar *cmdline;
+
+      if (type != SP_CAPTURE_FRAME_PROCESS)
+        {
+          if (!sp_capture_reader_skip (reader))
+            goto failure;
+          continue;
+        }
+
+      if (NULL == (pr = sp_capture_reader_read_process (reader)))
+        goto failure;
+
+      cmdline = g_strdup_printf ("[%s]", pr->cmdline);
+      g_hash_table_insert (cmdlines,
+                           GINT_TO_POINTER (pr->frame.pid),
+                           (gchar *)sp_callgraph_profile_intern_string (self, cmdline));
+    }
+
+  sp_capture_reader_reset (reader);
+
+  /*
+   * Walk through all of the sample events and resolve instruction-pointers
+   * to symbol names by loading the particular map and extracting the symbol
+   * name. If we wanted to support dynamic systems, we'd want to extend this
+   * to parse information from captured data about the languages jit'd code.
+   */
+  while (sp_capture_reader_peek_type (reader, &type))
+    {
+      SpAddressContext last_context = SP_ADDRESS_CONTEXT_NONE;
+      const SpCaptureSample *sample;
+      StackNode *node;
+      StackNode *iter;
+      const gchar *cmdline;
+      guint len = 5;
+
+      if (type != SP_CAPTURE_FRAME_SAMPLE)
+        {
+          if (!sp_capture_reader_skip (reader))
+            goto failure;
+          continue;
+        }
+
+      if (NULL == (sample = sp_capture_reader_read_sample (reader)))
+        goto failure;
+
+      cmdline = g_hash_table_lookup (cmdlines, GINT_TO_POINTER (sample->frame.pid));
+
+      node = stack_stash_add_trace (stash, sample->addrs, sample->n_addrs, 1);
+
+      for (iter = node; iter != NULL; iter = iter->parent)
+        len++;
+
+      if (G_UNLIKELY (resolved->len < len))
+        g_array_set_size (resolved, len);
+
+      len = 0;
+
+      for (iter = node; iter != NULL; iter = iter->parent)
+        {
+          SpAddressContext context = SP_ADDRESS_CONTEXT_NONE;
+          SpAddress address = iter->data;
+          const gchar *symbol = NULL;
+
+          if (sp_address_is_context_switch (address, &context))
+            {
+              if (last_context)
+                symbol = sp_address_context_to_string (last_context);
+              else
+                symbol = NULL;
+
+              last_context = context;
+            }
+          else
+            {
+              for (j = 0; j < resolvers->len; j++)
+                {
+                  SpSymbolResolver *resolver = g_ptr_array_index (resolvers, j);
+                  GQuark tag = 0;
+                  gchar *str;
+
+                  str = sp_symbol_resolver_resolve (resolver,
+                                                    sample->frame.time,
+                                                    sample->frame.pid,
+                                                    address,
+                                                    &tag);
+
+                  if (str != NULL)
+                    {
+                      symbol = sp_callgraph_profile_intern_string_take (self, str);
+                      if (tag != 0)
+                        g_hash_table_insert (self->tags, (gchar *)symbol, GSIZE_TO_POINTER (tag));
+                      break;
+                    }
+                }
+            }
+
+          if (symbol != NULL)
+            g_array_index (resolved, SpAddress, len++) = POINTER_TO_U64 (symbol);
+        }
+
+      if (last_context && last_context != SP_ADDRESS_CONTEXT_USER)
+        {
+          /* Kernel threads do not have a user part, so we end up here
+           * without ever getting a user context. If this happens,
+           * add the '- - kernel - - ' name, so that kernel threads
+           * are properly blamed on the kernel
+           */
+          const gchar *name = sp_address_context_to_string (last_context);
+          g_array_index (resolved, SpAddress, len++) = POINTER_TO_U64 (name);
+        }
+
+      if (cmdline != NULL)
+        g_array_index (resolved, guint64, len++) = POINTER_TO_U64 (cmdline);
+
+      g_array_index (resolved, guint64, len++) = POINTER_TO_U64 ("[Everything]");
+
+      stack_stash_add_trace (resolved_stash, (SpAddress *)resolved->data, len, 1);
+    }
+
+  ret = TRUE;
+
+failure:
+
+  if (ret == FALSE)
+    g_task_return_new_error (task,
+                             G_IO_ERROR,
+                             G_IO_ERROR_FAILED,
+                             _("Sysprof was unable to generate a callgraph from the system capture."));
+  self->stash = resolved_stash;
+  stack_stash_unref (stash);
+  g_task_return_boolean (task, ret);
+}
+
+static void
+sp_callgraph_profile_generate (SpProfile           *profile,
+                               GCancellable        *cancellable,
+                               GAsyncReadyCallback  callback,
+                               gpointer             user_data)
+{
+  SpCallgraphProfile *self = (SpCallgraphProfile *)profile;
+
+  g_autoptr(GTask) task = NULL;
+
+  g_assert (SP_IS_CALLGRAPH_PROFILE (self));
+  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  task = g_task_new (self, cancellable, callback, user_data);
+  g_task_set_task_data (task, self->reader, NULL);
+  g_task_run_in_thread (task, sp_callgraph_profile_generate_worker);
+}
+
+static gboolean
+sp_callgraph_profile_generate_finish (SpProfile     *profile,
+                                      GAsyncResult  *result,
+                                      GError       **error)
+{
+  g_assert (SP_IS_CALLGRAPH_PROFILE (profile));
+  g_assert (G_IS_TASK (result));
+
+  return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+static void
+profile_iface_init (SpProfileInterface *iface)
+{
+  iface->generate = sp_callgraph_profile_generate;
+  iface->generate_finish = sp_callgraph_profile_generate_finish;
+  iface->set_reader = sp_callgraph_profile_set_reader;
+}
+
+StackStash *
+sp_callgraph_profile_get_stash (SpCallgraphProfile *self)
+{
+  g_return_val_if_fail (SP_IS_CALLGRAPH_PROFILE (self), NULL);
+
+  return self->stash;
+}
+
+GQuark
+sp_callgraph_profile_get_tag (SpCallgraphProfile *self,
+                              const gchar        *symbol)
+{
+  g_return_val_if_fail (SP_IS_CALLGRAPH_PROFILE (self), 0);
+
+  return GPOINTER_TO_SIZE (g_hash_table_lookup (self->tags, symbol));
+}
diff --git a/lib/sp-callgraph-profile.h b/lib/sp-callgraph-profile.h
new file mode 100644
index 0000000..59597bd
--- /dev/null
+++ b/lib/sp-callgraph-profile.h
@@ -0,0 +1,36 @@
+/* sp-callgraph-profile.h
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_CALLGRAPH_PROFILE_H
+#define SP_CALLGRAPH_PROFILE_H
+
+#include "sp-profile.h"
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_CALLGRAPH_PROFILE (sp_callgraph_profile_get_type())
+
+G_DECLARE_FINAL_TYPE (SpCallgraphProfile, sp_callgraph_profile, SP, CALLGRAPH_PROFILE, GObject)
+
+SpProfile *sp_callgraph_profile_new     (void);
+GQuark     sp_callgraph_profile_get_tag (SpCallgraphProfile *self,
+                                         const gchar        *symbol);
+
+G_END_DECLS
+
+#endif /* SP_CALLGRAPH_PROFILE_H */
diff --git a/lib/sp-callgraph-view.c b/lib/sp-callgraph-view.c
new file mode 100644
index 0000000..84323b5
--- /dev/null
+++ b/lib/sp-callgraph-view.c
@@ -0,0 +1,881 @@
+/* sp-callgraph-view.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+/* Sysprof -- Sampling, systemwide CPU profiler
+ * Copyright 2004, Red Hat, Inc.
+ * Copyright 2004, 2005, 2006, Soeren Sandmann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <glib/gi18n.h>
+
+#include "sp-callgraph-profile-private.h"
+#include "sp-callgraph-view.h"
+
+#include "util.h"
+
+typedef struct
+{
+  SpCallgraphProfile  *profile;
+
+  GtkTreeView         *callers_view;
+  GtkTreeView         *functions_view;
+  GtkTreeView         *descendants_view;
+  GtkTreeViewColumn   *descendants_name_column;
+
+  guint                profile_size;
+} SpCallgraphViewPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (SpCallgraphView, sp_callgraph_view, GTK_TYPE_BIN)
+
+enum {
+  PROP_0,
+  PROP_PROFILE,
+  N_PROPS
+};
+
+enum {
+  COLUMN_NAME,
+  COLUMN_SELF,
+  COLUMN_TOTAL,
+  COLUMN_POINTER,
+};
+
+
+static void sp_callgraph_view_update_descendants (SpCallgraphView *self,
+                                                  StackNode       *node);
+
+static GParamSpec *properties [N_PROPS];
+
+static guint
+sp_callgraph_view_get_profile_size (SpCallgraphView *self)
+{
+  SpCallgraphViewPrivate *priv = sp_callgraph_view_get_instance_private (self);
+  StackStash *stash;
+  StackNode *node;
+  guint size = 0;
+
+  g_assert (SP_IS_CALLGRAPH_VIEW (self));
+
+  if (priv->profile_size != 0)
+    return priv->profile_size;
+
+  if (priv->profile == NULL)
+    return 0;
+
+  if (NULL == (stash = sp_callgraph_profile_get_stash (priv->profile)))
+    return 0;
+
+  for (node = stack_stash_get_root (stash); node != NULL; node = node->siblings)
+    size += node->total;
+
+  priv->profile_size = size;
+
+  return size;
+}
+
+static void
+build_functions_store (StackNode *node,
+                       gpointer   user_data)
+{
+  struct {
+    GtkListStore *store;
+    gdouble profile_size;
+  } *state = user_data;
+  GtkTreeIter iter;
+  const StackNode *n;
+  guint size = 0;
+  guint total = 0;
+
+  g_assert (state != NULL);
+  g_assert (GTK_IS_LIST_STORE (state->store));
+
+  for (n = node; n != NULL; n = n->next)
+    {
+      size += n->size;
+      if (n->toplevel)
+        total += n->total;
+    }
+
+  gtk_list_store_append (state->store, &iter);
+  gtk_list_store_set (state->store, &iter,
+                      COLUMN_NAME, (const gchar *)node->data,
+                      COLUMN_SELF, 100.0 * size / state->profile_size,
+                      COLUMN_TOTAL, 100.0 * total / state->profile_size,
+                      COLUMN_POINTER, node,
+                      -1);
+
+}
+
+static void
+sp_callgraph_view_load (SpCallgraphView    *self,
+                        SpCallgraphProfile *profile)
+{
+  SpCallgraphViewPrivate *priv = sp_callgraph_view_get_instance_private (self);
+  GtkListStore *functions;
+  StackStash *stash;
+  StackNode *n;
+  GtkTreeIter iter;
+  struct {
+    GtkListStore *store;
+    gdouble profile_size;
+  } state = { 0 };
+
+  g_assert (SP_IS_CALLGRAPH_VIEW (self));
+  g_assert (SP_IS_CALLGRAPH_PROFILE (profile));
+
+  /*
+   * TODO: This is probably the type of thing we want to do off the main
+   *       thread. We should be able to build the tree models off thread
+   *       and then simply apply them on the main thread.
+   *
+   *       In the mean time, we should set the state of the widget to
+   *       insensitive and give some indication of loading progress.
+   */
+
+  g_set_object (&priv->profile, profile);
+
+  if (NULL == (stash = sp_callgraph_profile_get_stash (profile)))
+    return;
+
+  for (n = stack_stash_get_root (stash); n; n = n->siblings)
+    state.profile_size += n->total;
+
+  functions = gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_POINTER);
+
+  state.store = functions;
+  stack_stash_foreach_by_address (stash, build_functions_store, &state);
+
+  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (functions),
+                                        COLUMN_TOTAL,
+                                        GTK_SORT_DESCENDING);
+
+  gtk_tree_view_set_model (priv->functions_view, GTK_TREE_MODEL (functions));
+  gtk_tree_view_set_model (priv->callers_view, NULL);
+  gtk_tree_view_set_model (priv->descendants_view, NULL);
+
+  if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (functions), &iter))
+    {
+      GtkTreeSelection *selection;
+
+      selection = gtk_tree_view_get_selection (priv->functions_view);
+      gtk_tree_selection_select_iter (selection, &iter);
+    }
+
+  g_clear_object (&functions);
+}
+
+static void
+sp_callgraph_view_unload (SpCallgraphView *self)
+{
+  SpCallgraphViewPrivate *priv = sp_callgraph_view_get_instance_private (self);
+
+  g_assert (SP_IS_CALLGRAPH_VIEW (self));
+  g_assert (SP_IS_CALLGRAPH_PROFILE (priv->profile));
+
+  g_clear_object (&priv->profile);
+  priv->profile_size = 0;
+}
+
+void
+sp_callgraph_view_set_profile (SpCallgraphView    *self,
+                               SpCallgraphProfile *profile)
+{
+  SpCallgraphViewPrivate *priv = sp_callgraph_view_get_instance_private (self);
+
+  g_return_if_fail (SP_IS_CALLGRAPH_VIEW (self));
+  g_return_if_fail (!profile || SP_IS_CALLGRAPH_PROFILE (profile));
+
+  if (profile != priv->profile)
+    {
+      if (priv->profile)
+        sp_callgraph_view_unload (self);
+
+      if (profile)
+        sp_callgraph_view_load (self, profile);
+
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_PROFILE]);
+    }
+}
+
+static void
+sp_callgraph_view_expand_descendants (SpCallgraphView *self)
+{
+  SpCallgraphViewPrivate *priv = sp_callgraph_view_get_instance_private (self);
+  GtkTreeModel *model;
+  GList *all_paths = NULL;
+  GtkTreePath *first_path;
+  GtkTreeIter iter;
+  gdouble top_value = 0;
+  gint max_rows = 40; /* FIXME */
+  gint n_rows;
+
+  g_assert (SP_IS_CALLGRAPH_VIEW (self));
+
+  model = gtk_tree_view_get_model (priv->descendants_view);
+  first_path = gtk_tree_path_new_first ();
+  all_paths = g_list_prepend (all_paths, first_path);
+  n_rows = 1;
+
+  gtk_tree_model_get_iter (model, &iter, first_path);
+  gtk_tree_model_get (model, &iter,
+                      COLUMN_TOTAL, &top_value,
+                      -1);
+
+  while ((all_paths != NULL) && (n_rows < max_rows))
+    {
+      GtkTreeIter best_iter;
+      GtkTreePath *best_path = NULL;
+      GList *list;
+      gdouble best_value = 0.0;
+      gint n_children;
+      gint i;
+
+      for (list = all_paths; list != NULL; list = list->next)
+        {
+          GtkTreePath *path = list->data;
+
+          g_assert (path != NULL);
+
+          if (gtk_tree_model_get_iter (model, &iter, path))
+            {
+              gdouble value;
+
+              gtk_tree_model_get (model, &iter,
+                                  COLUMN_TOTAL, &value,
+                                  -1);
+
+              if (value >= best_value)
+                {
+                  best_value = value;
+                  best_path = path;
+                  best_iter = iter;
+                }
+            }
+        }
+
+      n_children = gtk_tree_model_iter_n_children (model, &best_iter);
+
+      if ((n_children > 0) &&
+          ((best_value / top_value) > 0.04) &&
+          ((n_children + gtk_tree_path_get_depth (best_path)) / (gdouble)max_rows) < (best_value / 
top_value))
+        {
+          gtk_tree_view_expand_row (priv->descendants_view, best_path, FALSE);
+          n_rows += n_children;
+
+          if (gtk_tree_path_get_depth (best_path) < 4)
+            {
+              GtkTreePath *path;
+
+              path = gtk_tree_path_copy (best_path);
+              gtk_tree_path_down (path);
+
+              for (i = 0; i < n_children; i++)
+                {
+                  all_paths = g_list_prepend (all_paths, path);
+
+                  path = gtk_tree_path_copy (path);
+                  gtk_tree_path_next (path);
+                }
+
+              gtk_tree_path_free (path);
+            }
+        }
+
+      all_paths = g_list_remove (all_paths, best_path);
+
+      /* Always expand at least once */
+      if ((all_paths == NULL) && (n_rows == 1))
+        gtk_tree_view_expand_row (priv->descendants_view, best_path, FALSE);
+
+      gtk_tree_path_free (best_path);
+    }
+
+  g_list_free_full (all_paths, (GDestroyNotify)gtk_tree_path_free);
+}
+
+typedef struct
+{
+  StackNode   *node;
+  const gchar *name;
+  guint        self;
+  guint        total;
+} Caller;
+
+static Caller *
+caller_new (StackNode *node)
+{
+  Caller *c;
+
+  c = g_slice_new (Caller);
+  c->name = U64_TO_POINTER (node->data);
+  c->self = 0;
+  c->total = 0;
+  c->node = node;
+
+  return c;
+}
+
+static void
+caller_free (gpointer data)
+{
+  Caller *c = data;
+  g_slice_free (Caller, c);
+}
+
+static void
+sp_callgraph_view_function_selection_changed (SpCallgraphView  *self,
+                                              GtkTreeSelection *selection)
+{
+  SpCallgraphViewPrivate *priv = sp_callgraph_view_get_instance_private (self);
+  GtkTreeModel *model = NULL;
+  GtkTreeIter iter;
+  GtkListStore *callers_store;
+  g_autoptr(GHashTable) callers = NULL;
+  g_autoptr(GHashTable) processed = NULL;
+  StackNode *callees = NULL;
+  StackNode *node;
+
+  g_assert (SP_IS_CALLGRAPH_VIEW (self));
+  g_assert (GTK_IS_TREE_SELECTION (selection));
+
+  if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+    {
+      gtk_tree_view_set_model (priv->callers_view, NULL);
+      gtk_tree_view_set_model (priv->descendants_view, NULL);
+      return;
+    }
+
+  gtk_tree_model_get (model, &iter,
+                      COLUMN_POINTER, &callees,
+                      -1);
+
+  sp_callgraph_view_update_descendants (self, callees);
+
+  callers_store = gtk_list_store_new (4,
+                                      G_TYPE_STRING,
+                                      G_TYPE_DOUBLE,
+                                      G_TYPE_DOUBLE,
+                                      G_TYPE_POINTER);
+
+  callers = g_hash_table_new_full (NULL, NULL, NULL, caller_free);
+  processed = g_hash_table_new (NULL, NULL);
+
+  for (node = callees; node != NULL; node = node->next)
+    {
+      Caller *c;
+
+      if (!node->parent)
+        continue;
+
+      c = g_hash_table_lookup (callers, U64_TO_POINTER (node->parent->data));
+
+      if (c == NULL)
+        {
+          c = caller_new (node->parent);
+          g_hash_table_insert (callers, (gpointer)c->name, c);
+        }
+    }
+
+  for (node = callees; node != NULL; node = node->next)
+    {
+      StackNode *top_caller = node->parent;
+      StackNode *top_callee = node;
+      StackNode *n;
+      Caller *c;
+
+      if (!node->parent)
+        continue;
+
+      /*
+       * We could have a situation where the function was called in a
+       * reentrant fashion, so we want to take the top-most match in the
+       * stack.
+       */
+      for (n = node; n && n->parent; n = n->parent)
+        {
+          if (n->data == node->data && n->parent->data == node->parent->data)
+            {
+              top_caller = n->parent;
+              top_callee = n;
+            }
+        }
+
+      c = g_hash_table_lookup (callers, U64_TO_POINTER (node->parent->data));
+
+      g_assert (c != NULL);
+
+      if (!g_hash_table_lookup (processed, top_caller))
+        {
+          c->total += top_callee->total;
+          g_hash_table_insert (processed, top_caller, top_caller);
+        }
+
+      c->self += node->size;
+    }
+
+  {
+    GHashTableIter hiter;
+    gpointer key, value;
+    guint size = 0;
+
+    size = sp_callgraph_view_get_profile_size (self);
+
+    g_hash_table_iter_init (&hiter, callers);
+
+    while (g_hash_table_iter_next (&hiter, &key, &value))
+      {
+        Caller *c = value;
+
+        gtk_list_store_append (callers_store, &iter);
+        gtk_list_store_set (callers_store, &iter,
+                            COLUMN_NAME, c->name,
+                            COLUMN_SELF, c->self * 100.0 / size,
+                            COLUMN_TOTAL, c->total * 100.0 / size,
+                            COLUMN_POINTER, c->node,
+                            -1);
+      }
+  }
+
+  gtk_tree_view_set_model (priv->callers_view, GTK_TREE_MODEL (callers_store));
+  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (callers_store),
+                                        COLUMN_TOTAL,
+                                        GTK_SORT_DESCENDING);
+
+  g_clear_object (&callers_store);
+}
+
+static void
+sp_callgraph_view_set_node (SpCallgraphView *self,
+                            StackNode       *node)
+{
+  SpCallgraphViewPrivate *priv = sp_callgraph_view_get_instance_private (self);
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+
+  g_assert (SP_IS_CALLGRAPH_VIEW (self));
+  g_assert (node != NULL);
+
+  model = gtk_tree_view_get_model (priv->functions_view);
+
+  if (gtk_tree_model_get_iter_first (model, &iter))
+    {
+      do
+        {
+          StackNode *item = NULL;
+
+          gtk_tree_model_get (model, &iter,
+                              COLUMN_POINTER, &item,
+                              -1);
+
+          if (item == node)
+            {
+              GtkTreeSelection *selection;
+
+              selection = gtk_tree_view_get_selection (priv->functions_view);
+              gtk_tree_selection_select_iter (selection, &iter);
+
+              break;
+            }
+        }
+      while (gtk_tree_model_iter_next (model, &iter));
+    }
+}
+
+static void
+sp_callgraph_view_descendant_activated (SpCallgraphView   *self,
+                                        GtkTreePath       *path,
+                                        GtkTreeViewColumn *column,
+                                        GtkTreeView       *tree_view)
+{
+  GtkTreeModel *model;
+  StackNode *node = NULL;
+  GtkTreeIter iter;
+
+  g_assert (SP_IS_CALLGRAPH_VIEW (self));
+  g_assert (GTK_IS_TREE_VIEW (tree_view));
+  g_assert (path != NULL);
+  g_assert (GTK_IS_TREE_VIEW_COLUMN (column));
+
+  model = gtk_tree_view_get_model (tree_view);
+
+  if (!gtk_tree_model_get_iter (model, &iter, path))
+    return;
+
+  gtk_tree_model_get (model, &iter,
+                      COLUMN_POINTER, &node,
+                      -1);
+
+  if (node != NULL)
+    sp_callgraph_view_set_node (self, node);
+}
+
+static void
+sp_callgraph_view_caller_activated (SpCallgraphView   *self,
+                                    GtkTreePath       *path,
+                                    GtkTreeViewColumn *column,
+                                    GtkTreeView       *tree_view)
+{
+  GtkTreeModel *model;
+  StackNode *node = NULL;
+  GtkTreeIter iter;
+
+  g_assert (SP_IS_CALLGRAPH_VIEW (self));
+  g_assert (GTK_IS_TREE_VIEW (tree_view));
+  g_assert (path != NULL);
+  g_assert (GTK_IS_TREE_VIEW_COLUMN (column));
+
+  model = gtk_tree_view_get_model (tree_view);
+
+  if (!gtk_tree_model_get_iter (model, &iter, path))
+    return;
+
+  gtk_tree_model_get (model, &iter,
+                      COLUMN_POINTER, &node,
+                      -1);
+
+  if (node != NULL)
+    sp_callgraph_view_set_node (self, node);
+}
+
+static void
+sp_callgraph_view_tag_data_func (GtkTreeViewColumn *column,
+                                 GtkCellRenderer   *cell,
+                                 GtkTreeModel      *model,
+                                 GtkTreeIter       *iter,
+                                 gpointer           data)
+{
+  SpCallgraphView *self = data;
+  SpCallgraphViewPrivate *priv = sp_callgraph_view_get_instance_private (self);
+  StackNode *node = NULL;
+  const gchar *str = NULL;
+
+  gtk_tree_model_get (model, iter, COLUMN_POINTER, &node, -1);
+
+  if (node && node->data)
+    {
+      GQuark tag;
+
+      tag = sp_callgraph_profile_get_tag (priv->profile, GSIZE_TO_POINTER (node->data));
+      if (tag != 0)
+        str = g_quark_to_string (tag);
+    }
+
+  g_object_set (cell, "text", str, NULL);
+}
+
+static void
+sp_callgraph_view_finalize (GObject *object)
+{
+  SpCallgraphView *self = (SpCallgraphView *)object;
+  SpCallgraphViewPrivate *priv = sp_callgraph_view_get_instance_private (self);
+
+  g_clear_object (&priv->profile);
+
+  G_OBJECT_CLASS (sp_callgraph_view_parent_class)->finalize (object);
+}
+
+static void
+sp_callgraph_view_get_property (GObject    *object,
+                                guint       prop_id,
+                                GValue     *value,
+                                GParamSpec *pspec)
+{
+  SpCallgraphView *self = SP_CALLGRAPH_VIEW (object);
+  SpCallgraphViewPrivate *priv = sp_callgraph_view_get_instance_private (self);
+
+  switch (prop_id)
+    {
+    case PROP_PROFILE:
+      g_value_set_object (value, priv->profile);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+sp_callgraph_view_set_property (GObject      *object,
+                                guint         prop_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
+{
+  SpCallgraphView *self = SP_CALLGRAPH_VIEW (object);
+
+  switch (prop_id)
+    {
+    case PROP_PROFILE:
+      sp_callgraph_view_set_profile (self, g_value_get_object (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+sp_callgraph_view_class_init (SpCallgraphViewClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->finalize = sp_callgraph_view_finalize;
+  object_class->get_property = sp_callgraph_view_get_property;
+  object_class->set_property = sp_callgraph_view_set_property;
+
+  properties [PROP_PROFILE] =
+    g_param_spec_object ("profile",
+                         "Profile",
+                         "The callgraph profile to view",
+                         SP_TYPE_CALLGRAPH_PROFILE,
+                         (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+
+  gtk_widget_class_set_template_from_resource (widget_class,
+                                               "/org/gnome/sysprof/ui/sp-callgraph-view.ui");
+
+  gtk_widget_class_bind_template_child_private (widget_class, SpCallgraphView, callers_view);
+  gtk_widget_class_bind_template_child_private (widget_class, SpCallgraphView, functions_view);
+  gtk_widget_class_bind_template_child_private (widget_class, SpCallgraphView, descendants_view);
+  gtk_widget_class_bind_template_child_private (widget_class, SpCallgraphView, descendants_name_column);
+}
+
+static void
+sp_callgraph_view_init (SpCallgraphView *self)
+{
+  SpCallgraphViewPrivate *priv = sp_callgraph_view_get_instance_private (self);
+  GtkTreeSelection *selection;
+  GtkCellRenderer *cell;
+
+  gtk_widget_init_template (GTK_WIDGET (self));
+
+  selection = gtk_tree_view_get_selection (priv->functions_view);
+
+  g_signal_connect_object (selection,
+                           "changed",
+                           G_CALLBACK (sp_callgraph_view_function_selection_changed),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (priv->descendants_view,
+                           "row-activated",
+                           G_CALLBACK (sp_callgraph_view_descendant_activated),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (priv->callers_view,
+                           "row-activated",
+                           G_CALLBACK (sp_callgraph_view_caller_activated),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  cell = g_object_new (GTK_TYPE_CELL_RENDERER_TEXT,
+                       "foreground", "#666666",
+                       "scale", PANGO_SCALE_SMALL,
+                       "xalign", 1.0f,
+                       NULL);
+  gtk_tree_view_column_pack_start (priv->descendants_name_column, cell, FALSE);
+  gtk_tree_view_column_set_cell_data_func (priv->descendants_name_column, cell,
+                                           sp_callgraph_view_tag_data_func,
+                                           self, NULL);
+}
+
+typedef struct _Descendant Descendant;
+
+struct _Descendant
+{
+  const gchar *name;
+  guint        self;
+  guint        cumulative;
+  Descendant  *parent;
+  Descendant  *siblings;
+  Descendant  *children;
+};
+
+static void
+build_tree_cb (StackLink *trace,
+               gint       size,
+               gpointer   user_data)
+{
+  Descendant **tree = user_data;
+  Descendant *parent = NULL;
+  StackLink *link;
+
+  g_assert (trace != NULL);
+  g_assert (tree != NULL);
+
+  /* Get last item */
+  link = trace;
+  while (link->next)
+    link = link->next;
+
+  for (; link != NULL; link = link->prev)
+    {
+      const gchar *address = U64_TO_POINTER (link->data);
+      Descendant *prev = NULL;
+      Descendant *match = NULL;
+
+      for (match = *tree; match != NULL; match = match->siblings)
+        {
+          if (match->name == address)
+            {
+              if (prev != NULL)
+                {
+                  /* Move to front */
+                  prev->siblings = match->siblings;
+                  match->siblings = *tree;
+                  *tree = match;
+                }
+              break;
+            }
+        }
+
+      if (match == NULL)
+        {
+          /* Have we seen this object further up the tree? */
+          for (match = parent; match != NULL; match = match->parent)
+            {
+              if (match->name == address)
+                break;
+            }
+        }
+
+      if (match == NULL)
+        {
+          match = g_slice_new (Descendant);
+          match->name = address;
+          match->cumulative = 0;
+          match->self = 0;
+          match->children = NULL;
+          match->parent = parent;
+          match->siblings = *tree;
+          *tree = match;
+        }
+
+      tree = &match->children;
+      parent = match;
+    }
+
+  parent->self += size;
+
+  for (; parent != NULL; parent = parent->parent)
+    parent->cumulative += size;
+}
+
+static Descendant *
+build_tree (StackNode *node)
+{
+  Descendant *tree = NULL;
+
+  for (; node != NULL; node = node->next)
+    {
+      if (node->toplevel)
+        stack_node_foreach_trace (node, build_tree_cb, &tree);
+    }
+
+  return tree;
+}
+
+static void
+append_to_tree_and_free (SpCallgraphView *self,
+                         StackStash      *stash,
+                         GtkTreeStore    *store,
+                         Descendant      *item,
+                         GtkTreeIter     *parent)
+{
+  StackNode *node = NULL;
+  GtkTreeIter iter;
+  guint profile_size;
+
+  g_assert (GTK_IS_TREE_STORE (store));
+  g_assert (item != NULL);
+
+  profile_size = sp_callgraph_view_get_profile_size (self);
+
+  gtk_tree_store_append (store, &iter, parent);
+
+  node = stack_stash_find_node (stash, (gpointer)item->name);
+
+  gtk_tree_store_set (store, &iter,
+                      COLUMN_NAME, item->name,
+                      COLUMN_SELF, item->self * 100.0 / (gdouble)profile_size,
+                      COLUMN_TOTAL, item->cumulative * 100.0 / (gdouble)profile_size,
+                      COLUMN_POINTER, node,
+                      -1);
+
+  if (item->siblings != NULL)
+    append_to_tree_and_free (self, stash, store, item->siblings, parent);
+
+  if (item->children != NULL)
+    append_to_tree_and_free (self, stash, store, item->children, &iter);
+
+  g_slice_free (Descendant, item);
+}
+
+static void
+sp_callgraph_view_update_descendants (SpCallgraphView *self,
+                                      StackNode       *node)
+{
+  SpCallgraphViewPrivate *priv = sp_callgraph_view_get_instance_private (self);
+  GtkTreeStore *store;
+
+  g_assert (SP_IS_CALLGRAPH_VIEW (self));
+
+  store = gtk_tree_store_new (4,
+                              G_TYPE_STRING,
+                              G_TYPE_DOUBLE,
+                              G_TYPE_DOUBLE,
+                              G_TYPE_POINTER);
+
+  if (priv->profile != NULL)
+  {
+    StackStash *stash;
+
+    stash = sp_callgraph_profile_get_stash (priv->profile);
+    if (stash != NULL)
+      {
+        Descendant *tree;
+
+        tree = build_tree (node);
+        if (tree != NULL)
+          append_to_tree_and_free (self, stash, store, tree, NULL);
+      }
+  }
+
+  gtk_tree_view_set_model (priv->descendants_view, GTK_TREE_MODEL (store));
+  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
+                                        COLUMN_TOTAL, GTK_SORT_DESCENDING);
+  sp_callgraph_view_expand_descendants (self);
+
+  g_clear_object (&store);
+}
diff --git a/lib/sp-callgraph-view.h b/lib/sp-callgraph-view.h
new file mode 100644
index 0000000..8e9898e
--- /dev/null
+++ b/lib/sp-callgraph-view.h
@@ -0,0 +1,44 @@
+/* sp-callgraph-view.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_CALLGRAPH_VIEW_H
+#define SP_CALLGRAPH_VIEW_H
+
+#include <gtk/gtk.h>
+
+#include "sp-callgraph-profile.h"
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_CALLGRAPH_VIEW (sp_callgraph_view_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (SpCallgraphView, sp_callgraph_view, SP, CALLGRAPH_VIEW, GtkBin)
+
+struct _SpCallgraphViewClass
+{
+  GtkBinClass parent_class;
+};
+
+GtkWidget          *sp_callgraph_view_new         (void);
+SpCallgraphProfile *sp_callgraph_view_get_profile (SpCallgraphView    *self);
+void                sp_callgraph_view_set_profile (SpCallgraphView    *self,
+                                                   SpCallgraphProfile *profile);
+
+G_END_DECLS
+
+#endif /* SP_CALLGRAPH_VIEW_H */
diff --git a/lib/sp-capture-reader.c b/lib/sp-capture-reader.c
new file mode 100644
index 0000000..f5d4544
--- /dev/null
+++ b/lib/sp-capture-reader.c
@@ -0,0 +1,686 @@
+/* sp-capture-reader.c
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This file 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
+ * Lesser 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/>.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/sendfile.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "sp-capture-reader.h"
+#include "sp-capture-writer.h"
+
+struct _SpCaptureReader
+{
+  volatile gint        ref_count;
+  gchar               *filename;
+  guint8              *buf;
+  gsize                bufsz;
+  gsize                len;
+  gsize                pos;
+  gsize                fd_off;
+  int                  fd;
+  gint                 endian;
+  SpCaptureFileHeader  header;
+};
+
+#ifndef SP_DISABLE_GOBJECT
+G_DEFINE_BOXED_TYPE (SpCaptureReader, sp_capture_reader,
+                     sp_capture_reader_ref, sp_capture_reader_unref)
+#endif
+
+static gboolean
+sp_capture_reader_read_file_header (SpCaptureReader      *self,
+                                    SpCaptureFileHeader  *header,
+                                    GError              **error)
+{
+  g_assert (self != NULL);
+  g_assert (header != NULL);
+
+  if (sizeof *header != pread (self->fd, header, sizeof *header, 0L))
+    {
+      g_set_error (error,
+                   G_FILE_ERROR,
+                   g_file_error_from_errno (errno),
+                   "%s", g_strerror (errno));
+      return FALSE;
+    }
+
+  if (header->magic != SP_CAPTURE_MAGIC)
+    {
+      g_set_error (error,
+                   G_FILE_ERROR,
+                   G_FILE_ERROR_FAILED,
+                   "Capture file magic does not match");
+      return FALSE;
+    }
+
+  header->capture_time[sizeof header->capture_time - 1] = '\0';
+
+  return TRUE;
+}
+
+static void
+sp_capture_reader_finalize (SpCaptureReader *self)
+{
+  if (self != NULL)
+    {
+      close (self->fd);
+      g_free (self->buf);
+      g_free (self->filename);
+      g_free (self);
+    }
+}
+
+const gchar *
+sp_capture_reader_get_time (SpCaptureReader *self)
+{
+  g_return_val_if_fail (self != NULL, NULL);
+
+  return self->header.capture_time;
+}
+
+const gchar *
+sp_capture_reader_get_filename (SpCaptureReader *self)
+{
+  g_return_val_if_fail (self != NULL, NULL);
+
+  return self->filename;
+}
+
+SpCaptureReader *
+sp_capture_reader_new_from_fd (int      fd,
+                               GError **error)
+{
+  SpCaptureReader *self;
+
+  g_assert (fd > -1);
+
+  self = g_new0 (SpCaptureReader, 1);
+  self->ref_count = 1;
+  self->bufsz = G_MAXUSHORT * 2;
+  self->buf = g_malloc (self->bufsz);
+  self->len = 0;
+  self->pos = 0;
+  self->fd = fd;
+  self->fd_off = sizeof (SpCaptureFileHeader);
+
+  if (!sp_capture_reader_read_file_header (self, &self->header, error))
+    {
+      sp_capture_reader_finalize (self);
+      return NULL;
+    }
+
+  if (self->header.little_endian)
+    self->endian = G_LITTLE_ENDIAN;
+  else
+    self->endian = G_BIG_ENDIAN;
+
+  return self;
+}
+
+SpCaptureReader *
+sp_capture_reader_new (const gchar  *filename,
+                       GError      **error)
+{
+  SpCaptureReader *self;
+  int fd;
+
+  g_assert (filename != NULL);
+
+  if (-1 == (fd = open (filename, O_RDONLY, 0)))
+    {
+      g_set_error (error,
+                   G_FILE_ERROR,
+                   g_file_error_from_errno (errno),
+                   "%s", g_strerror (errno));
+      return NULL;
+    }
+
+  if (NULL == (self = sp_capture_reader_new_from_fd (fd, error)))
+    {
+      close (fd);
+      return NULL;
+    }
+
+  self->filename = g_strdup (filename);
+
+  return self;
+}
+
+static inline void
+sp_capture_reader_bswap_frame (SpCaptureReader *self,
+                               SpCaptureFrame  *frame)
+{
+  g_assert (self != NULL);
+  g_assert (frame!= NULL);
+
+  if (G_UNLIKELY (self->endian != G_BYTE_ORDER))
+    {
+      frame->len = GUINT16_SWAP_LE_BE (frame->len);
+      frame->cpu = GUINT16_SWAP_LE_BE (frame->len);
+      frame->pid = GUINT32_SWAP_LE_BE (frame->len);
+      frame->time = GUINT64_SWAP_LE_BE (frame->len);
+    }
+}
+
+static inline void
+sp_capture_reader_bswap_map (SpCaptureReader *self,
+                             SpCaptureMap    *map)
+{
+  g_assert (self != NULL);
+  g_assert (map != NULL);
+
+  if (G_UNLIKELY (self->endian != G_BYTE_ORDER))
+    {
+      map->start = GUINT64_SWAP_LE_BE (map->start);
+      map->end = GUINT64_SWAP_LE_BE (map->end);
+      map->offset = GUINT64_SWAP_LE_BE (map->offset);
+      map->inode = GUINT64_SWAP_LE_BE (map->inode);
+    }
+}
+
+static inline void
+sp_capture_reader_bswap_jitmap (SpCaptureReader *self,
+                                SpCaptureJitmap *jitmap)
+{
+  g_assert (self != NULL);
+  g_assert (jitmap != NULL);
+
+  if (G_UNLIKELY (self->endian != G_BYTE_ORDER))
+    jitmap->n_jitmaps = GUINT64_SWAP_LE_BE (jitmap->n_jitmaps);
+}
+
+static gboolean
+sp_capture_reader_ensure_space_for (SpCaptureReader *self,
+                                    gsize            len)
+{
+  g_assert (self != NULL);
+  g_assert (len > 0);
+
+  if ((self->len - self->pos) < len)
+    {
+      gssize r;
+
+      g_assert (self->len >= self->pos);
+
+      memmove (self->buf, &self->buf[self->pos], self->len - self->pos);
+      self->len -= self->pos;
+      self->pos = 0;
+
+      while ((self->len - self->pos) <= len)
+        {
+          g_assert (self->pos + self->len < self->bufsz);
+
+          /* Read into our buffer after our current read position */
+          r = pread (self->fd,
+                     &self->buf[self->len],
+                     self->bufsz - self->len,
+                     self->fd_off);
+
+          if (r <= 0)
+            break;
+
+          self->fd_off += r;
+          self->len += r;
+        }
+    }
+
+  return (self->len - self->pos) >= len;
+}
+
+gboolean
+sp_capture_reader_skip (SpCaptureReader *self)
+{
+  SpCaptureFrame *frame;
+
+  g_assert (self != NULL);
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+
+  if (!sp_capture_reader_ensure_space_for (self, sizeof (SpCaptureFrame)))
+    return FALSE;
+
+  frame = (SpCaptureFrame *)(gpointer)&self->buf[self->pos];
+  sp_capture_reader_bswap_frame (self, frame);
+
+  if (frame->len < sizeof (SpCaptureFrame))
+    return FALSE;
+
+  if (!sp_capture_reader_ensure_space_for (self, frame->len))
+    return FALSE;
+
+  frame = (SpCaptureFrame *)(gpointer)&self->buf[self->pos];
+
+  self->pos += frame->len;
+
+  if ((self->pos % SP_CAPTURE_ALIGN) != 0)
+    return FALSE;
+
+  return TRUE;
+}
+
+gboolean
+sp_capture_reader_peek_type (SpCaptureReader    *self,
+                             SpCaptureFrameType *type)
+{
+  SpCaptureFrame *frame;
+
+  g_assert (self != NULL);
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+  g_assert (self->pos <= self->bufsz);
+  g_assert (type != NULL);
+
+  *type = 0;
+
+  if (!sp_capture_reader_ensure_space_for (self, sizeof *frame))
+    return FALSE;
+
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+
+  frame = (SpCaptureFrame *)(gpointer)&self->buf[self->pos];
+
+  *type = frame->type;
+
+  return TRUE;
+}
+
+static const SpCaptureFrame *
+sp_capture_reader_read_basic (SpCaptureReader    *self,
+                              SpCaptureFrameType  type,
+                              gsize               extra)
+{
+  SpCaptureFrame *frame;
+  gsize len = sizeof *frame + extra;
+
+  g_assert (self != NULL);
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+  g_assert (self->pos <= self->bufsz);
+
+  if (!sp_capture_reader_ensure_space_for (self, len))
+    return NULL;
+
+  frame = (SpCaptureFrame *)(gpointer)&self->buf[self->pos];
+
+  sp_capture_reader_bswap_frame (self, frame);
+
+  if (frame->len < len)
+    return NULL;
+
+  if (frame->type != type)
+    return NULL;
+
+  self->pos += frame->len;
+
+  return frame;
+}
+
+const SpCaptureTimestamp *
+sp_capture_reader_read_timestamp (SpCaptureReader *self)
+{
+  return (SpCaptureTimestamp *)
+    sp_capture_reader_read_basic (self, SP_CAPTURE_FRAME_TIMESTAMP, 0);
+}
+
+const SpCaptureExit *
+sp_capture_reader_read_exit (SpCaptureReader *self)
+{
+  return (SpCaptureExit *)
+    sp_capture_reader_read_basic (self, SP_CAPTURE_FRAME_EXIT, 0);
+}
+
+const SpCaptureFork *
+sp_capture_reader_read_fork (SpCaptureReader *self)
+{
+  SpCaptureFork *fk;
+
+  g_assert (self != NULL);
+
+  fk = (SpCaptureFork *)
+    sp_capture_reader_read_basic (self, SP_CAPTURE_FRAME_FORK, sizeof(guint32));
+
+  if (fk != NULL)
+    {
+      if (G_UNLIKELY (self->endian != G_BYTE_ORDER))
+        fk->child_pid = GUINT32_SWAP_LE_BE (fk->child_pid);
+    }
+
+  return fk;
+}
+
+const SpCaptureMap *
+sp_capture_reader_read_map (SpCaptureReader *self)
+{
+  SpCaptureMap *map;
+
+  g_assert (self != NULL);
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+  g_assert (self->pos <= self->bufsz);
+
+  if (!sp_capture_reader_ensure_space_for (self, sizeof *map))
+    return NULL;
+
+  map = (SpCaptureMap *)(gpointer)&self->buf[self->pos];
+
+  sp_capture_reader_bswap_frame (self, &map->frame);
+
+  if (map->frame.type != SP_CAPTURE_FRAME_MAP)
+    return NULL;
+
+  if (map->frame.len < (sizeof *map + 1))
+    return NULL;
+
+  if (!sp_capture_reader_ensure_space_for (self, map->frame.len))
+    return NULL;
+
+  map = (SpCaptureMap *)(gpointer)&self->buf[self->pos];
+
+  if (self->buf[self->pos + map->frame.len - 1] != '\0')
+    return NULL;
+
+  sp_capture_reader_bswap_map (self, map);
+
+  self->pos += map->frame.len;
+
+  if ((self->pos % SP_CAPTURE_ALIGN) != 0)
+    return NULL;
+
+  return map;
+}
+
+const SpCaptureProcess *
+sp_capture_reader_read_process (SpCaptureReader *self)
+{
+  SpCaptureProcess *process;
+
+  g_assert (self != NULL);
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+  g_assert (self->pos <= self->bufsz);
+
+  if (!sp_capture_reader_ensure_space_for (self, sizeof *process))
+    return NULL;
+
+  process = (SpCaptureProcess *)(gpointer)&self->buf[self->pos];
+
+  sp_capture_reader_bswap_frame (self, &process->frame);
+
+  if (process->frame.type != SP_CAPTURE_FRAME_PROCESS)
+    return NULL;
+
+  if (process->frame.len < (sizeof *process + 1))
+    return NULL;
+
+  if (!sp_capture_reader_ensure_space_for (self, process->frame.len))
+    return NULL;
+
+  process = (SpCaptureProcess *)(gpointer)&self->buf[self->pos];
+
+  if (self->buf[self->pos + process->frame.len - 1] != '\0')
+    return NULL;
+
+  self->pos += process->frame.len;
+
+  if ((self->pos % SP_CAPTURE_ALIGN) != 0)
+    return NULL;
+
+  return process;
+}
+
+GHashTable *
+sp_capture_reader_read_jitmap (SpCaptureReader *self)
+{
+  g_autoptr(GHashTable) ret = NULL;
+  SpCaptureJitmap *jitmap;
+  guint8 *buf;
+  guint8 *endptr;
+  guint i;
+
+  g_assert (self != NULL);
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+  g_assert (self->pos <= self->bufsz);
+
+  if (!sp_capture_reader_ensure_space_for (self, sizeof *jitmap))
+    return NULL;
+
+  jitmap = (SpCaptureJitmap *)(gpointer)&self->buf[self->pos];
+
+  sp_capture_reader_bswap_frame (self, &jitmap->frame);
+
+  if (jitmap->frame.type != SP_CAPTURE_FRAME_JITMAP)
+    return NULL;
+
+  if (jitmap->frame.len < sizeof *jitmap)
+    return NULL;
+
+  if (!sp_capture_reader_ensure_space_for (self, jitmap->frame.len))
+    return NULL;
+
+  jitmap = (SpCaptureJitmap *)(gpointer)&self->buf[self->pos];
+
+  ret = g_hash_table_new_full (NULL, NULL, NULL, g_free);
+
+  buf = jitmap->data;
+  endptr = &self->buf[self->pos + jitmap->frame.len];
+
+  for (i = 0; i < jitmap->n_jitmaps; i++)
+    {
+      SpCaptureAddress addr;
+      const gchar *str;
+
+      if (buf + sizeof addr >= endptr)
+        return NULL;
+
+      memcpy (&addr, buf, sizeof addr);
+      buf += sizeof addr;
+
+      str = (gchar *)buf;
+
+      buf = memchr (buf, '\0', (endptr - buf));
+
+      if (buf == NULL)
+        return NULL;
+
+      buf++;
+
+      g_hash_table_insert (ret, GSIZE_TO_POINTER (addr), g_strdup (str));
+    }
+
+  self->pos += jitmap->frame.len;
+
+  return g_steal_pointer (&ret);
+}
+
+const SpCaptureSample *
+sp_capture_reader_read_sample (SpCaptureReader *self)
+{
+  SpCaptureSample *sample;
+
+  g_assert (self != NULL);
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+  g_assert (self->pos <= self->bufsz);
+
+  if (!sp_capture_reader_ensure_space_for (self, sizeof *sample))
+    return NULL;
+
+  sample = (SpCaptureSample *)(gpointer)&self->buf[self->pos];
+
+  sp_capture_reader_bswap_frame (self, &sample->frame);
+
+  if (sample->frame.type != SP_CAPTURE_FRAME_SAMPLE)
+    return NULL;
+
+  if (sample->frame.len < sizeof *sample)
+    return NULL;
+
+  if (self->endian != G_BYTE_ORDER)
+    sample->n_addrs = GUINT16_SWAP_LE_BE (sample->n_addrs);
+
+  if (sample->frame.len < (sizeof *sample + (sizeof(SpCaptureAddress) * sample->n_addrs)))
+    return NULL;
+
+  if (!sp_capture_reader_ensure_space_for (self, sample->frame.len))
+    return NULL;
+
+  sample = (SpCaptureSample *)(gpointer)&self->buf[self->pos];
+
+  if (self->endian != G_BYTE_ORDER)
+    {
+      guint i;
+
+      for (i = 0; i < sample->n_addrs; i++)
+        sample->addrs[i] = GUINT64_SWAP_LE_BE (sample->addrs[i]);
+    }
+
+  self->pos += sample->frame.len;
+
+  return sample;
+}
+
+gboolean
+sp_capture_reader_reset (SpCaptureReader *self)
+{
+  g_assert (self != NULL);
+
+  self->fd_off = sizeof (SpCaptureFileHeader);
+  self->pos = 0;
+  self->len = 0;
+
+  return TRUE;
+}
+
+SpCaptureReader *
+sp_capture_reader_ref (SpCaptureReader *self)
+{
+  g_assert (self != NULL);
+  g_assert (self->ref_count > 0);
+
+  g_atomic_int_inc (&self->ref_count);
+
+  return self;
+}
+
+void
+sp_capture_reader_unref (SpCaptureReader *self)
+{
+  g_assert (self != NULL);
+  g_assert (self->ref_count > 0);
+
+  if (g_atomic_int_dec_and_test (&self->ref_count))
+    sp_capture_reader_finalize (self);
+}
+
+gboolean
+sp_capture_reader_splice (SpCaptureReader  *self,
+                          SpCaptureWriter  *dest,
+                          GError          **error)
+{
+  g_assert (self != NULL);
+  g_assert (self->fd != -1);
+  g_assert (dest != NULL);
+
+  /* Flush before writing anything to ensure consistency */
+  if (!sp_capture_writer_flush (dest))
+    {
+      g_set_error (error,
+                   G_FILE_ERROR,
+                   g_file_error_from_errno (errno),
+                   "%s", g_strerror (errno));
+      return FALSE;
+    }
+
+  /*
+   * We don't need to track position because writer will
+   * track the current position to avoid reseting it.
+   */
+
+  /* Perform the splice */
+  return _sp_capture_writer_splice_from_fd (dest, self->fd, error);
+}
+
+/**
+ * sp_capture_reader_save_as:
+ * @self: An #SpCaptureReader
+ * @filename: the file to save the capture as
+ * @error: a location for a #GError or %NULL.
+ *
+ * This is a convenience function for copying a capture file for which
+ * you may have already discarded the writer for.
+ *
+ * Returns: %TRUE on success; otherwise %FALSE and @error is set.
+ */
+gboolean
+sp_capture_reader_save_as (SpCaptureReader  *self,
+                           const gchar      *filename,
+                           GError          **error)
+{
+  struct stat stbuf;
+  off_t in_off;
+  gsize to_write;
+  int fd = -1;
+
+  g_assert (self != NULL);
+  g_assert (filename != NULL);
+
+  if (-1 == (fd = open (filename, O_CREAT | O_WRONLY, 0640)))
+    goto handle_errno;
+
+  if (-1 == fstat (self->fd, &stbuf))
+    goto handle_errno;
+
+  if (-1 == ftruncate (fd, stbuf.st_size))
+    goto handle_errno;
+
+  if ((off_t)-1 == lseek (fd, 0L, SEEK_SET))
+    goto handle_errno;
+
+  in_off = 0;
+  to_write = stbuf.st_size;
+
+  while (to_write > 0)
+    {
+      gssize written;
+
+      written = sendfile (fd, self->fd, &in_off, to_write);
+
+      if (written < 0)
+        goto handle_errno;
+
+      if (written == 0 && errno != EAGAIN)
+        goto handle_errno;
+
+      g_assert (written <= (gssize)to_write);
+
+      to_write -= written;
+    }
+
+  close (fd);
+
+  return TRUE;
+
+handle_errno:
+  if (fd != -1)
+    close (fd);
+
+  g_set_error (error,
+               G_FILE_ERROR,
+               g_file_error_from_errno (errno),
+               "%s", g_strerror (errno));
+
+  return FALSE;
+}
diff --git a/lib/sp-capture-reader.h b/lib/sp-capture-reader.h
new file mode 100644
index 0000000..14d93c8
--- /dev/null
+++ b/lib/sp-capture-reader.h
@@ -0,0 +1,65 @@
+/* sp-capture-reader.h
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This file 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
+ * Lesser 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/>.
+ */
+
+#ifndef SP_CAPTURE_READER_H
+#define SP_CAPTURE_READER_H
+
+#include "sp-capture-types.h"
+
+G_BEGIN_DECLS
+
+typedef struct _SpCaptureReader SpCaptureReader;
+
+SpCaptureReader          *sp_capture_reader_new            (const gchar         *filename,
+                                                            GError             **error);
+SpCaptureReader          *sp_capture_reader_new_from_fd    (int                  fd,
+                                                            GError             **error);
+SpCaptureReader          *sp_capture_reader_ref            (SpCaptureReader     *self);
+void                      sp_capture_reader_unref          (SpCaptureReader     *self);
+const gchar              *sp_capture_reader_get_filename   (SpCaptureReader     *self);
+const gchar              *sp_capture_reader_get_time       (SpCaptureReader     *self);
+gboolean                  sp_capture_reader_skip           (SpCaptureReader     *self);
+gboolean                  sp_capture_reader_peek_type      (SpCaptureReader     *self,
+                                                            SpCaptureFrameType  *type);
+const SpCaptureMap       *sp_capture_reader_read_map       (SpCaptureReader     *self);
+const SpCaptureExit      *sp_capture_reader_read_exit      (SpCaptureReader     *self);
+const SpCaptureFork      *sp_capture_reader_read_fork      (SpCaptureReader     *self);
+const SpCaptureTimestamp *sp_capture_reader_read_timestamp (SpCaptureReader     *self);
+const SpCaptureProcess   *sp_capture_reader_read_process   (SpCaptureReader     *self);
+const SpCaptureSample    *sp_capture_reader_read_sample    (SpCaptureReader     *self);
+GHashTable               *sp_capture_reader_read_jitmap    (SpCaptureReader     *self);
+gboolean                  sp_capture_reader_reset          (SpCaptureReader     *self);
+gboolean                  sp_capture_reader_splice         (SpCaptureReader     *self,
+                                                            SpCaptureWriter     *dest,
+                                                            GError             **error);
+gboolean                  sp_capture_reader_save_as        (SpCaptureReader     *self,
+                                                            const gchar         *filename,
+                                                            GError             **error);
+
+#ifndef SP_DISABLE_GOBJECT
+# define SP_TYPE_CAPTURE_READER (sp_capture_reader_get_type())
+  GType sp_capture_reader_get_type (void);
+#endif
+
+#if GLIB_CHECK_VERSION(2, 44, 0)
+  G_DEFINE_AUTOPTR_CLEANUP_FUNC (SpCaptureReader, sp_capture_reader_unref)
+#endif
+
+G_END_DECLS
+
+#endif /* SP_CAPTURE_READER_H */
diff --git a/lib/sp-capture-types.h b/lib/sp-capture-types.h
new file mode 100644
index 0000000..7bb3ab7
--- /dev/null
+++ b/lib/sp-capture-types.h
@@ -0,0 +1,155 @@
+/* sp-capture-types.h
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This file 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
+ * Lesser 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/>.
+ */
+
+#ifndef SP_CAPTURE_FORMAT_H
+#define SP_CAPTURE_FORMAT_H
+
+#include <glib.h>
+
+#ifndef SP_DISABLE_GOBJECT
+# include <glib-object.h>
+#endif
+
+G_BEGIN_DECLS
+
+#define SP_CAPTURE_MAGIC (GUINT32_TO_LE(0xFDCA975E))
+#define SP_CAPTURE_ALIGN (sizeof(SpCaptureAddress))
+
+#if __WORDSIZE == 64
+# define SP_CAPTURE_JITMAP_MARK    G_GUINT64_CONSTANT(0xE000000000000000)
+# define SP_CAPTURE_ADDRESS_FORMAT "0x%016lx"
+#else
+# define SP_CAPTURE_JITMAP_MARK    G_GUINT64_CONSTANT(0xE0000000)
+# define SP_CAPTURE_ADDRESS_FORMAT "0x%016llx"
+#endif
+
+#define SP_CAPTURE_CURRENT_TIME (g_get_monotonic_time() * 1000L)
+
+typedef struct _SpCaptureReader SpCaptureReader;
+typedef struct _SpCaptureWriter SpCaptureWriter;
+
+typedef guint64 SpCaptureAddress;
+
+typedef enum
+{
+  SP_CAPTURE_FRAME_TIMESTAMP = 1,
+  SP_CAPTURE_FRAME_SAMPLE    = 2,
+  SP_CAPTURE_FRAME_MAP       = 3,
+  SP_CAPTURE_FRAME_PROCESS   = 4,
+  SP_CAPTURE_FRAME_FORK      = 5,
+  SP_CAPTURE_FRAME_EXIT      = 6,
+  SP_CAPTURE_FRAME_JITMAP    = 7,
+} SpCaptureFrameType;
+
+#pragma pack(push, 1)
+
+typedef struct
+{
+  guint32 magic;
+  guint8  version;
+  guint32 little_endian : 1;
+  guint32 padding : 23;
+  gchar   capture_time[64];
+  gchar   suffix[184];
+} SpCaptureFileHeader;
+
+typedef struct
+{
+  guint16 len;
+  gint16  cpu;
+  gint32  pid;
+  gint64  time;
+  guint8  type;
+  guint64 padding : 56;
+  guint8  data[0];
+} SpCaptureFrame;
+
+typedef struct
+{
+  SpCaptureFrame frame;
+  guint64        start;
+  guint64        end;
+  guint64        offset;
+  guint64        inode;
+  gchar          filename[0];
+} SpCaptureMap;
+
+typedef struct
+{
+  SpCaptureFrame frame;
+  guint32        n_jitmaps;
+  guint8         data[0];
+} SpCaptureJitmap;
+
+typedef struct
+{
+  SpCaptureFrame frame;
+  gchar          cmdline[0];
+} SpCaptureProcess;
+
+typedef struct
+{
+  SpCaptureFrame   frame;
+  guint16          n_addrs;
+  guint64          padding : 48;
+  SpCaptureAddress addrs[0];
+} SpCaptureSample;
+
+typedef struct
+{
+  SpCaptureFrame frame;
+  GPid           child_pid;
+} SpCaptureFork;
+
+typedef struct
+{
+  SpCaptureFrame frame;
+} SpCaptureExit;
+
+typedef struct
+{
+  SpCaptureFrame frame;
+} SpCaptureTimestamp;
+
+#pragma pack(pop)
+
+G_STATIC_ASSERT (sizeof (SpCaptureFileHeader) == 256);
+G_STATIC_ASSERT (sizeof (SpCaptureFrame) == 24);
+G_STATIC_ASSERT (sizeof (SpCaptureMap) == 56);
+G_STATIC_ASSERT (sizeof (SpCaptureJitmap) == 28);
+G_STATIC_ASSERT (sizeof (SpCaptureProcess) == 24);
+G_STATIC_ASSERT (sizeof (SpCaptureSample) == 32);
+G_STATIC_ASSERT (sizeof (SpCaptureFork) == 28);
+G_STATIC_ASSERT (sizeof (SpCaptureExit) == 24);
+G_STATIC_ASSERT (sizeof (SpCaptureTimestamp) == 24);
+
+static inline gint
+sp_capture_address_compare (SpCaptureAddress a,
+                            SpCaptureAddress b)
+{
+  if (a < b)
+    return -1;
+  if (a > b)
+    return 1;
+  else
+    return 0;
+}
+
+G_END_DECLS
+
+#endif /* SP_CAPTURE_FORMAT_H */
diff --git a/lib/sp-capture-writer.c b/lib/sp-capture-writer.c
new file mode 100644
index 0000000..f0f725f
--- /dev/null
+++ b/lib/sp-capture-writer.c
@@ -0,0 +1,954 @@
+/* sp-capture-writer.c
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This file 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
+ * Lesser 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/>.
+ */
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <glib/gstdio.h>
+#include <string.h>
+#include <sys/sendfile.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "sp-capture-reader.h"
+#include "sp-capture-writer.h"
+
+#define DEFAULT_BUFFER_SIZE (getpagesize() * 64L)
+#define INVALID_ADDRESS     (G_GUINT64_CONSTANT(0))
+
+typedef struct
+{
+  /* A pinter into the string buffer */
+  const gchar *str;
+
+  /* The unique address for the string */
+  guint64 addr;
+} SpCaptureJitmapBucket;
+
+struct _SpCaptureWriter
+{
+  /*
+   * This is our buffer location for incoming strings. This is used
+   * similarly to GStringChunk except there is only one-page, and after
+   * it fills, we flush to disk.
+   *
+   * This is paired with a closed hash table for deduplication.
+   */
+  gchar addr_buf[4096*4];
+
+  /* Our hashtable for deduplication. */
+  SpCaptureJitmapBucket addr_hash[512];
+
+  /* We keep the large fields above so that our allocation will be page
+   * alinged for the write buffer. This improves the performance of large
+   * writes to the target file-descriptor.
+   */
+
+  volatile gint ref_count;
+
+  /*
+   * Our address sequence counter. The value that comes from
+   * monotonically increasing this is OR'd with JITMAP_MARK to denote
+   * the address name should come from the JIT map.
+   */
+  gsize addr_seq;
+
+  /* Our position in addr_buf. */
+  gsize addr_buf_pos;
+
+  /*
+   * The number of hash table items in @addr_hash. This is an
+   * optimization so that we can avoid calculating the number of strings
+   * when flushing out the jitmap.
+   */
+  guint addr_hash_size;
+
+  /* Capture file handle */
+  int fd;
+
+  /* Our write buffer for fd */
+  guint8 *buf;
+  gsize pos;
+  gsize len;
+
+  /* Statistics while recording */
+  SpCaptureStat stat;
+};
+
+#ifndef SP_DISABLE_GOBJECT
+G_DEFINE_BOXED_TYPE (SpCaptureWriter, sp_capture_writer,
+                     sp_capture_writer_ref, sp_capture_writer_unref)
+#endif
+
+static void
+sp_capture_writer_finalize (SpCaptureWriter *self)
+{
+  if (self != NULL)
+    {
+      sp_capture_writer_flush (self);
+      close (self->fd);
+      g_free (self->buf);
+      g_free (self);
+    }
+}
+
+SpCaptureWriter *
+sp_capture_writer_ref (SpCaptureWriter *self)
+{
+  g_assert (self != NULL);
+  g_assert (self->ref_count > 0);
+
+  g_atomic_int_inc (&self->ref_count);
+
+  return self;
+}
+
+void
+sp_capture_writer_unref (SpCaptureWriter *self)
+{
+  g_assert (self != NULL);
+  g_assert (self->ref_count > 0);
+
+  if (g_atomic_int_dec_and_test (&self->ref_count))
+    sp_capture_writer_finalize (self);
+}
+
+static gboolean
+sp_capture_writer_flush_data (SpCaptureWriter *self)
+{
+  const guint8 *buf;
+  gssize written;
+  gsize to_write;
+
+  g_assert (self != NULL);
+  g_assert (self->pos <= self->len);
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+
+  buf = self->buf;
+  to_write = self->pos;
+
+  while (to_write > 0)
+    {
+      written = write (self->fd, buf, to_write);
+      if (written < 0)
+        return FALSE;
+
+      if (written == 0 && errno != EAGAIN)
+        return FALSE;
+
+      g_assert (written <= (gssize)to_write);
+
+      buf += written;
+      to_write -= written;
+    }
+
+  self->pos = 0;
+
+  return TRUE;
+}
+
+static inline void
+sp_capture_writer_realign (gsize *pos)
+{
+  *pos = (*pos + SP_CAPTURE_ALIGN - 1) & ~(SP_CAPTURE_ALIGN - 1);
+}
+
+static inline gboolean
+sp_capture_writer_ensure_space_for (SpCaptureWriter *self,
+                                    gsize            len)
+{
+  if ((self->len - self->pos) < len)
+    {
+      if (!sp_capture_writer_flush_data (self))
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
+static gboolean
+sp_capture_writer_flush_jitmap (SpCaptureWriter *self)
+{
+  SpCaptureJitmap jitmap;
+  gssize r;
+  gsize len;
+
+  g_assert (self != NULL);
+
+  if (self->addr_hash_size == 0)
+    return TRUE;
+
+  g_assert (self->addr_buf_pos > 0);
+
+  len = sizeof jitmap + self->addr_buf_pos;
+
+  sp_capture_writer_realign (&len);
+
+  jitmap.frame.len = len;
+  jitmap.frame.cpu = -1;
+  jitmap.frame.pid = getpid ();
+  jitmap.frame.time = g_get_monotonic_time ();
+  jitmap.frame.type = SP_CAPTURE_FRAME_JITMAP;
+  jitmap.n_jitmaps = self->addr_hash_size;
+
+  if (sizeof jitmap != write (self->fd, &jitmap, sizeof jitmap))
+    return FALSE;
+
+  r = write (self->fd, self->addr_buf, len - sizeof jitmap);
+  if (r < 0 || (gsize)r != (len - sizeof jitmap))
+    return FALSE;
+
+  self->addr_buf_pos = 0;
+  self->addr_hash_size = 0;
+  memset (self->addr_hash, 0, sizeof self->addr_hash);
+
+  self->stat.frame_count[SP_CAPTURE_FRAME_JITMAP]++;
+
+  return TRUE;
+}
+
+static gboolean
+sp_capture_writer_lookup_jitmap (SpCaptureWriter  *self,
+                                 const gchar      *name,
+                                 SpCaptureAddress *addr)
+{
+  guint hash;
+  guint i;
+
+  g_assert (self != NULL);
+  g_assert (name != NULL);
+  g_assert (addr != NULL);
+
+  hash = g_str_hash (name) % G_N_ELEMENTS (self->addr_hash);
+
+  for (i = hash; i < G_N_ELEMENTS (self->addr_hash); i++)
+    {
+      SpCaptureJitmapBucket *bucket = &self->addr_hash[i];
+
+      if (bucket->str == NULL)
+        return FALSE;
+
+      if (strcmp (bucket->str, name) == 0)
+        {
+          *addr = bucket->addr;
+          return TRUE;
+        }
+    }
+
+  for (i = 0; i < hash; i++)
+    {
+      SpCaptureJitmapBucket *bucket = &self->addr_hash[i];
+
+      if (bucket->str == NULL)
+        return FALSE;
+
+      if (strcmp (bucket->str, name) == 0)
+        {
+          *addr = bucket->addr;
+          return TRUE;
+        }
+    }
+
+  return FALSE;
+}
+
+static SpCaptureAddress
+sp_capture_writer_insert_jitmap (SpCaptureWriter *self,
+                                 const gchar     *str)
+{
+  SpCaptureAddress addr;
+  gchar *dst;
+  gsize len;
+  guint hash;
+  guint i;
+
+  g_assert (self != NULL);
+  g_assert (str != NULL);
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+
+  len = sizeof addr + strlen (str) + 1;
+
+  if ((self->addr_hash_size == G_N_ELEMENTS (self->addr_hash)) ||
+      ((sizeof self->addr_buf - self->addr_buf_pos) < len))
+    {
+      if (!sp_capture_writer_flush_jitmap (self))
+        return INVALID_ADDRESS;
+
+      g_assert (self->addr_hash_size == 0);
+      g_assert (self->addr_buf_pos == 0);
+    }
+
+  g_assert (self->addr_hash_size < G_N_ELEMENTS (self->addr_hash));
+  g_assert (len > sizeof addr);
+
+  /* Allocate the next unique address */
+  addr = SP_CAPTURE_JITMAP_MARK | ++self->addr_seq;
+
+  /* Copy the address into the buffer */
+  dst = (gchar *)&self->addr_buf[self->addr_buf_pos];
+  memcpy (dst, &addr, sizeof addr);
+
+  /*
+   * Copy the string into the buffer, keeping dst around for
+   * when we insert into the hashtable.
+   */
+  dst += sizeof addr;
+  memcpy (dst, str, len - sizeof addr);
+
+  /* Advance our string cache position */
+  self->addr_buf_pos += len;
+  g_assert (self->addr_buf_pos <= sizeof self->addr_buf);
+
+  /* Now place the address into the hashtable */
+  hash = g_str_hash (str) % G_N_ELEMENTS (self->addr_hash);
+
+  /* Start from the current hash bucket and go forward */
+  for (i = hash; i < G_N_ELEMENTS (self->addr_hash); i++)
+    {
+      SpCaptureJitmapBucket *bucket = &self->addr_hash[i];
+
+      if (G_LIKELY (bucket->str == NULL))
+        {
+          bucket->str = dst;
+          bucket->addr = addr;
+          self->addr_hash_size++;
+          return addr;
+        }
+    }
+
+  /* Wrap around to the beginning */
+  for (i = 0; i < hash; i++)
+    {
+      SpCaptureJitmapBucket *bucket = &self->addr_hash[i];
+
+      if (G_LIKELY (bucket->str == NULL))
+        {
+          bucket->str = dst;
+          bucket->addr = addr;
+          self->addr_hash_size++;
+          return addr;
+        }
+    }
+
+  g_assert_not_reached ();
+
+  return INVALID_ADDRESS;
+}
+
+SpCaptureWriter *
+sp_capture_writer_new_from_fd (int   fd,
+                               gsize buffer_size)
+{
+  g_autofree gchar *nowstr = NULL;
+  SpCaptureWriter *self;
+  SpCaptureFileHeader *header;
+  GTimeVal tv;
+
+  if (buffer_size == 0)
+    buffer_size = DEFAULT_BUFFER_SIZE;
+
+  g_assert (fd != -1);
+  g_assert (buffer_size % getpagesize() == 0);
+
+  self = g_new0 (SpCaptureWriter, 1);
+  self->ref_count = 1;
+  self->fd = fd;
+  self->buf = (guint8 *)g_malloc (buffer_size);
+  self->len = buffer_size;
+
+  g_get_current_time (&tv);
+  nowstr = g_time_val_to_iso8601 (&tv);
+
+  header = (SpCaptureFileHeader *)(gpointer)self->buf;
+  header->magic = SP_CAPTURE_MAGIC;
+  header->version = 1;
+#ifdef G_LITTLE_ENDIAN
+  header->little_endian = TRUE;
+#else
+  header->little_endian = FALSE;
+#endif
+  header->padding = 0;
+  g_strlcpy (header->capture_time, nowstr, sizeof header->capture_time);
+  memset (header->suffix, 0, sizeof header->suffix);
+
+  self->pos += sizeof *header;
+
+  if (!sp_capture_writer_flush_data (self))
+    {
+      sp_capture_writer_finalize (self);
+      return NULL;
+    }
+
+  g_assert (self->pos == 0);
+  g_assert (self->len > 0);
+  g_assert (self->len % getpagesize() == 0);
+  g_assert (self->buf != NULL);
+  g_assert (self->addr_hash_size == 0);
+  g_assert (self->fd != -1);
+
+  return self;
+}
+
+SpCaptureWriter *
+sp_capture_writer_new (const gchar *filename,
+                       gsize        buffer_size)
+{
+  SpCaptureWriter *self;
+  int fd;
+
+  g_assert (filename != NULL);
+  g_assert (buffer_size % getpagesize() == 0);
+
+  if ((-1 == (fd = open (filename, O_CREAT | O_RDWR, 0640))) ||
+      (-1 == ftruncate (fd, 0L)))
+    return NULL;
+
+  self = sp_capture_writer_new_from_fd (fd, buffer_size);
+
+  if (self == NULL)
+    close (fd);
+
+  return self;
+}
+
+gboolean
+sp_capture_writer_add_map (SpCaptureWriter *self,
+                           gint64           time,
+                           gint             cpu,
+                           GPid             pid,
+                           guint64          start,
+                           guint64          end,
+                           guint64          offset,
+                           guint64          inode,
+                           const gchar     *filename)
+{
+  SpCaptureMap *ev;
+  gsize len;
+
+  if (filename == NULL)
+    filename = "";
+
+  g_assert (self != NULL);
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+  g_assert (filename != NULL);
+
+  len = sizeof *ev + strlen (filename) + 1;
+
+  sp_capture_writer_realign (&len);
+
+  if (!sp_capture_writer_ensure_space_for (self, len))
+    return FALSE;
+
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+
+  ev = (SpCaptureMap *)(gpointer)&self->buf[self->pos];
+  ev->frame.len = len;
+  ev->frame.cpu = cpu;
+  ev->frame.pid = pid;
+  ev->frame.time = time;
+  ev->frame.type = SP_CAPTURE_FRAME_MAP;
+  ev->frame.padding = 0;
+  ev->start = start;
+  ev->end = end;
+  ev->offset = offset;
+  ev->inode = inode;
+
+  g_strlcpy (ev->filename, filename, len - sizeof *ev);
+  ev->filename[len - sizeof *ev - 1] = '\0';
+
+  self->pos += ev->frame.len;
+
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+
+  self->stat.frame_count[SP_CAPTURE_FRAME_MAP]++;
+
+  return TRUE;
+}
+
+SpCaptureAddress
+sp_capture_writer_add_jitmap (SpCaptureWriter *self,
+                              const gchar     *name)
+{
+  SpCaptureAddress addr = INVALID_ADDRESS;
+
+  if (name == NULL)
+    name = "";
+
+  g_assert (self != NULL);
+  g_assert (name != NULL);
+
+  if (!sp_capture_writer_lookup_jitmap (self, name, &addr))
+    addr = sp_capture_writer_insert_jitmap (self, name);
+
+  return addr;
+}
+
+gboolean
+sp_capture_writer_add_process (SpCaptureWriter *self,
+                               gint64           time,
+                               gint             cpu,
+                               GPid             pid,
+                               const gchar     *cmdline)
+{
+  SpCaptureProcess *ev;
+  gsize len;
+
+  if (cmdline == NULL)
+    cmdline = "";
+
+  g_assert (self != NULL);
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+  g_assert (cmdline != NULL);
+
+  len = sizeof *ev + strlen (cmdline) + 1;
+
+  sp_capture_writer_realign (&len);
+
+  if (!sp_capture_writer_ensure_space_for (self, len))
+    return FALSE;
+
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+
+  ev = (SpCaptureProcess *)(gpointer)&self->buf[self->pos];
+  ev->frame.len = len;
+  ev->frame.cpu = cpu;
+  ev->frame.pid = pid;
+  ev->frame.time = time;
+  ev->frame.type = SP_CAPTURE_FRAME_PROCESS;
+  ev->frame.padding = 0;
+
+  g_strlcpy (ev->cmdline, cmdline, len - sizeof *ev);
+  ev->cmdline[len - sizeof *ev - 1] = '\0';
+
+  self->pos += ev->frame.len;
+
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+
+  self->stat.frame_count[SP_CAPTURE_FRAME_PROCESS]++;
+
+  return TRUE;
+}
+
+gboolean
+sp_capture_writer_add_sample (SpCaptureWriter        *self,
+                              gint64                  time,
+                              gint                    cpu,
+                              GPid                    pid,
+                              const SpCaptureAddress *addrs,
+                              guint                   n_addrs)
+{
+  SpCaptureSample *ev;
+  gsize len;
+
+  g_assert (self != NULL);
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+
+  len = sizeof *ev + (n_addrs * sizeof (SpCaptureAddress));
+
+  sp_capture_writer_realign (&len);
+
+  if (!sp_capture_writer_ensure_space_for (self, len))
+    return FALSE;
+
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+
+  ev = (SpCaptureSample *)(gpointer)&self->buf[self->pos];
+  ev->frame.len = len;
+  ev->frame.cpu = cpu;
+  ev->frame.pid = pid;
+  ev->frame.time = time;
+  ev->frame.type = SP_CAPTURE_FRAME_SAMPLE;
+  ev->frame.padding = 0;
+  ev->n_addrs = n_addrs;
+
+  memcpy (ev->addrs, addrs, (n_addrs * sizeof (SpCaptureAddress)));
+
+  self->pos += ev->frame.len;
+
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+
+  self->stat.frame_count[SP_CAPTURE_FRAME_SAMPLE]++;
+
+  return TRUE;
+}
+
+gboolean
+sp_capture_writer_add_fork (SpCaptureWriter *self,
+                            gint64           time,
+                            gint             cpu,
+                            GPid             pid,
+                            GPid             child_pid)
+{
+  SpCaptureFork *ev;
+  gsize len = sizeof *ev;
+
+  g_assert (self != NULL);
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+
+  sp_capture_writer_realign (&len);
+
+  if (!sp_capture_writer_ensure_space_for (self, len))
+    return FALSE;
+
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+
+  ev = (SpCaptureFork *)(gpointer)&self->buf[self->pos];
+  ev->frame.len = len;
+  ev->frame.cpu = cpu;
+  ev->frame.pid = pid;
+  ev->frame.time = time;
+  ev->frame.type = SP_CAPTURE_FRAME_FORK;
+  ev->frame.padding = 0;
+  ev->child_pid = child_pid;
+
+  self->pos += ev->frame.len;
+
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+
+  self->stat.frame_count[SP_CAPTURE_FRAME_FORK]++;
+
+  return TRUE;
+}
+
+gboolean
+sp_capture_writer_add_exit (SpCaptureWriter *self,
+                            gint64           time,
+                            gint             cpu,
+                            GPid             pid)
+{
+  SpCaptureExit *ev;
+  gsize len = sizeof *ev;
+
+  g_assert (self != NULL);
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+
+  sp_capture_writer_realign (&len);
+
+  if (!sp_capture_writer_ensure_space_for (self, len))
+    return FALSE;
+
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+
+  ev = (SpCaptureExit *)(gpointer)&self->buf[self->pos];
+  ev->frame.len = len;
+  ev->frame.cpu = cpu;
+  ev->frame.pid = pid;
+  ev->frame.time = time;
+  ev->frame.type = SP_CAPTURE_FRAME_EXIT;
+  ev->frame.padding = 0;
+
+  self->pos += ev->frame.len;
+
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+
+  self->stat.frame_count[SP_CAPTURE_FRAME_EXIT]++;
+
+  return TRUE;
+}
+
+gboolean
+sp_capture_writer_add_timestamp (SpCaptureWriter *self,
+                                 gint64           time,
+                                 gint             cpu,
+                                 GPid             pid)
+{
+  SpCaptureTimestamp *ev;
+  gsize len = sizeof *ev;
+
+  g_assert (self != NULL);
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+
+  sp_capture_writer_realign (&len);
+
+  if (!sp_capture_writer_ensure_space_for (self, len))
+    return FALSE;
+
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+
+  ev = (SpCaptureTimestamp *)(gpointer)&self->buf[self->pos];
+  ev->frame.len = len;
+  ev->frame.cpu = cpu;
+  ev->frame.pid = pid;
+  ev->frame.time = time;
+  ev->frame.type = SP_CAPTURE_FRAME_TIMESTAMP;
+  ev->frame.padding = 0;
+
+  self->pos += ev->frame.len;
+
+  g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0);
+
+  self->stat.frame_count[SP_CAPTURE_FRAME_TIMESTAMP]++;
+
+  return TRUE;
+}
+
+gboolean
+sp_capture_writer_flush (SpCaptureWriter *self)
+{
+  g_assert (self != NULL);
+
+  return (sp_capture_writer_flush_jitmap (self) &&
+          sp_capture_writer_flush_data (self));
+}
+
+/**
+ * sp_capture_writer_save_as:
+ * @self: A #SpCaptureWriter
+ * @filename: the file to save the capture as
+ * @error: a location for a #GError or %NULL.
+ *
+ * Saves the captured data as the file @filename.
+ *
+ * This is primarily useful if the writer was created with a memory-backed
+ * file-descriptor such as a memfd or tmpfs file on Linux.
+ *
+ * Returns: %TRUE if successful, otherwise %FALSE and @error is set.
+ */
+gboolean
+sp_capture_writer_save_as (SpCaptureWriter            *self,
+                           const gchar                *filename,
+                           GError                    **error)
+{
+  gsize to_write;
+  off_t in_off;
+  off_t pos;
+  int fd = -1;
+
+  g_assert (self != NULL);
+  g_assert (self->fd != -1);
+  g_assert (filename != NULL);
+
+  if (-1 == (fd = open (filename, O_CREAT | O_RDWR, 0640)))
+    goto handle_errno;
+
+  if (!sp_capture_writer_flush (self))
+    goto handle_errno;
+
+  if (-1 == (pos = lseek (self->fd, 0L, SEEK_CUR)))
+    goto handle_errno;
+
+  to_write = pos;
+  in_off = 0;
+
+  while (to_write > 0)
+    {
+      gssize written;
+
+      written = sendfile (fd, self->fd, &in_off, pos);
+
+      if (written < 0)
+        goto handle_errno;
+
+      if (written == 0 && errno != EAGAIN)
+        goto handle_errno;
+
+      g_assert (written <= (gssize)to_write);
+
+      to_write -= written;
+    }
+
+  close (fd);
+
+  return TRUE;
+
+handle_errno:
+  g_set_error (error,
+               G_FILE_ERROR,
+               g_file_error_from_errno (errno),
+               "%s", g_strerror (errno));
+
+  if (fd != -1)
+    {
+      close (fd);
+      g_unlink (filename);
+    }
+
+  return FALSE;
+}
+
+/**
+ * _sp_capture_writer_splice_from_fd:
+ * @self: An #SpCaptureWriter
+ * @fd: the fd to read from.
+ * @error: A location for a #GError, or %NULL.
+ *
+ * This is internal API for SpCaptureWriter and SpCaptureReader to
+ * communicate when splicing a reader into a writer.
+ *
+ * This should not be used outside of #SpCaptureReader or
+ * #SpCaptureWriter.
+ *
+ * This will not advance the position of @fd.
+ *
+ * Returns: %TRUE if successful; otherwise %FALSE and @error is set.
+ */
+gboolean
+_sp_capture_writer_splice_from_fd (SpCaptureWriter  *self,
+                                   int               fd,
+                                   GError          **error)
+{
+  struct stat stbuf;
+  off_t in_off;
+  gsize to_write;
+
+  g_assert (self != NULL);
+  g_assert (self->fd != -1);
+
+  if (-1 == fstat (fd, &stbuf))
+    goto handle_errno;
+
+  if (stbuf.st_size < 256)
+    {
+      g_set_error (error,
+                   G_FILE_ERROR,
+                   G_FILE_ERROR_INVAL,
+                   "Cannot splice, possibly corrupt file.");
+      return FALSE;
+    }
+
+  in_off = 256;
+  to_write = stbuf.st_size - in_off;
+
+  while (to_write > 0)
+    {
+      gssize written;
+
+      written = sendfile (self->fd, fd, &in_off, to_write);
+
+      if (written < 0)
+        goto handle_errno;
+
+      if (written == 0 && errno != EAGAIN)
+        goto handle_errno;
+
+      g_assert (written <= (gssize)to_write);
+
+      to_write -= written;
+    }
+
+  return TRUE;
+
+handle_errno:
+  g_set_error (error,
+               G_FILE_ERROR,
+               g_file_error_from_errno (errno),
+               "%s", g_strerror (errno));
+
+  return FALSE;
+}
+
+/**
+ * sp_capture_writer_splice:
+ * @self: An #SpCaptureWriter
+ * @dest: An #SpCaptureWriter
+ * @error: A location for a #GError, or %NULL.
+ *
+ * This function will copy the capture @self into the capture @dest.  This
+ * tries to be semi-efficient by using sendfile() to copy the contents between
+ * the captures. @self and @dest will be flushed before the contents are copied
+ * into the @dest file-descriptor.
+ *
+ * Returns: %TRUE if successful, otherwise %FALSE and and @error is set.
+ */
+gboolean
+sp_capture_writer_splice (SpCaptureWriter  *self,
+                          SpCaptureWriter  *dest,
+                          GError          **error)
+{
+  gboolean ret;
+  off_t pos;
+
+  g_assert (self != NULL);
+  g_assert (self->fd != -1);
+  g_assert (dest != NULL);
+  g_assert (dest->fd != -1);
+
+  /* Flush before writing anything to ensure consistency */
+  if (!sp_capture_writer_flush (self) || !sp_capture_writer_flush (dest))
+    goto handle_errno;
+
+  /* Track our current position so we can reset */
+  if ((off_t)-1 == (pos = lseek (self->fd, 0L, SEEK_CUR)))
+    goto handle_errno;
+
+  /* Perform the splice */
+  ret = _sp_capture_writer_splice_from_fd (dest, self->fd, error);
+
+  /* Now reset or file-descriptor position (it should be the same */
+  if (pos != lseek (self->fd, pos, SEEK_SET))
+    {
+      ret = FALSE;
+      goto handle_errno;
+    }
+
+  return ret;
+
+handle_errno:
+  g_set_error (error,
+               G_FILE_ERROR,
+               g_file_error_from_errno (errno),
+               "%s", g_strerror (errno));
+
+  return FALSE;
+}
+
+/**
+ * sp_capture_writer_create_reader:
+ * @self: A #SpCaptureWriter
+ * @error: a location for a #GError, or %NULL
+ *
+ * Creates a new reader for the writer.
+ *
+ * Since readers use positioned reads, this uses the same file-descriptor for
+ * the #SpCaptureReader. Therefore, if you are writing to the capture while
+ * also consuming from the reader, you could get transient failures unless you
+ * synchronize the operations.
+ *
+ * Returns: (transfer full): A #SpCaptureReader.
+ */
+SpCaptureReader *
+sp_capture_writer_create_reader (SpCaptureWriter  *self,
+                                 GError          **error)
+{
+  g_return_val_if_fail (self != NULL, NULL);
+  g_return_val_if_fail (self->fd != -1, NULL);
+
+  return sp_capture_reader_new_from_fd (self->fd, error);
+}
+
+/**
+ * sp_capture_writer_stat:
+ * @self: A #SpCaptureWriter
+ * @stat: (out): A location for an #SpCaptureStat
+ *
+ * This function will fill @stat with statistics generated while capturing
+ * the profiler session.
+ */
+void
+sp_capture_writer_stat (SpCaptureWriter *self,
+                        SpCaptureStat   *stat)
+{
+  g_return_if_fail (self != NULL);
+  g_return_if_fail (stat != NULL);
+
+  *stat = self->stat;
+}
diff --git a/lib/sp-capture-writer.h b/lib/sp-capture-writer.h
new file mode 100644
index 0000000..1846fd1
--- /dev/null
+++ b/lib/sp-capture-writer.h
@@ -0,0 +1,108 @@
+/* sp-capture-writer.h
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This file 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
+ * Lesser 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/>.
+ */
+
+#ifndef SP_CAPTURE_WRITER_H
+#define SP_CAPTURE_WRITER_H
+
+#include "sp-capture-types.h"
+
+G_BEGIN_DECLS
+
+typedef struct _SpCaptureWriter SpCaptureWriter;
+
+typedef struct
+{
+  /*
+   * The number of frames indexed by SpCaptureFrameType
+   */
+  gsize frame_count[16];
+
+  /*
+   * Padding for future expansion.
+   */
+  gsize padding[48];
+} SpCaptureStat;
+
+SpCaptureWriter    *sp_capture_writer_new             (const gchar             *filename,
+                                                       gsize                    buffer_size);
+SpCaptureWriter    *sp_capture_writer_new_from_fd     (int                      fd,
+                                                       gsize                    buffer_size);
+SpCaptureWriter    *sp_capture_writer_ref             (SpCaptureWriter         *self);
+void                sp_capture_writer_unref           (SpCaptureWriter         *self);
+void                sp_capture_writer_stat            (SpCaptureWriter         *self,
+                                                       SpCaptureStat           *stat);
+gboolean            sp_capture_writer_add_map         (SpCaptureWriter         *self,
+                                                       gint64                   time,
+                                                       gint                     cpu,
+                                                       GPid                     pid,
+                                                       guint64                  start,
+                                                       guint64                  end,
+                                                       guint64                  offset,
+                                                       guint64                  inode,
+                                                       const gchar             *filename);
+guint64             sp_capture_writer_add_jitmap      (SpCaptureWriter         *self,
+                                                       const gchar             *name);
+gboolean            sp_capture_writer_add_process     (SpCaptureWriter         *self,
+                                                       gint64                   time,
+                                                       gint                     cpu,
+                                                       GPid                     pid,
+                                                       const gchar             *cmdline);
+gboolean            sp_capture_writer_add_sample      (SpCaptureWriter         *self,
+                                                       gint64                   time,
+                                                       gint                     cpu,
+                                                       GPid                     pid,
+                                                       const SpCaptureAddress  *addrs,
+                                                       guint                    n_addrs);
+gboolean            sp_capture_writer_add_fork        (SpCaptureWriter         *self,
+                                                       gint64                   time,
+                                                       gint                     cpu,
+                                                       GPid                     pid,
+                                                       GPid                     child_pid);
+gboolean            sp_capture_writer_add_exit        (SpCaptureWriter         *self,
+                                                       gint64                   time,
+                                                       gint                     cpu,
+                                                       GPid                     pid);
+gboolean            sp_capture_writer_add_timestamp   (SpCaptureWriter         *self,
+                                                       gint64                   time,
+                                                       gint                     cpu,
+                                                       GPid                     pid);
+gboolean            sp_capture_writer_flush           (SpCaptureWriter         *self);
+gboolean            sp_capture_writer_save_as         (SpCaptureWriter         *self,
+                                                       const gchar             *filename,
+                                                       GError                 **error);
+SpCaptureReader    *sp_capture_writer_create_reader   (SpCaptureWriter         *self,
+                                                       GError                 **error);
+gboolean            sp_capture_writer_splice          (SpCaptureWriter         *self,
+                                                       SpCaptureWriter         *dest,
+                                                       GError                 **error);
+gboolean            _sp_capture_writer_splice_from_fd (SpCaptureWriter         *self,
+                                                       int                      fd,
+                                                       GError                 **error) G_GNUC_INTERNAL;
+
+#ifndef SP_DISABLE_GOBJECT
+# define SP_TYPE_CAPTURE_WRITER (sp_capture_writer_get_type())
+  GType sp_capture_writer_get_type (void);
+#endif
+
+#if GLIB_CHECK_VERSION(2, 44, 0)
+  G_DEFINE_AUTOPTR_CLEANUP_FUNC (SpCaptureWriter, sp_capture_writer_unref)
+#endif
+
+G_END_DECLS
+
+#endif /* SP_CAPTURE_WRITER_H */
diff --git a/lib/sp-cell-renderer-percent.c b/lib/sp-cell-renderer-percent.c
new file mode 100644
index 0000000..4f5fe2b
--- /dev/null
+++ b/lib/sp-cell-renderer-percent.c
@@ -0,0 +1,135 @@
+/* sp-cell-renderer-percent.c
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#include <glib/gi18n.h>
+
+#include "sp-cell-renderer-percent.h"
+
+typedef struct
+{
+  gdouble percent;
+} SpCellRendererPercentPrivate;
+
+enum {
+  PROP_0,
+  PROP_PERCENT,
+  N_PROPS
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (SpCellRendererPercent, sp_cell_renderer_percent, GTK_TYPE_CELL_RENDERER_TEXT)
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+sp_cell_renderer_percent_get_property (GObject    *object,
+                                       guint       prop_id,
+                                       GValue     *value,
+                                       GParamSpec *pspec)
+{
+  SpCellRendererPercent *self = SP_CELL_RENDERER_PERCENT (object);
+
+  switch (prop_id)
+    {
+    case PROP_PERCENT:
+      g_value_set_double (value, sp_cell_renderer_percent_get_percent (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+sp_cell_renderer_percent_set_property (GObject      *object,
+                                       guint         prop_id,
+                                       const GValue *value,
+                                       GParamSpec   *pspec)
+{
+  SpCellRendererPercent *self = SP_CELL_RENDERER_PERCENT (object);
+
+  switch (prop_id)
+    {
+    case PROP_PERCENT:
+      sp_cell_renderer_percent_set_percent (self, g_value_get_double (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+sp_cell_renderer_percent_class_init (SpCellRendererPercentClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->get_property = sp_cell_renderer_percent_get_property;
+  object_class->set_property = sp_cell_renderer_percent_set_property;
+
+  properties [PROP_PERCENT] =
+    g_param_spec_double ("percent",
+                         "Percent",
+                         "Percent",
+                         0.0,
+                         100.0,
+                         0.0,
+                         (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+sp_cell_renderer_percent_init (SpCellRendererPercent *self)
+{
+  g_object_set (self, "xalign", 1.0f, NULL);
+}
+
+gdouble
+sp_cell_renderer_percent_get_percent (SpCellRendererPercent *self)
+{
+  SpCellRendererPercentPrivate *priv = sp_cell_renderer_percent_get_instance_private (self);
+
+  g_return_val_if_fail (SP_IS_CELL_RENDERER_PERCENT (self), 0.0);
+
+  return priv->percent;
+}
+
+void
+sp_cell_renderer_percent_set_percent (SpCellRendererPercent *self,
+                                      gdouble                percent)
+{
+  SpCellRendererPercentPrivate *priv = sp_cell_renderer_percent_get_instance_private (self);
+
+  g_return_if_fail (SP_IS_CELL_RENDERER_PERCENT (self));
+  g_return_if_fail (percent >= 0.0);
+  g_return_if_fail (percent <= 100.0);
+
+  if (percent != priv->percent)
+    {
+      gchar text[128];
+
+      priv->percent = percent;
+
+      g_snprintf (text, sizeof text, "%.2lf<span size='smaller'><span size='smaller'> </span>%%</span>", 
percent);
+      text [sizeof text - 1] = '\0';
+
+      g_object_set (self, "markup", text, NULL);
+
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_PERCENT]);
+    }
+}
diff --git a/lib/sp-cell-renderer-percent.h b/lib/sp-cell-renderer-percent.h
new file mode 100644
index 0000000..1c747b2
--- /dev/null
+++ b/lib/sp-cell-renderer-percent.h
@@ -0,0 +1,55 @@
+/* sp-cell-renderer-percent.h
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_CELL_RENDERER_PERCENT_H
+#define SP_CELL_RENDERER_PERCENT_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_CELL_RENDERER_PERCENT            (sp_cell_renderer_percent_get_type())
+#define SP_CELL_RENDERER_PERCENT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
SP_TYPE_CELL_RENDERER_PERCENT, SpCellRendererPercent))
+#define SP_CELL_RENDERER_PERCENT_CONST(obj)      (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
SP_TYPE_CELL_RENDERER_PERCENT, SpCellRendererPercent const))
+#define SP_CELL_RENDERER_PERCENT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  
SP_TYPE_CELL_RENDERER_PERCENT, SpCellRendererPercentClass))
+#define SP_IS_CELL_RENDERER_PERCENT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
SP_TYPE_CELL_RENDERER_PERCENT))
+#define SP_IS_CELL_RENDERER_PERCENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  
SP_TYPE_CELL_RENDERER_PERCENT))
+#define SP_CELL_RENDERER_PERCENT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  
SP_TYPE_CELL_RENDERER_PERCENT, SpCellRendererPercentClass))
+
+typedef struct _SpCellRendererPercent      SpCellRendererPercent;
+typedef struct _SpCellRendererPercentClass SpCellRendererPercentClass;
+
+struct _SpCellRendererPercent
+{
+  GtkCellRendererText parent;
+};
+
+struct _SpCellRendererPercentClass
+{
+  GtkCellRendererTextClass parent_class;
+};
+
+GType            sp_cell_renderer_percent_get_type    (void);
+GtkCellRenderer *sp_cell_renderer_percent_new         (void);
+gdouble          sp_cell_renderer_percent_get_percent (SpCellRendererPercent *self);
+void             sp_cell_renderer_percent_set_percent (SpCellRendererPercent *self,
+                                                       gdouble                percent);
+
+G_END_DECLS
+
+#endif /* SP_CELL_RENDERER_PERCENT_H */
diff --git a/lib/sp-clock.c b/lib/sp-clock.c
new file mode 100644
index 0000000..4d34ad8
--- /dev/null
+++ b/lib/sp-clock.c
@@ -0,0 +1,51 @@
+/* sp-clock.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#include "sp-clock.h"
+
+gint sp_clock = -1;
+
+void
+sp_clock_init (void)
+{
+  static const gint clock_ids[] = {
+    CLOCK_MONOTONIC_RAW,
+    CLOCK_MONOTONIC_COARSE,
+    CLOCK_MONOTONIC,
+    CLOCK_REALTIME_COARSE,
+    CLOCK_REALTIME,
+  };
+  guint i;
+
+  if (sp_clock != -1)
+    return;
+
+  for (i = 0; i < G_N_ELEMENTS (clock_ids); i++)
+    {
+      struct timespec ts;
+      int clock_id = clock_ids [i];
+
+      if (0 == clock_gettime (clock_id, &ts))
+        {
+          sp_clock = clock_id;
+          return;
+        }
+    }
+
+  g_assert_not_reached ();
+}
diff --git a/lib/sp-clock.h b/lib/sp-clock.h
new file mode 100644
index 0000000..a38c172
--- /dev/null
+++ b/lib/sp-clock.h
@@ -0,0 +1,54 @@
+/* sp-clock.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_CLOCK_H
+#define SP_CLOCK_H
+
+#include <glib.h>
+#include <time.h>
+
+G_BEGIN_DECLS
+
+typedef gint SpClock;
+typedef gint64 SpTimeStamp;
+typedef gint32 SpTimeSpan;
+
+extern SpClock sp_clock;
+
+static inline SpTimeStamp
+sp_clock_get_current_time (void)
+{
+  struct timespec ts;
+
+  clock_gettime (sp_clock, &ts);
+
+  return (ts.tv_sec * G_GINT64_CONSTANT (1000000000)) + ts.tv_nsec;
+}
+
+static inline SpTimeSpan
+sp_clock_get_relative_time (SpTimeStamp epoch)
+{
+  return sp_clock_get_current_time () - epoch;
+}
+
+void sp_clock_init (void);
+
+G_END_DECLS
+
+#endif /* SP_CLOCK_H */
+
diff --git a/lib/sp-elf-symbol-resolver.c b/lib/sp-elf-symbol-resolver.c
new file mode 100644
index 0000000..2c7cf23
--- /dev/null
+++ b/lib/sp-elf-symbol-resolver.c
@@ -0,0 +1,276 @@
+/* sp-elf-symbol-resolver.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#include <string.h>
+
+#include "binfile.h"
+#include "elfparser.h"
+
+#include "sp-map-lookaside.h"
+#include "sp-elf-symbol-resolver.h"
+
+struct _SpElfSymbolResolver
+{
+  GObject     parent_instance;
+
+  GHashTable *lookasides;
+  GHashTable *bin_files;
+  GHashTable *tag_cache;
+};
+
+static void symbol_resolver_iface_init (SpSymbolResolverInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (SpElfSymbolResolver,
+                        sp_elf_symbol_resolver,
+                        G_TYPE_OBJECT,
+                        0,
+                        G_IMPLEMENT_INTERFACE (SP_TYPE_SYMBOL_RESOLVER,
+                                               symbol_resolver_iface_init))
+
+static void
+sp_elf_symbol_resolver_finalize (GObject *object)
+{
+  SpElfSymbolResolver *self = (SpElfSymbolResolver *)object;
+
+  g_clear_pointer (&self->bin_files, g_hash_table_unref);
+  g_clear_pointer (&self->lookasides, g_hash_table_unref);
+  g_clear_pointer (&self->tag_cache, g_hash_table_unref);
+
+  G_OBJECT_CLASS (sp_elf_symbol_resolver_parent_class)->finalize (object);
+}
+
+static void
+sp_elf_symbol_resolver_class_init (SpElfSymbolResolverClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = sp_elf_symbol_resolver_finalize;
+}
+
+static void
+sp_elf_symbol_resolver_init (SpElfSymbolResolver *self)
+{
+  self->lookasides = g_hash_table_new_full (NULL,
+                                            NULL,
+                                            NULL,
+                                            (GDestroyNotify)sp_map_lookaside_free);
+
+  self->bin_files = g_hash_table_new_full (g_str_hash,
+                                           g_str_equal,
+                                           g_free,
+                                           (GDestroyNotify)bin_file_free);
+
+  self->tag_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+}
+
+static void
+sp_elf_symbol_resolver_load (SpSymbolResolver *resolver,
+                             SpCaptureReader  *reader)
+{
+  SpElfSymbolResolver *self = (SpElfSymbolResolver *)resolver;
+  SpCaptureFrameType type;
+
+  g_assert (SP_IS_SYMBOL_RESOLVER (resolver));
+  g_assert (reader != NULL);
+
+  sp_capture_reader_reset (reader);
+
+  while (sp_capture_reader_peek_type (reader, &type))
+    {
+      const SpCaptureMap *ev;
+      SpMapLookaside *lookaside;
+      SpMap map;
+
+      if (type != SP_CAPTURE_FRAME_MAP)
+        {
+          if (!sp_capture_reader_skip (reader))
+            return;
+          continue;
+        }
+
+      ev = sp_capture_reader_read_map (reader);
+
+      map.start = ev->start;
+      map.end = ev->end;
+      map.offset = ev->offset;
+      map.inode = ev->inode;
+      map.filename = ev->filename;
+
+      lookaside = g_hash_table_lookup (self->lookasides, GINT_TO_POINTER (ev->frame.pid));
+
+      if (lookaside == NULL)
+        {
+          lookaside = sp_map_lookaside_new ();
+          g_hash_table_insert (self->lookasides, GINT_TO_POINTER (ev->frame.pid), lookaside);
+        }
+
+      sp_map_lookaside_insert (lookaside, &map);
+    }
+}
+
+static bin_file_t *
+sp_elf_symbol_resolver_get_bin_file (SpElfSymbolResolver *self,
+                                     const gchar         *filename)
+{
+  bin_file_t *bin_file;
+
+  g_assert (SP_IS_ELF_SYMBOL_RESOLVER (self));
+
+  bin_file = g_hash_table_lookup (self->bin_files, filename);
+
+  if (bin_file == NULL)
+    {
+      bin_file = bin_file_new (filename);
+      g_hash_table_insert (self->bin_files, g_strdup (filename), bin_file);
+    }
+
+  return bin_file;
+}
+
+static GQuark
+guess_tag (SpElfSymbolResolver *self,
+           const SpMap         *map)
+{
+  g_assert (map != NULL);
+  g_assert (map->filename != NULL);
+
+  if (!g_hash_table_contains (self->tag_cache, map->filename))
+    {
+      GQuark tag = 0;
+
+      if (strstr (map->filename, "/libgobject-2.0."))
+        tag = g_quark_from_static_string ("GObject");
+
+      else if (strstr (map->filename, "/libglib-2.0."))
+        tag = g_quark_from_static_string ("GLib");
+
+      else if (strstr (map->filename, "/libgio-2.0."))
+        tag = g_quark_from_static_string ("Gio");
+
+      else if (strstr (map->filename, "/libgtk-3."))
+        tag = g_quark_from_static_string ("Gtk+");
+
+      else if (strstr (map->filename, "/libgdk-3."))
+        tag = g_quark_from_static_string ("Gdk");
+
+      else if (strstr (map->filename, "/libpixman-1"))
+        tag = g_quark_from_static_string ("Pixman");
+
+      else if (strstr (map->filename, "/libcairo."))
+        tag = g_quark_from_static_string ("cairo");
+
+      else if (strstr (map->filename, "/libgstreamer-1."))
+        tag = g_quark_from_static_string ("GStreamer");
+
+      else if (strstr (map->filename, "/libX11."))
+        tag = g_quark_from_static_string ("X11");
+
+      else if (strstr (map->filename, "/libpango-1.0."))
+        tag = g_quark_from_static_string ("Pango");
+
+      else if (strstr (map->filename, "/libclutter-"))
+        tag = g_quark_from_static_string ("Clutter");
+
+      else if (strstr (map->filename, "/libcogl.") ||
+               strstr (map->filename, "/libcogl-"))
+        tag = g_quark_from_static_string ("Cogl");
+
+      else if (strstr (map->filename, "/libffi."))
+        tag = g_quark_from_static_string ("libffi");
+
+      else if (strstr (map->filename, "/libwayland-"))
+        tag = g_quark_from_static_string ("Wayland");
+
+      else if (strstr (map->filename, "/libinput."))
+        tag = g_quark_from_static_string ("libinput");
+
+      else if (strstr (map->filename, "/libgjs."))
+        tag = g_quark_from_static_string ("Gjs");
+
+      else if (strstr (map->filename, "/libmozjs-"))
+        tag = g_quark_from_static_string ("MozJS");
+
+      else if (strstr (map->filename, "/libGL."))
+        tag = g_quark_from_static_string ("GL");
+
+      else if (strstr (map->filename, "/libEGL."))
+        tag = g_quark_from_static_string ("EGL");
+
+      g_hash_table_insert (self->tag_cache,
+                           g_strdup (map->filename),
+                           GSIZE_TO_POINTER (tag));
+    }
+
+  return GPOINTER_TO_SIZE (g_hash_table_lookup (self->tag_cache, map->filename));
+}
+
+static gchar *
+sp_elf_symbol_resolver_resolve (SpSymbolResolver *resolver,
+                                guint64           time,
+                                GPid              pid,
+                                SpCaptureAddress  address,
+                                GQuark           *tag)
+{
+  SpElfSymbolResolver *self = (SpElfSymbolResolver *)resolver;
+  const bin_symbol_t *bin_sym;
+  SpMapLookaside *lookaside;
+  const gchar *bin_sym_name;
+  const SpMap *map;
+  bin_file_t *bin_file;
+
+  g_assert (SP_IS_ELF_SYMBOL_RESOLVER (self));
+
+  lookaside = g_hash_table_lookup (self->lookasides, GINT_TO_POINTER (pid));
+  if (lookaside == NULL)
+    return NULL;
+
+  map = sp_map_lookaside_lookup (lookaside, address);
+  if (map == NULL)
+    return NULL;
+
+  address -= map->start;
+  address += map->offset;
+
+  bin_file = sp_elf_symbol_resolver_get_bin_file (self, map->filename);
+
+  g_assert (bin_file != NULL);
+
+  if (map->inode && !bin_file_check_inode (bin_file, map->inode))
+    return g_strdup_printf ("%s: inode mismatch", map->filename);
+
+  bin_sym = bin_file_lookup_symbol (bin_file, address);
+  bin_sym_name = bin_symbol_get_name (bin_file, bin_sym);
+
+  if (map->filename)
+    *tag = guess_tag (self, map);
+
+  return elf_demangle (bin_sym_name);
+}
+
+static void
+symbol_resolver_iface_init (SpSymbolResolverInterface *iface)
+{
+  iface->load = sp_elf_symbol_resolver_load;
+  iface->resolve = sp_elf_symbol_resolver_resolve;
+}
+
+SpSymbolResolver *
+sp_elf_symbol_resolver_new (void)
+{
+  return g_object_new (SP_TYPE_ELF_SYMBOL_RESOLVER, NULL);
+}
diff --git a/lib/sp-elf-symbol-resolver.h b/lib/sp-elf-symbol-resolver.h
new file mode 100644
index 0000000..3b359af
--- /dev/null
+++ b/lib/sp-elf-symbol-resolver.h
@@ -0,0 +1,34 @@
+/* sp-elf-symbol-resolver.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_ELF_SYMBOL_RESOLVER_H
+#define SP_ELF_SYMBOL_RESOLVER_H
+
+#include "sp-symbol-resolver.h"
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_ELF_SYMBOL_RESOLVER (sp_elf_symbol_resolver_get_type())
+
+G_DECLARE_FINAL_TYPE (SpElfSymbolResolver, sp_elf_symbol_resolver, SP, ELF_SYMBOL_RESOLVER, GObject)
+
+SpSymbolResolver *sp_elf_symbol_resolver_new (void);
+
+G_END_DECLS
+
+#endif /* SP_ELF_SYMBOL_RESOLVER_H */
diff --git a/lib/sp-empty-state-view.c b/lib/sp-empty-state-view.c
new file mode 100644
index 0000000..8164fdc
--- /dev/null
+++ b/lib/sp-empty-state-view.c
@@ -0,0 +1,41 @@
+/* sp-empty-state-view.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#include "sp-empty-state-view.h"
+
+G_DEFINE_TYPE (SpEmptyStateView, sp_empty_state_view, GTK_TYPE_BIN)
+
+GtkWidget *
+sp_empty_state_view_new (void)
+{
+  return g_object_new (SP_TYPE_EMPTY_STATE_VIEW, NULL);
+}
+
+static void
+sp_empty_state_view_class_init (SpEmptyStateViewClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sp-empty-state-view.ui");
+}
+
+static void
+sp_empty_state_view_init (SpEmptyStateView *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
diff --git a/lib/sp-empty-state-view.h b/lib/sp-empty-state-view.h
new file mode 100644
index 0000000..d9f79bb
--- /dev/null
+++ b/lib/sp-empty-state-view.h
@@ -0,0 +1,40 @@
+/* sp-empty-state-view.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_EMPTY_STATE_VIEW_H
+#define SP_EMPTY_STATE_VIEW_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_EMPTY_STATE_VIEW (sp_empty_state_view_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (SpEmptyStateView, sp_empty_state_view, SP, EMPTY_STATE_VIEW, GtkBin)
+
+struct _SpEmptyStateViewClass
+{
+  GtkBinClass parent;
+};
+
+GtkWidget *sp_empty_state_view_new (void);
+
+G_END_DECLS
+
+#endif /* SP_EMPTY_STATE_VIEW_H */
+
diff --git a/lib/sp-error.c b/lib/sp-error.c
new file mode 100644
index 0000000..5a3b44b
--- /dev/null
+++ b/lib/sp-error.c
@@ -0,0 +1,30 @@
+/* sp-error.c
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#include "sp-error.h"
+
+GQuark
+sp_error_quark (void)
+{
+  static GQuark quark;
+
+  if (G_UNLIKELY (!quark))
+    quark = g_quark_from_static_string ("sp-error-quark");
+
+  return quark;
+}
diff --git a/lib/sp-error.h b/lib/sp-error.h
new file mode 100644
index 0000000..ef8f165
--- /dev/null
+++ b/lib/sp-error.h
@@ -0,0 +1,32 @@
+/* sp-error.h
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_ERROR_H
+#define SP_ERROR_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#define SP_ERROR (sp_error_quark())
+
+GQuark sp_error_quark (void);
+
+G_END_DECLS
+
+#endif /* SP_ERROR_H */
diff --git a/lib/sp-failed-state-view.c b/lib/sp-failed-state-view.c
new file mode 100644
index 0000000..17021aa
--- /dev/null
+++ b/lib/sp-failed-state-view.c
@@ -0,0 +1,42 @@
+/* sp-failed-state-view.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#include "sp-failed-state-view.h"
+
+G_DEFINE_TYPE (SpFailedStateView, sp_failed_state_view, GTK_TYPE_BIN)
+
+GtkWidget *
+sp_failed_state_view_new (void)
+{
+  return g_object_new (SP_TYPE_FAILED_STATE_VIEW, NULL);
+}
+
+static void
+sp_failed_state_view_class_init (SpFailedStateViewClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  gtk_widget_class_set_template_from_resource (widget_class,
+                                               "/org/gnome/sysprof/ui/sp-failed-state-view.ui");
+}
+
+static void
+sp_failed_state_view_init (SpFailedStateView *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
diff --git a/lib/sp-failed-state-view.h b/lib/sp-failed-state-view.h
new file mode 100644
index 0000000..af4605b
--- /dev/null
+++ b/lib/sp-failed-state-view.h
@@ -0,0 +1,43 @@
+/* sp-failed-state-view.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_FAILED_STATE_VIEW_H
+#define SP_FAILED_STATE_VIEW_H
+
+#include <gtk/gtk.h>
+
+#include "sp-profiler.h"
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_FAILED_STATE_VIEW (sp_failed_state_view_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (SpFailedStateView, sp_failed_state_view, SP, FAILED_STATE_VIEW, GtkBin)
+
+struct _SpFailedStateViewClass
+{
+  GtkBinClass parent;
+};
+
+GtkWidget *sp_failed_state_view_new          (void);
+void       sp_failed_state_view_set_profiler (SpFailedStateView *self,
+                                              SpProfiler        *profiler);
+
+G_END_DECLS
+
+#endif /* SP_FAILED_STATE_VIEW_H */
diff --git a/lib/sp-gjs-source.c b/lib/sp-gjs-source.c
new file mode 100644
index 0000000..ac163ec
--- /dev/null
+++ b/lib/sp-gjs-source.c
@@ -0,0 +1,245 @@
+/* sp-gjs-source.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#include <signal.h>
+#include <string.h>
+
+#include "sp-capture-reader.h"
+#include "sp-gjs-source.h"
+
+struct _SpGjsSource
+{
+  GObject          parent_instance;
+
+  SpCaptureWriter *writer;
+  GArray          *pids;
+  GArray          *enabled;
+};
+
+#define ENABLE_PROFILER  0x1
+#define DISABLE_PROFILER 0x0
+
+static void source_iface_init (SpSourceInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (SpGjsSource, sp_gjs_source, G_TYPE_OBJECT, 0,
+                        G_IMPLEMENT_INTERFACE (SP_TYPE_SOURCE, source_iface_init))
+
+static void
+sp_gjs_source_finalize (GObject *object)
+{
+  SpGjsSource *self = (SpGjsSource *)object;
+
+  g_clear_pointer (&self->pids, g_array_unref);
+  g_clear_pointer (&self->enabled, g_array_unref);
+  g_clear_pointer (&self->writer, sp_capture_writer_unref);
+
+  G_OBJECT_CLASS (sp_gjs_source_parent_class)->finalize (object);
+}
+
+static void
+sp_gjs_source_class_init (SpGjsSourceClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = sp_gjs_source_finalize;
+}
+
+static void
+sp_gjs_source_init (SpGjsSource *self)
+{
+  self->pids = g_array_new (FALSE, FALSE, sizeof (GPid));
+  self->enabled = g_array_new (FALSE, FALSE, sizeof (GPid));
+}
+
+static void
+sp_gjs_source_process_capture (SpGjsSource *self,
+                               GPid         pid,
+                               const gchar *path)
+{
+  g_autoptr(GError) error = NULL;
+  g_autoptr(SpCaptureReader) reader = NULL;
+
+  g_assert (SP_IS_GJS_SOURCE (self));
+  g_assert (self->writer != NULL);
+  g_assert (path != NULL);
+
+  if (!(reader = sp_capture_reader_new (path, &error)))
+    {
+      g_warning ("Failed to load capture: %s", error->message);
+      return;
+    }
+
+  if (!sp_capture_reader_splice (reader, self->writer, &error))
+    {
+      g_warning ("Failed to load capture: %s", error->message);
+      return;
+    }
+}
+
+static void
+sp_gjs_source_process_captures (SpGjsSource *self)
+{
+  guint i;
+
+  g_assert (SP_IS_GJS_SOURCE (self));
+  g_assert (self->writer != NULL);
+
+  for (i = 0; i < self->enabled->len; i++)
+    {
+      g_autofree gchar *filename = NULL;
+      g_autofree gchar *path = NULL;
+      GPid pid = g_array_index (self->enabled, GPid, i);
+
+      filename = g_strdup_printf ("gjs-profile-%u", (guint)pid);
+      path = g_build_filename (g_get_tmp_dir (), filename, NULL);
+
+      sp_gjs_source_process_capture (self, pid, path);
+    }
+}
+
+static void
+sp_gjs_source_set_writer (SpSource        *source,
+                          SpCaptureWriter *writer)
+{
+  SpGjsSource *self = (SpGjsSource *)source;
+
+  g_assert (SP_IS_GJS_SOURCE (self));
+  g_assert (writer != NULL);
+
+  self->writer = sp_capture_writer_ref (writer);
+}
+
+static gboolean
+pid_is_profileable (GPid pid)
+{
+  g_autofree gchar *path = NULL;
+  g_autofree gchar *contents = NULL;
+  const gchar *libgjs;
+  gsize len = 0;
+
+  g_assert (pid != -1);
+
+  /*
+   * Make sure this process has linked in libgjs. No sense in sending it a
+   * signal unless we know it can handle it.
+   */
+
+  path = g_strdup_printf ("/proc/%d/maps", pid);
+  if (!g_file_get_contents (path, &contents, &len, NULL))
+    return FALSE;
+
+  if (NULL == (libgjs = strstr (contents, "libgjs."G_MODULE_SUFFIX)))
+    return FALSE;
+
+  return TRUE;
+}
+
+static void
+sp_gjs_source_enable_pid (SpGjsSource *self,
+                          GPid         pid)
+{
+  union sigval si;
+
+  g_assert (SP_IS_GJS_SOURCE (self));
+  g_assert (pid != -1);
+
+  si.sival_int = ENABLE_PROFILER;
+
+  if (0 != sigqueue (pid, SIGUSR2, si))
+    g_warning ("Failed to queue SIGUSR2 to pid %u", (guint)pid);
+  else
+    g_array_append_val (self->enabled, pid);
+}
+
+static void
+sp_gjs_source_disable_pid (SpGjsSource *self,
+                           GPid         pid)
+{
+  union sigval si;
+
+  g_assert (SP_IS_GJS_SOURCE (self));
+  g_assert (pid != -1);
+
+  si.sival_int = DISABLE_PROFILER;
+
+  if (0 != sigqueue (pid, SIGUSR2, si))
+    g_warning ("Failed to queue SIGUSR2 to pid %u", (guint)pid);
+}
+
+static void
+sp_gjs_source_start (SpSource *source)
+{
+  SpGjsSource *self = (SpGjsSource *)source;
+  guint i;
+
+  g_assert (SP_IS_GJS_SOURCE (self));
+
+  for (i = 0; i < self->pids->len; i++)
+    {
+      GPid pid = g_array_index (self->pids, GPid, i);
+
+      if (pid_is_profileable (pid))
+        sp_gjs_source_enable_pid (self, pid);
+    }
+}
+
+static void
+sp_gjs_source_stop (SpSource *source)
+{
+  SpGjsSource *self = (SpGjsSource *)source;
+  guint i;
+
+  g_assert (SP_IS_GJS_SOURCE (self));
+
+  for (i = 0; i < self->pids->len; i++)
+    {
+      GPid pid = g_array_index (self->pids, GPid, i);
+
+      if (pid_is_profileable (pid))
+        sp_gjs_source_disable_pid (self, pid);
+    }
+
+  sp_gjs_source_process_captures (self);
+}
+
+static void
+sp_gjs_source_add_pid (SpSource *source,
+                       GPid      pid)
+{
+  SpGjsSource *self = (SpGjsSource *)source;
+
+  g_assert (SP_IS_GJS_SOURCE (self));
+  g_assert (pid > -1);
+
+  g_array_append_val (self->pids, pid);
+}
+
+static void
+source_iface_init (SpSourceInterface *iface)
+{
+  iface->set_writer = sp_gjs_source_set_writer;
+  iface->start = sp_gjs_source_start;
+  iface->stop = sp_gjs_source_stop;
+  iface->add_pid = sp_gjs_source_add_pid;
+}
+
+SpSource *
+sp_gjs_source_new (void)
+{
+  return g_object_new (SP_TYPE_GJS_SOURCE, NULL);
+}
diff --git a/lib/sp-gjs-source.h b/lib/sp-gjs-source.h
new file mode 100644
index 0000000..b0d106d
--- /dev/null
+++ b/lib/sp-gjs-source.h
@@ -0,0 +1,34 @@
+/* sp-gjs-source.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_GJS_SOURCE_H
+#define SP_GJS_SOURCE_H
+
+#include "sp-source.h"
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_GJS_SOURCE (sp_gjs_source_get_type())
+
+G_DECLARE_FINAL_TYPE (SpGjsSource, sp_gjs_source, SP, GJS_SOURCE, GObject)
+
+SpSource *sp_gjs_source_new (void);
+
+G_END_DECLS
+
+#endif /* SP_GJS_SOURCE_H */
diff --git a/lib/sp-jitmap-symbol-resolver.c b/lib/sp-jitmap-symbol-resolver.c
new file mode 100644
index 0000000..f2b80a7
--- /dev/null
+++ b/lib/sp-jitmap-symbol-resolver.c
@@ -0,0 +1,121 @@
+/* sp-jitmap-symbol-resolver.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#include "sp-kernel-symbol.h"
+#include "sp-jitmap-symbol-resolver.h"
+
+struct _SpJitmapSymbolResolver
+{
+  GObject     parent_instance;
+  GHashTable *jitmap;
+};
+
+static void symbol_resolver_iface_init (SpSymbolResolverInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (SpJitmapSymbolResolver,
+                        sp_jitmap_symbol_resolver,
+                        G_TYPE_OBJECT,
+                        0,
+                        G_IMPLEMENT_INTERFACE (SP_TYPE_SYMBOL_RESOLVER,
+                                               symbol_resolver_iface_init))
+
+static void
+sp_jitmap_symbol_resolver_finalize (GObject *object)
+{
+  SpJitmapSymbolResolver *self = (SpJitmapSymbolResolver *)object;
+
+  g_clear_pointer (&self->jitmap, g_hash_table_unref);
+
+  G_OBJECT_CLASS (sp_jitmap_symbol_resolver_parent_class)->finalize (object);
+}
+
+static void
+sp_jitmap_symbol_resolver_class_init (SpJitmapSymbolResolverClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = sp_jitmap_symbol_resolver_finalize;
+}
+
+static void
+sp_jitmap_symbol_resolver_init (SpJitmapSymbolResolver *self)
+{
+  self->jitmap = g_hash_table_new_full (NULL, NULL, NULL, g_free);
+}
+
+static void
+sp_jitmap_symbol_resolver_load (SpSymbolResolver *resolver,
+                                SpCaptureReader  *reader)
+{
+  SpJitmapSymbolResolver *self = (SpJitmapSymbolResolver *)resolver;
+  SpCaptureFrameType type;
+
+  g_assert (SP_IS_JITMAP_SYMBOL_RESOLVER (self));
+  g_assert (reader != NULL);
+
+  while (sp_capture_reader_peek_type (reader, &type))
+    {
+      g_autoptr(GHashTable) jitmap = NULL;
+      GHashTableIter iter;
+      SpCaptureAddress addr;
+      const gchar *str;
+
+      if (type != SP_CAPTURE_FRAME_JITMAP)
+        {
+          if (!sp_capture_reader_skip (reader))
+            return;
+          continue;
+        }
+
+      if (!(jitmap = sp_capture_reader_read_jitmap (reader)))
+        return;
+
+      g_hash_table_iter_init (&iter, jitmap);
+      while (g_hash_table_iter_next (&iter, (gpointer *)&addr, (gpointer *)&str))
+        g_hash_table_insert (self->jitmap, GSIZE_TO_POINTER (addr), g_strdup (str));
+    }
+}
+
+static gchar *
+sp_jitmap_symbol_resolver_resolve (SpSymbolResolver *resolver,
+                                   guint64           time,
+                                   GPid              pid,
+                                   SpCaptureAddress  address,
+                                   GQuark           *tag)
+{
+  SpJitmapSymbolResolver *self = (SpJitmapSymbolResolver *)resolver;
+
+  g_assert (SP_IS_JITMAP_SYMBOL_RESOLVER (self));
+
+  *tag = 0;
+
+  return g_strdup (g_hash_table_lookup (self->jitmap, GSIZE_TO_POINTER (address)));
+}
+
+static void
+symbol_resolver_iface_init (SpSymbolResolverInterface *iface)
+{
+  iface->load = sp_jitmap_symbol_resolver_load;
+  iface->resolve = sp_jitmap_symbol_resolver_resolve;
+}
+
+SpSymbolResolver *
+sp_jitmap_symbol_resolver_new (void)
+{
+  return g_object_new (SP_TYPE_JITMAP_SYMBOL_RESOLVER, NULL);
+}
diff --git a/lib/sp-jitmap-symbol-resolver.h b/lib/sp-jitmap-symbol-resolver.h
new file mode 100644
index 0000000..1d07fc7
--- /dev/null
+++ b/lib/sp-jitmap-symbol-resolver.h
@@ -0,0 +1,34 @@
+/* sp-jitmap-symbol-resolver.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_JITMAP_SYMBOL_RESOLVER_H
+#define SP_JITMAP_SYMBOL_RESOLVER_H
+
+#include "sp-symbol-resolver.h"
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_JITMAP_SYMBOL_RESOLVER (sp_jitmap_symbol_resolver_get_type())
+
+G_DECLARE_FINAL_TYPE (SpJitmapSymbolResolver, sp_jitmap_symbol_resolver, SP, JITMAP_SYMBOL_RESOLVER, GObject)
+
+SpSymbolResolver *sp_jitmap_symbol_resolver_new (void);
+
+G_END_DECLS
+
+#endif /* SP_JITMAP_SYMBOL_RESOLVER_H */
diff --git a/lib/sp-kernel-symbol-resolver.c b/lib/sp-kernel-symbol-resolver.c
new file mode 100644
index 0000000..ed7cc9f
--- /dev/null
+++ b/lib/sp-kernel-symbol-resolver.c
@@ -0,0 +1,79 @@
+/* sp-kernel-symbol-resolver.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#include "sp-kernel-symbol.h"
+#include "sp-kernel-symbol-resolver.h"
+
+struct _SpKernelSymbolResolver
+{
+  GObject parent_instance;
+};
+
+static void symbol_resolver_iface_init (SpSymbolResolverInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (SpKernelSymbolResolver,
+                        sp_kernel_symbol_resolver,
+                        G_TYPE_OBJECT,
+                        0,
+                        G_IMPLEMENT_INTERFACE (SP_TYPE_SYMBOL_RESOLVER,
+                                               symbol_resolver_iface_init))
+
+static GQuark linux_quark;
+
+static void
+sp_kernel_symbol_resolver_class_init (SpKernelSymbolResolverClass *klass)
+{
+  linux_quark = g_quark_from_static_string ("Linux");
+}
+
+static void
+sp_kernel_symbol_resolver_init (SpKernelSymbolResolver *skernel)
+{
+}
+
+static gchar *
+sp_kernel_symbol_resolver_resolve (SpSymbolResolver *resolver,
+                                   guint64           time,
+                                   GPid              pid,
+                                   SpCaptureAddress  address,
+                                   GQuark           *tag)
+{
+  const SpKernelSymbol *sym;
+
+  g_assert (SP_IS_SYMBOL_RESOLVER (resolver));
+
+  if (NULL != (sym = sp_kernel_symbol_from_address (address)))
+    {
+      *tag = linux_quark;
+      return g_strdup (sym->name);
+    }
+
+  return NULL;
+}
+
+static void
+symbol_resolver_iface_init (SpSymbolResolverInterface *iface)
+{
+  iface->resolve = sp_kernel_symbol_resolver_resolve;
+}
+
+SpSymbolResolver *
+sp_kernel_symbol_resolver_new (void)
+{
+  return g_object_new (SP_TYPE_KERNEL_SYMBOL_RESOLVER, NULL);
+}
diff --git a/lib/sp-kernel-symbol-resolver.h b/lib/sp-kernel-symbol-resolver.h
new file mode 100644
index 0000000..d2bf3b7
--- /dev/null
+++ b/lib/sp-kernel-symbol-resolver.h
@@ -0,0 +1,34 @@
+/* sp-kernel-symbol-resolver.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_KERNEL_SYMBOL_RESOLVER_H
+#define SP_KERNEL_SYMBOL_RESOLVER_H
+
+#include "sp-symbol-resolver.h"
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_KERNEL_SYMBOL_RESOLVER (sp_kernel_symbol_resolver_get_type())
+
+G_DECLARE_FINAL_TYPE (SpKernelSymbolResolver, sp_kernel_symbol_resolver, SP, KERNEL_SYMBOL_RESOLVER, GObject)
+
+SpSymbolResolver *sp_kernel_symbol_resolver_new (void);
+
+G_END_DECLS
+
+#endif /* SP_KERNEL_SYMBOL_RESOLVER_H */
diff --git a/lib/sp-kernel-symbol.c b/lib/sp-kernel-symbol.c
new file mode 100644
index 0000000..2855b29
--- /dev/null
+++ b/lib/sp-kernel-symbol.c
@@ -0,0 +1,205 @@
+/* sp-kernel-symbol.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#include "sp-line-reader.h"
+#include "sp-kernel-symbol.h"
+
+static GArray *kernel_symbols;
+static const gchar *kernel_symbols_skip[] = {
+  /* IRQ stack */
+  "common_interrupt",
+  "apic_timer_interrupt",
+  "smp_apic_timer_interrupt",
+  "hrtimer_interrupt",
+  "__run_hrtimer",
+  "perf_swevent_hrtimer",
+  "perf_event_overflow",
+  "__perf_event_overflow",
+  "perf_prepare_sample",
+  "perf_callchain",
+  "perf_swcounter_hrtimer",
+  "perf_counter_overflow",
+  "__perf_counter_overflow",
+  "perf_counter_output",
+
+  /* NMI stack */
+  "nmi_stack_correct",
+  "do_nmi",
+  "notify_die",
+  "atomic_notifier_call_chain",
+  "notifier_call_chain",
+  "perf_event_nmi_handler",
+  "perf_counter_nmi_handler",
+  "intel_pmu_handle_irq",
+  "perf_event_overflow",
+  "perf_counter_overflow",
+  "__perf_event_overflow",
+  "perf_prepare_sample",
+  "perf_callchain",
+
+  NULL
+};
+
+static gint
+sp_kernel_symbol_compare (gconstpointer a,
+                          gconstpointer b)
+{
+  const SpKernelSymbol *syma = a;
+  const SpKernelSymbol *symb = b;
+
+  if (syma->address > symb->address)
+    return 1;
+  else if (syma->address == symb->address)
+    return 0;
+  else
+    return -1;
+}
+
+static gboolean
+sp_kernel_symbol_load (void)
+{
+  g_autofree gchar *contents = NULL;
+  g_autoptr(GArray) ar = NULL;
+  g_autoptr(GHashTable) skip = NULL;
+  g_autoptr(SpLineReader) reader = NULL;
+  const gchar *line;
+  gsize len;
+  guint i;
+
+  skip = g_hash_table_new (g_str_hash, g_str_equal);
+  for (i = 0; kernel_symbols_skip [i]; i++)
+    g_hash_table_insert (skip, (gchar *)kernel_symbols_skip [i], NULL);
+
+  ar = g_array_new (FALSE, TRUE, sizeof (SpKernelSymbol));
+
+  if (!g_file_get_contents ("/proc/kallsyms", &contents, &len, NULL))
+    {
+      g_warning ("/proc/kallsyms is missing, kernel symbols will not be available");
+      return FALSE;
+    }
+
+  reader = sp_line_reader_new (contents, len);
+
+  while (NULL != (line = sp_line_reader_next (reader, &len)))
+    {
+      gchar **tokens;
+
+      ((gchar *)line) [len] = '\0';
+
+      tokens = g_strsplit_set (line, " \t", -1);
+
+      if (tokens [0] && tokens [1] && tokens [2])
+        {
+          SpCaptureAddress address;
+          gchar *endptr;
+
+          if (g_hash_table_contains (skip, tokens [2]))
+            continue;
+
+          address = g_ascii_strtoull (tokens [0], &endptr, 16);
+
+          if (*endptr == '\0' &&
+              (g_str_equal (tokens [1], "T") || g_str_equal (tokens [1], "t")))
+            {
+              SpKernelSymbol sym;
+
+              sym.address = address;
+              sym.name = g_steal_pointer (&tokens [2]);
+
+              g_array_append_val (ar, sym);
+            }
+        }
+
+      g_strfreev (tokens);
+    }
+
+  if (ar->len == 0)
+    return FALSE;
+
+  g_array_sort (ar, sp_kernel_symbol_compare);
+
+  kernel_symbols = g_steal_pointer (&ar);
+
+  return TRUE;
+}
+
+static const SpKernelSymbol *
+sp_kernel_symbol_lookup (SpKernelSymbol   *symbols,
+                         SpCaptureAddress  address,
+                         guint             first,
+                         guint             last)
+{
+  if (address >= symbols [last].address)
+    {
+      return &symbols [last];
+    }
+  else if (last - first < 3)
+    {
+      while (last >= first)
+        {
+          if (address >= symbols[last].address)
+            return &symbols [last];
+
+          last--;
+        }
+
+      return NULL;
+    }
+  else
+    {
+      int mid = (first + last) / 2;
+
+      if (symbols [mid].address > address)
+        return sp_kernel_symbol_lookup (symbols, address, first, mid);
+      else
+        return sp_kernel_symbol_lookup (symbols, address, mid, last);
+    }
+}
+
+/**
+ * sp_kernel_symbol_from_address:
+ * @address: the address of the instruction pointer
+ *
+ * Locates the kernel symbol that contains @address.
+ *
+ * Returns: (transfer none): An #SpKernelSymbol or %NULL.
+ */
+const SpKernelSymbol *
+sp_kernel_symbol_from_address (SpCaptureAddress address)
+{
+  const SpKernelSymbol *first;
+
+  if (G_UNLIKELY (kernel_symbols == NULL))
+    {
+      if (!sp_kernel_symbol_load ())
+        return NULL;
+    }
+
+  g_assert (kernel_symbols != NULL);
+  g_assert (kernel_symbols->len > 0);
+
+  /* Short circuit if this is out of range */
+  first = &g_array_index (kernel_symbols, SpKernelSymbol, 0);
+  if (address < first->address)
+    return NULL;
+
+  return sp_kernel_symbol_lookup ((SpKernelSymbol *)kernel_symbols->data,
+                                  address,
+                                  0,
+                                  kernel_symbols->len - 1);
+}
diff --git a/lib/sp-kernel-symbol.h b/lib/sp-kernel-symbol.h
new file mode 100644
index 0000000..e5e4216
--- /dev/null
+++ b/lib/sp-kernel-symbol.h
@@ -0,0 +1,36 @@
+/* sp-kernel-symbol.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_KERNEL_SYMBOL_H
+#define SP_KERNEL_SYMBOL_H
+
+#include "sp-capture-types.h"
+
+G_BEGIN_DECLS
+
+typedef struct
+{
+  SpCaptureAddress  address;
+  const gchar      *name;
+} SpKernelSymbol;
+
+const SpKernelSymbol *sp_kernel_symbol_from_address (SpCaptureAddress address);
+
+G_END_DECLS
+
+#endif /* SP_KERNEL_SYMBOL_H */
diff --git a/lib/sp-line-reader.c b/lib/sp-line-reader.c
new file mode 100644
index 0000000..174ed98
--- /dev/null
+++ b/lib/sp-line-reader.c
@@ -0,0 +1,124 @@
+/* sp-line-reader.c
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#include <string.h>
+
+#include "sp-line-reader.h"
+
+struct _SpLineReader
+{
+  const gchar *contents;
+  gsize        length;
+  gsize        pos;
+};
+
+void
+sp_line_reader_free (SpLineReader *self)
+{
+  g_slice_free (SpLineReader, self);
+}
+
+/**
+ * sp_line_reader_new:
+ * @contents: The buffer to read lines from
+ * @length: the length of @buffer in bytes
+ *
+ * Creates a new #SpLineReader for the contents provided. @contents are not
+ * copied and therefore it is a programming error to free contents before
+ * freeing the #SpLineReader structure.
+ *
+ * Use sp_line_reader_next() to read through the lines of the buffer.
+ *
+ * Returns: (transfer full): A new #SpLineReader that should be freed with
+ *   sp_line_reader_free() when no longer in use.
+ */
+SpLineReader *
+sp_line_reader_new (const gchar *contents,
+                    gssize       length)
+{
+  SpLineReader *self;
+
+  g_return_val_if_fail (contents != NULL, NULL);
+
+  self = g_slice_new (SpLineReader);
+
+  if (length < 0)
+    length = strlen (contents);
+
+  if (contents != NULL)
+    {
+      self->contents = contents;
+      self->length = length;
+      self->pos = 0;
+    }
+  else
+    {
+      self->contents = NULL;
+      self->length = 0;
+      self->pos = 0;
+    }
+
+  return self;
+}
+
+/**
+ * sp_line_reader_next:
+ * @self: the #SpLineReader
+ * @length: a location for the length of the line in bytes
+ *
+ * Moves forward to the beginning of the next line in the buffer. No changes to
+ * the buffer are made, and the result is a pointer within the string passed as
+ * @contents in sp_line_reader_init(). Since the line most likely will not be
+ * terminated with a NULL byte, you must provide @length to determine the
+ * length of the line.
+ *
+ * Using "line[length]" will place you on the \n that was found for the line.
+ * However, to perform this safely, you need to know that your string was
+ * either \0 terminated to begin with, or that your buffer provides enough space
+ * to guarantee you can dereference past the last "textual content" of the
+ * buffer.
+ *
+ * Returns: (nullable) (transfer none): The beginning of the line within the buffer
+ */
+const gchar *
+sp_line_reader_next (SpLineReader *self,
+                     gsize        *length)
+{
+  const gchar *ret;
+  const gchar *endptr;
+
+  g_return_val_if_fail (self != NULL, NULL);
+  g_return_val_if_fail (length != NULL, NULL);
+
+  if ((self->contents == NULL) || (self->pos >= self->length))
+    {
+      *length = 0;
+      return NULL;
+    }
+
+  ret = &self->contents [self->pos];
+
+  endptr = memchr (ret, '\n', self->length - self->pos);
+  if (G_UNLIKELY (endptr == NULL))
+    endptr = &self->contents [self->length];
+
+  *length = (endptr - ret);
+  self->pos += *length + 1;
+
+  return ret;
+}
diff --git a/lib/sp-line-reader.h b/lib/sp-line-reader.h
new file mode 100644
index 0000000..c95f54a
--- /dev/null
+++ b/lib/sp-line-reader.h
@@ -0,0 +1,38 @@
+/* sp-line-reader.h
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_LINE_READER_H
+#define SP_LINE_READER_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SpLineReader SpLineReader;
+
+SpLineReader *sp_line_reader_new  (const gchar   *contents,
+                                   gssize         length);
+void          sp_line_reader_free (SpLineReader  *self);
+const gchar  *sp_line_reader_next (SpLineReader  *self,
+                                   gsize         *length);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (SpLineReader, sp_line_reader_free)
+
+G_END_DECLS
+
+#endif /* SP_LINE_READER_H */
diff --git a/lib/sp-map-lookaside.c b/lib/sp-map-lookaside.c
new file mode 100644
index 0000000..ba590f4
--- /dev/null
+++ b/lib/sp-map-lookaside.c
@@ -0,0 +1,119 @@
+/* sp-map-lookaside.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#include "sp-map-lookaside.h"
+
+struct _SpMapLookaside
+{
+  GSequence    *seq;
+  GStringChunk *chunk;
+};
+
+static gint
+sp_map_compare (gconstpointer a,
+                gconstpointer b,
+                gpointer      user_data)
+{
+  const SpMap *map_a = a;
+  const SpMap *map_b = b;
+
+  return sp_capture_address_compare (map_a->start, map_b->start);
+}
+
+static gint
+sp_map_compare_in_range (gconstpointer a,
+                         gconstpointer b,
+                         gpointer      user_data)
+{
+  const SpMap *map_a = a;
+  const SpMap *map_b = b;
+
+  /*
+   * map_b is the needle for the search.
+   * Only map_b->start is set.
+   */
+
+  if ((map_b->start >= map_a->start) && (map_b->start < map_a->end))
+    return 0;
+
+  return sp_capture_address_compare (map_a->start, map_b->start);
+}
+
+static void
+sp_map_free (gpointer data)
+{
+  SpMap *map = data;
+
+  g_slice_free (SpMap, map);
+}
+
+SpMapLookaside *
+sp_map_lookaside_new (void)
+{
+  SpMapLookaside *ret;
+
+  ret = g_slice_new (SpMapLookaside);
+  ret->seq = g_sequence_new (sp_map_free);
+  ret->chunk = g_string_chunk_new (4096);
+
+  return ret;
+}
+
+void
+sp_map_lookaside_free (SpMapLookaside *self)
+{
+  g_sequence_free (self->seq);
+  g_string_chunk_free (self->chunk);
+  g_slice_free (SpMapLookaside, self);
+}
+
+void
+sp_map_lookaside_insert (SpMapLookaside *self,
+                         const SpMap    *map)
+{
+  SpMap *copy;
+
+  g_assert (self != NULL);
+  g_assert (map != NULL);
+
+  copy = g_slice_new (SpMap);
+  copy->start = map->start;
+  copy->end = map->end;
+  copy->offset = map->offset;
+  copy->inode = map->inode;
+  copy->filename = g_string_chunk_insert_const (self->chunk, map->filename);
+
+  g_sequence_insert_sorted (self->seq, copy, sp_map_compare, NULL);
+}
+
+const SpMap *
+sp_map_lookaside_lookup (SpMapLookaside   *self,
+                         SpCaptureAddress  address)
+{
+  SpMap map = { address };
+  GSequenceIter *iter;
+
+  g_assert (self != NULL);
+
+  iter = g_sequence_lookup (self->seq, &map, sp_map_compare_in_range, NULL);
+
+  if (iter != NULL)
+    return g_sequence_get (iter);
+
+  return NULL;
+}
diff --git a/lib/sp-map-lookaside.h b/lib/sp-map-lookaside.h
new file mode 100644
index 0000000..c106158
--- /dev/null
+++ b/lib/sp-map-lookaside.h
@@ -0,0 +1,50 @@
+/* sp-map-lookaside.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_MAP_LOOKASIDE_H
+#define SP_MAP_LOOKASIDE_H
+
+#include <glib.h>
+
+#include "sp-capture-types.h"
+
+G_BEGIN_DECLS
+
+typedef struct _SpMapLookaside SpMapLookaside;
+
+typedef struct
+{
+  SpCaptureAddress  start;
+  SpCaptureAddress  end;
+  off_t             offset;
+  ino_t             inode;
+  const gchar      *filename;
+} SpMap;
+
+SpMapLookaside *sp_map_lookaside_new    (void);
+void            sp_map_lookaside_insert (SpMapLookaside   *self,
+                                         const SpMap      *map);
+const SpMap    *sp_map_lookaside_lookup (SpMapLookaside   *self,
+                                         SpCaptureAddress  address);
+void            sp_map_lookaside_free   (SpMapLookaside *self);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (SpMapLookaside, sp_map_lookaside_free)
+
+G_END_DECLS
+
+#endif /* SP_MAP_LOOKASIDE_H */
diff --git a/lib/sp-model-filter.c b/lib/sp-model-filter.c
new file mode 100644
index 0000000..9b83c15
--- /dev/null
+++ b/lib/sp-model-filter.c
@@ -0,0 +1,472 @@
+/* sp-model-filter.c
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#include "sp-model-filter.h"
+
+/*
+ * This is a simple model filter for GListModel.
+ *
+ * Let me start by saying how it works, and then how I wish it worked.
+ *
+ * This uses 2 GSequence (Treaps) to track the filters. One matches the
+ * underlying listmodel. One matches the filtered set. We hold onto our
+ * own reference to the object in the child list model, and update things
+ * as necessary when ::items-changed is emitted.
+ *
+ * I'd rather see this solved in one of two ways.
+ *
+ * 1) Add filtering support to GListStore
+ *
+ * or
+ *
+ * 2) Create a multi-tree data-structure that contains two tree nodes
+ *    in each element. One tree contains all items, one tree contains
+ *    the visible items (a subset of the other tree). The nodes might
+ *    look something like:
+ *
+ *    Item {
+ *      TreeNode  all_tree;
+ *      TreeNode  visible_tree;
+ *      GObject  *item;
+ *    }
+ *
+ * But either way, this gets the job done for now. I'd venture a guess
+ * that in many cases (small lists), this is actually slower than just
+ * rechecking a simple GPtrArray, but let's see how it goes.
+ *
+ * -- Christian
+ */
+
+typedef struct
+{
+  GListModel        *child_model;
+
+  GSequence         *seq;
+  GSequence         *visible_seq;
+
+  SpModelFilterFunc  filter_func;
+  gpointer           filter_func_data;
+  GDestroyNotify     filter_func_data_destroy;
+
+  guint              needs_rebuild : 1;
+} SpModelFilterPrivate;
+
+typedef struct
+{
+  GSequenceIter *iter;
+  GObject       *object;
+} Element;
+
+static void list_model_iface_init (GListModelInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (SpModelFilter, sp_model_filter, G_TYPE_OBJECT, 0,
+                        G_ADD_PRIVATE (SpModelFilter)
+                        G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL,
+                                               list_model_iface_init))
+
+enum {
+  PROP_0,
+  PROP_CHILD_MODEL,
+  N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+element_free (gpointer data)
+{
+  Element *e = data;
+
+  g_clear_object (&e->object);
+  g_slice_free (Element, e);
+}
+
+static gboolean
+sp_model_filter_default_filter_func (GObject  *item,
+                                     gpointer  user_data)
+{
+  return TRUE;
+}
+
+static void
+sp_model_filter_child_model_items_changed (SpModelFilter *self,
+                                           guint          position,
+                                           guint          n_removed,
+                                           guint          n_added,
+                                           GListModel    *child_model)
+{
+  SpModelFilterPrivate *priv = sp_model_filter_get_instance_private (self);
+  GSequenceIter *insert_before = NULL;
+  GSequenceIter *insert_iter;
+  GSequenceIter *lower;
+  GSequenceIter *upper;
+  guint i;
+
+  g_assert (SP_IS_MODEL_FILTER (self));
+  g_assert (G_IS_LIST_MODEL (child_model));
+
+
+  for (i = 0; i < n_removed; i++)
+    {
+      GSequenceIter *iter;
+      Element *ele;
+
+      iter = g_sequence_get_iter_at_pos (priv->seq, position);
+      ele = g_sequence_get (iter);
+
+      if (ele->iter)
+        {
+          guint visible_position = g_sequence_iter_get_position (ele->iter);
+
+          insert_before = g_sequence_iter_next (ele->iter);
+          g_sequence_remove (ele->iter);
+          g_list_model_items_changed (G_LIST_MODEL (self), visible_position, 1, 0);
+        }
+
+      g_sequence_remove (iter);
+    }
+
+  insert_iter = g_sequence_get_iter_at_pos (priv->seq, position + 1);
+
+  if (insert_before != NULL)
+    goto add_items;
+
+#if GLIB_CHECK_VERSION(2, 48, 0)
+  if (g_sequence_is_empty (priv->visible_seq))
+#else
+  if (g_sequence_get_begin_iter (priv->visible_seq) == g_sequence_get_end_iter (priv->visible_seq))
+#endif
+    {
+      insert_before = g_sequence_get_end_iter (priv->visible_seq);
+      goto add_items;
+    }
+
+  lower = g_sequence_get_begin_iter (priv->visible_seq);
+  upper = g_sequence_get_end_iter (priv->visible_seq);
+
+  while (lower != upper)
+    {
+      GSequenceIter *mid;
+      GSequenceIter *iter;
+      guint mid_pos;
+
+      mid = g_sequence_range_get_midpoint (lower, upper);
+      iter = g_sequence_get (mid);
+      mid_pos = g_sequence_iter_get_position (iter);
+
+      if (mid_pos < position)
+        lower = g_sequence_iter_next (mid);
+      else if (mid_pos > position)
+        upper = g_sequence_iter_prev (mid);
+      else
+        upper = lower = mid;
+    }
+
+  if (upper == g_sequence_get_end_iter (priv->visible_seq))
+    insert_before = upper;
+  else
+    insert_before =
+      ((guint)g_sequence_iter_get_position (g_sequence_get (upper)) <= position)
+        ? upper : g_sequence_iter_next (upper);
+
+add_items:
+  for (i = 0; i < n_added; i++)
+    {
+      GSequenceIter *iter;
+      Element *ele;
+
+      ele = g_slice_new (Element);
+      ele->object = g_list_model_get_item (priv->child_model, position + i);
+      ele->iter = NULL;
+
+      iter = g_sequence_insert_before (insert_iter, ele);
+
+      if (priv->filter_func (ele->object, priv->filter_func_data))
+        {
+          ele->iter = g_sequence_insert_before (insert_before, iter);
+          g_list_model_items_changed (G_LIST_MODEL (self),
+                                      g_sequence_iter_get_position (ele->iter),
+                                      0, 1);
+        }
+    }
+}
+
+static void
+sp_model_filter_finalize (GObject *object)
+{
+  SpModelFilter *self = (SpModelFilter *)object;
+  SpModelFilterPrivate *priv = sp_model_filter_get_instance_private (self);
+
+  g_clear_pointer (&priv->seq, g_sequence_free);
+  g_clear_pointer (&priv->visible_seq, g_sequence_free);
+
+  if (priv->filter_func_data_destroy)
+    {
+      g_clear_pointer (&priv->filter_func_data, priv->filter_func_data_destroy);
+      priv->filter_func_data_destroy = NULL;
+    }
+
+  g_clear_object (&priv->child_model);
+
+  G_OBJECT_CLASS (sp_model_filter_parent_class)->finalize (object);
+}
+
+static void
+sp_model_filter_get_property (GObject    *object,
+                              guint       prop_id,
+                              GValue     *value,
+                              GParamSpec *pspec)
+{
+  SpModelFilter *self = SP_MODEL_FILTER (object);
+
+  switch (prop_id)
+    {
+    case PROP_CHILD_MODEL:
+      g_value_set_object (value, sp_model_filter_get_child_model (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+sp_model_filter_class_init (SpModelFilterClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = sp_model_filter_finalize;
+  object_class->get_property = sp_model_filter_get_property;
+
+  properties [PROP_CHILD_MODEL] =
+    g_param_spec_object ("child-model",
+                         "Child Model",
+                         "The child model being filtered.",
+                         G_TYPE_LIST_MODEL,
+                         (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+sp_model_filter_init (SpModelFilter *self)
+{
+  SpModelFilterPrivate *priv = sp_model_filter_get_instance_private (self);
+
+  priv->filter_func = sp_model_filter_default_filter_func;
+  priv->seq = g_sequence_new (element_free);
+  priv->visible_seq = g_sequence_new (NULL);
+
+  priv->needs_rebuild = TRUE;
+}
+
+static void
+sp_model_filter_rebuild (SpModelFilter *self,
+                         gboolean       no_emit)
+{
+  SpModelFilterPrivate *priv = sp_model_filter_get_instance_private (self);
+  guint new_n_items = 0;
+  guint old_n_items;
+  guint n_items;
+  guint i;
+
+  g_assert (SP_IS_MODEL_FILTER (self));
+  g_assert (priv->needs_rebuild);
+
+  old_n_items = g_sequence_get_length (priv->visible_seq);
+
+  g_clear_pointer (&priv->seq, g_sequence_free);
+  g_clear_pointer (&priv->visible_seq, g_sequence_free);
+
+  priv->seq = g_sequence_new (element_free);
+  priv->visible_seq = g_sequence_new (NULL);
+
+  n_items = g_list_model_get_n_items (priv->child_model);
+
+  for (i = 0; i < n_items; i++)
+    {
+      GSequenceIter *iter;
+      Element *ele;
+
+      ele = g_slice_new (Element);
+      ele->object = g_list_model_get_item (priv->child_model, i);
+      ele->iter = NULL;
+
+      iter = g_sequence_append (priv->seq, ele);
+
+      if (priv->filter_func (ele->object, priv->filter_func_data))
+        {
+          ele->iter = g_sequence_append (priv->visible_seq, iter);
+          new_n_items++;
+        }
+    }
+
+  if (!no_emit)
+    g_list_model_items_changed (G_LIST_MODEL (self), 0, old_n_items, new_n_items);
+
+  priv->needs_rebuild = FALSE;
+}
+
+static GType
+sp_model_filter_get_item_type (GListModel *model)
+{
+  SpModelFilter *self = (SpModelFilter *)model;
+  SpModelFilterPrivate *priv = sp_model_filter_get_instance_private (self);
+
+  g_assert (SP_IS_MODEL_FILTER (self));
+
+  return g_list_model_get_item_type (priv->child_model);
+}
+
+static guint
+sp_model_filter_get_n_items (GListModel *model)
+{
+  SpModelFilter *self = (SpModelFilter *)model;
+  SpModelFilterPrivate *priv = sp_model_filter_get_instance_private (self);
+
+  g_assert (SP_IS_MODEL_FILTER (self));
+
+  if (priv->needs_rebuild)
+    sp_model_filter_rebuild (self, TRUE);
+
+  return g_sequence_get_length (priv->visible_seq);
+}
+
+static gpointer
+sp_model_filter_get_item (GListModel *model,
+                          guint       position)
+{
+  SpModelFilter *self = (SpModelFilter *)model;
+  SpModelFilterPrivate *priv = sp_model_filter_get_instance_private (self);
+  GSequenceIter *iter;
+  Element *ele;
+
+  g_assert (SP_IS_MODEL_FILTER (self));
+
+  if (priv->needs_rebuild)
+    sp_model_filter_rebuild (self, TRUE);
+
+  iter = g_sequence_get_iter_at_pos (priv->visible_seq, position);
+
+  if (!iter || g_sequence_iter_is_end (iter))
+    {
+      g_warning ("invalid position for filter, filter is corrupt");
+      return NULL;
+    }
+
+  iter = g_sequence_get (iter);
+
+  if (!iter || g_sequence_iter_is_end (iter))
+    {
+      g_warning ("invalid position for filter, filter is corrupt");
+      return NULL;
+    }
+
+  ele = g_sequence_get (iter);
+
+  return g_object_ref (ele->object);
+}
+
+static void
+list_model_iface_init (GListModelInterface *iface)
+{
+  iface->get_item_type = sp_model_filter_get_item_type;
+  iface->get_n_items = sp_model_filter_get_n_items;
+  iface->get_item = sp_model_filter_get_item;
+}
+
+SpModelFilter *
+sp_model_filter_new (GListModel *child_model)
+{
+  SpModelFilter *ret;
+  SpModelFilterPrivate *priv;
+
+  g_return_val_if_fail (G_IS_LIST_MODEL (child_model), NULL);
+
+  ret = g_object_new (SP_TYPE_MODEL_FILTER, NULL);
+  priv = sp_model_filter_get_instance_private (ret);
+  priv->child_model = g_object_ref (child_model);
+
+  g_signal_connect_object (child_model,
+                           "items-changed",
+                           G_CALLBACK (sp_model_filter_child_model_items_changed),
+                           ret,
+                           G_CONNECT_SWAPPED);
+
+  return ret;
+}
+
+/**
+ * sp_model_filter_get_child_model:
+ * @self: A #SpModelFilter
+ *
+ * Gets the child model that is being filtered.
+ *
+ * Returns: (transfer none): A #GListModel.
+ */
+GListModel *
+sp_model_filter_get_child_model (SpModelFilter *self)
+{
+  SpModelFilterPrivate *priv = sp_model_filter_get_instance_private (self);
+
+  g_return_val_if_fail (SP_IS_MODEL_FILTER (self), NULL);
+
+  return priv->child_model;
+}
+
+void
+sp_model_filter_invalidate (SpModelFilter *self)
+{
+  SpModelFilterPrivate *priv = sp_model_filter_get_instance_private (self);
+
+  g_return_if_fail (SP_IS_MODEL_FILTER (self));
+
+  priv->needs_rebuild = TRUE;
+
+  sp_model_filter_rebuild (self, FALSE);
+}
+
+void
+sp_model_filter_set_filter_func (SpModelFilter     *self,
+                                 SpModelFilterFunc  filter_func,
+                                 gpointer           filter_func_data,
+                                 GDestroyNotify     filter_func_data_destroy)
+{
+  SpModelFilterPrivate *priv = sp_model_filter_get_instance_private (self);
+
+  g_return_if_fail (SP_IS_MODEL_FILTER (self));
+  g_return_if_fail (filter_func || (!filter_func_data && !filter_func_data_destroy));
+
+  if (priv->filter_func_data_destroy)
+    g_clear_pointer (&priv->filter_func_data, priv->filter_func_data_destroy);
+
+  if (filter_func != NULL)
+    {
+      priv->filter_func = filter_func;
+      priv->filter_func_data = filter_func_data;
+      priv->filter_func_data_destroy = filter_func_data_destroy;
+    }
+  else
+    {
+      priv->filter_func = sp_model_filter_default_filter_func;
+      priv->filter_func_data = NULL;
+      priv->filter_func_data_destroy = NULL;
+    }
+
+  sp_model_filter_invalidate (self);
+}
diff --git a/lib/sp-model-filter.h b/lib/sp-model-filter.h
new file mode 100644
index 0000000..1a6038b
--- /dev/null
+++ b/lib/sp-model-filter.h
@@ -0,0 +1,48 @@
+/* sp-model-filter.h
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_MODEL_FILTER_H
+#define SP_MODEL_FILTER_H
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_MODEL_FILTER (sp_model_filter_get_type())
+
+typedef gboolean (*SpModelFilterFunc) (GObject  *object,
+                                       gpointer  user_data);
+
+G_DECLARE_DERIVABLE_TYPE (SpModelFilter, sp_model_filter, SP, MODEL_FILTER, GObject)
+
+struct _SpModelFilterClass
+{
+  GObjectClass parent_class;
+};
+
+SpModelFilter *sp_model_filter_new             (GListModel        *child_model);
+GListModel    *sp_model_filter_get_child_model (SpModelFilter     *self);
+void           sp_model_filter_invalidate      (SpModelFilter     *self);
+void           sp_model_filter_set_filter_func (SpModelFilter     *self,
+                                                SpModelFilterFunc  filter_func,
+                                                gpointer           filter_func_data,
+                                                GDestroyNotify     filter_func_data_destroy);
+
+G_END_DECLS
+
+#endif /* SP_MODEL_FILTER_H */
diff --git a/lib/sp-perf-counter.c b/lib/sp-perf-counter.c
new file mode 100644
index 0000000..d400d5f
--- /dev/null
+++ b/lib/sp-perf-counter.c
@@ -0,0 +1,671 @@
+/* sp-perf-counter.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+/* Sysprof -- Sampling, systemwide CPU profiler
+ * Copyright 2004, Red Hat, Inc.
+ * Copyright 2004, 2005, Soeren Sandmann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <errno.h>
+#include <gio/gio.h>
+#include <gio/gunixfdlist.h>
+#include <polkit/polkit.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#include "sp-perf-counter.h"
+
+#include "util.h"
+
+/*
+ * Number of pages to map for the ring buffer.  We map one additional buffer
+ * at the beginning for header information to communicate with perf.
+ */
+#define N_PAGES 32
+
+/*
+ * This represents a stream coming to us from perf. All SpPerfCounterInfo
+ * share a single GSource used for watching incoming G_IO_IN requests.
+ * The map is the mmap() zone we are using as a ring buffer for communicating
+ * with perf. The rest is for managing the ring buffer.
+ */
+typedef struct
+{
+  gint                         fd;
+  gpointer                     fdtag;
+  struct perf_event_mmap_page *map;
+  guint8                      *data;
+  guint64                      tail;
+  gint                         cpu;
+  guint                        in_callback : 1;
+} SpPerfCounterInfo;
+
+struct _SpPerfCounter
+{
+  volatile gint ref_count;
+
+  /*
+   * If we are should currently be enabled. We allow calling
+   * multiple times and disabling when we reach zero.
+   */
+  guint enabled;
+
+  /*
+   * Our main context and source for delivering callbacks.
+   */
+  GMainContext *context;
+  GSource *source;
+
+  /*
+   * An array of SpPerfCounterInfo, indicating all of our open
+   * perf stream.s
+   */
+  GPtrArray *info;
+
+  /*
+   * The callback to execute for every discovered perf event.
+   */
+  SpPerfCounterCallback callback;
+  gpointer callback_data;
+  GDestroyNotify callback_data_destroy;
+
+  /*
+   * The number of samples we've recorded.
+   */
+  guint64 n_samples;
+};
+
+typedef struct
+{
+  GSource        source;
+  SpPerfCounter *counter;
+} PerfGSource;
+
+G_DEFINE_BOXED_TYPE (SpPerfCounter,
+                     sp_perf_counter,
+                     (GBoxedCopyFunc)sp_perf_counter_ref,
+                     (GBoxedFreeFunc)sp_perf_counter_unref)
+
+static gboolean
+perf_gsource_dispatch (GSource     *source,
+                       GSourceFunc  callback,
+                       gpointer     user_data)
+{
+  return callback ? callback (user_data) : G_SOURCE_CONTINUE;
+}
+
+static GSourceFuncs source_funcs = {
+  NULL, NULL, perf_gsource_dispatch, NULL
+};
+
+static void
+sp_perf_counter_info_free (SpPerfCounterInfo *info)
+{
+  if (info->map)
+    {
+      gsize map_size;
+
+      map_size = N_PAGES * getpagesize () + getpagesize ();
+      munmap (info->map, map_size);
+
+      info->map = NULL;
+      info->data = NULL;
+    }
+
+  if (info->fd != -1)
+    {
+      close (info->fd);
+      info->fd = 0;
+    }
+
+  g_slice_free (SpPerfCounterInfo, info);
+}
+
+static void
+sp_perf_counter_finalize (SpPerfCounter *self)
+{
+  guint i;
+
+  g_assert (self != NULL);
+  g_assert (self->ref_count == 0);
+
+  for (i = 0; i < self->info->len; i++)
+    {
+      SpPerfCounterInfo *info = g_ptr_array_index (self->info, i);
+
+      if (info->fdtag)
+        g_source_remove_unix_fd (self->source, info->fdtag);
+
+      sp_perf_counter_info_free (info);
+    }
+
+  if (self->callback_data_destroy)
+    self->callback_data_destroy (self->callback_data);
+
+  g_clear_pointer (&self->source, g_source_destroy);
+  g_clear_pointer (&self->info, g_ptr_array_free);
+  g_clear_pointer (&self->context, g_main_context_unref);
+  g_slice_free (SpPerfCounter, self);
+}
+
+void
+sp_perf_counter_unref (SpPerfCounter *self)
+{
+  g_return_if_fail (self != NULL);
+  g_return_if_fail (self->ref_count > 0);
+
+  if (g_atomic_int_dec_and_test (&self->ref_count))
+    sp_perf_counter_finalize (self);
+}
+
+SpPerfCounter *
+sp_perf_counter_ref (SpPerfCounter *self)
+{
+  g_return_val_if_fail (self != NULL, NULL);
+  g_return_val_if_fail (self->ref_count > 0, NULL);
+
+  g_atomic_int_inc (&self->ref_count);
+
+  return self;
+}
+
+static void
+sp_perf_counter_flush (SpPerfCounter     *self,
+                       SpPerfCounterInfo *info)
+{
+  guint64 head;
+  guint64 tail;
+  guint64 n_bytes = N_PAGES * getpagesize ();
+  guint64 mask = n_bytes - 1;
+
+  g_assert (self != NULL);
+  g_assert (info != NULL);
+
+  tail = info->tail;
+  head = info->map->data_head;
+
+  read_barrier ();
+
+  if (head < tail)
+    tail = head;
+
+  while ((head - tail) >= sizeof (struct perf_event_header))
+    {
+      g_autofree guint8 *free_me = NULL;
+      struct perf_event_header *header;
+      guint8 buffer[4096];
+
+      /* Note that:
+       *
+       * - perf events are a multiple of 64 bits
+       * - the perf event header is 64 bits
+       * - the data area is a multiple of 64 bits
+       *
+       * which means there will always be space for one header, which means we
+       * can safely dereference the size field.
+       */
+      header = (struct perf_event_header *)(info->data + (tail & mask));
+
+      if (header->size > head - tail)
+        {
+          /* The kernel did not generate a complete event.
+           * I don't think that can happen, but we may as well
+           * be paranoid.
+           */
+          break;
+        }
+
+      if (info->data + (tail & mask) + header->size > info->data + n_bytes)
+        {
+          gint n_before;
+          gint n_after;
+          guint8 *b;
+
+          if (header->size > sizeof buffer)
+            free_me = b = g_malloc (header->size);
+          else
+            b = buffer;
+
+          n_after = (tail & mask) + header->size - n_bytes;
+          n_before = header->size - n_after;
+
+          memcpy (b, info->data + (tail & mask), n_before);
+          memcpy (b + n_before, info->data, n_after);
+
+          header = (struct perf_event_header *)b;
+        }
+
+      if (header->type == PERF_RECORD_SAMPLE)
+        self->n_samples++;
+
+      if (self->callback != NULL)
+        {
+          info->in_callback = TRUE;
+          self->callback ((SpPerfCounterEvent *)header, info->cpu, self->callback_data);
+          info->in_callback = FALSE;
+        }
+
+      tail += header->size;
+    }
+
+  info->tail = tail;
+  info->map->data_tail = tail;
+}
+
+static gboolean
+sp_perf_counter_dispatch (gpointer user_data)
+{
+  SpPerfCounter *self = user_data;
+  guint i;
+
+  g_assert (self != NULL);
+  g_assert (self->info != NULL);
+
+  for (i = 0; i < self->info->len; i++)
+    {
+      SpPerfCounterInfo *info = g_ptr_array_index (self->info, i);
+
+      sp_perf_counter_flush (self, info);
+    }
+
+  return G_SOURCE_CONTINUE;
+}
+
+static void
+sp_perf_counter_enable_info (SpPerfCounter     *self,
+                             SpPerfCounterInfo *info)
+{
+  g_assert (self != NULL);
+  g_assert (info != NULL);
+
+  if (0 != ioctl (info->fd, PERF_EVENT_IOC_ENABLE))
+    g_warning ("Failed to enable counters");
+
+  g_source_modify_unix_fd (self->source, info->fdtag, G_IO_IN);
+}
+
+SpPerfCounter *
+sp_perf_counter_new (GMainContext *context)
+{
+  SpPerfCounter *ret;
+
+  if (context == NULL)
+    context = g_main_context_default ();
+
+  ret = g_slice_new0 (SpPerfCounter);
+  ret->ref_count = 1;
+  ret->info = g_ptr_array_new ();
+  ret->context = g_main_context_ref (context);
+  ret->source = g_source_new (&source_funcs, sizeof (PerfGSource));
+
+  ((PerfGSource *)ret->source)->counter = ret;
+  g_source_set_callback (ret->source, sp_perf_counter_dispatch, ret, NULL);
+  g_source_set_name (ret->source, "[perf]");
+  g_source_attach (ret->source, context);
+
+  return ret;
+}
+
+void
+sp_perf_counter_close (SpPerfCounter *self,
+                       gint           fd)
+{
+  guint i;
+
+  g_return_if_fail (self != NULL);
+  g_return_if_fail (fd != -1);
+
+  for (i = 0; i < self->info->len; i++)
+    {
+      SpPerfCounterInfo *info = g_ptr_array_index (self->info, i);
+
+      if (info->fd == fd)
+        {
+          g_ptr_array_remove_index (self->info, i);
+          if (self->source)
+            g_source_remove_unix_fd (self->source, info->fdtag);
+          sp_perf_counter_info_free (info);
+          return;
+        }
+    }
+}
+
+static void
+sp_perf_counter_add_info (SpPerfCounter *self,
+                          int            fd,
+                          int            cpu)
+{
+  SpPerfCounterInfo *info;
+  guint8 *map;
+  gsize map_size;
+
+  g_assert (self != NULL);
+  g_assert (fd != -1);
+
+  map_size = N_PAGES * getpagesize () + getpagesize ();
+  map = mmap (NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+
+  if (map == MAP_FAILED)
+    {
+      close (fd);
+      return;
+    }
+
+  info = g_slice_new0 (SpPerfCounterInfo);
+  info->fd = fd;
+  info->map = (gpointer)map;
+  info->data = map + getpagesize ();
+  info->tail = 0;
+  info->cpu = cpu;
+
+  g_ptr_array_add (self->info, info);
+
+  info->fdtag = g_source_add_unix_fd (self->source, info->fd, G_IO_ERR);
+
+  if (self->enabled)
+    sp_perf_counter_enable_info (self, info);
+}
+
+void
+sp_perf_counter_take_fd (SpPerfCounter *self,
+                         int            fd)
+{
+  g_return_if_fail (self != NULL);
+  g_return_if_fail (fd > -1);
+
+  sp_perf_counter_add_info (self, fd, -1);
+}
+
+#ifdef ENABLE_SYSPROFD
+static GDBusProxy *
+get_proxy (void)
+{
+  static GDBusProxy *proxy;
+  GDBusConnection *bus = NULL;
+
+  if (proxy != NULL)
+    return g_object_ref (proxy);
+
+  bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
+  if (bus == NULL)
+    return NULL;
+
+  proxy = g_dbus_proxy_new_sync (bus,
+                                 (G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
+                                  G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS |
+                                  G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START_AT_CONSTRUCTION),
+                                 NULL,
+                                 "org.gnome.Sysprof2",
+                                 "/org/gnome/Sysprof2",
+                                 "org.gnome.Sysprof2",
+                                 NULL, NULL);
+
+  if (proxy != NULL)
+    {
+      g_object_add_weak_pointer (G_OBJECT (proxy), (gpointer *)&proxy);
+      return g_object_ref (proxy);
+    }
+
+  return NULL;
+}
+
+static gboolean
+authorize_proxy (GDBusProxy *proxy)
+{
+  PolkitSubject *subject = NULL;
+  GPermission *permission = NULL;
+  GDBusConnection *conn;
+  const gchar *name;
+
+  g_assert (G_IS_DBUS_PROXY (proxy));
+
+  conn = g_dbus_proxy_get_connection (proxy);
+  if (conn == NULL)
+    goto failure;
+
+  name = g_dbus_connection_get_unique_name (conn);
+  if (name == NULL)
+    goto failure;
+
+  subject = polkit_system_bus_name_new (name);
+  if (subject == NULL)
+    goto failure;
+
+  permission = polkit_permission_new_sync ("org.gnome.sysprof2.perf-event-open", subject, NULL, NULL);
+  if (permission == NULL)
+    goto failure;
+
+  if (!g_permission_acquire (permission, NULL, NULL))
+    goto failure;
+
+  return TRUE;
+
+failure:
+  g_clear_object (&subject);
+  g_clear_object (&permission);
+
+  return FALSE;
+}
+
+static GDBusProxy *
+get_authorized_proxy (void)
+{
+  g_autoptr(GDBusProxy) proxy = NULL;
+
+  proxy = get_proxy ();
+  if (proxy != NULL && authorize_proxy (proxy))
+    return g_steal_pointer (&proxy);
+
+  return NULL;
+}
+#endif
+
+gint
+sp_perf_counter_open (SpPerfCounter          *self,
+                      struct perf_event_attr *attr,
+                      GPid                    pid,
+                      gint                    cpu,
+                      gint                    group_fd,
+                      gulong                  flags)
+{
+#ifdef ENABLE_SYSPROFD
+  g_autoptr(GError) error = NULL;
+  g_autoptr(GDBusProxy) proxy = NULL;
+  g_autoptr(GUnixFDList) fdlist = NULL;
+  g_autoptr(GVariant) res = NULL;
+  g_autoptr(GVariant) params = NULL;
+  gint handle = -1;
+#endif
+  gint ret = -1;
+
+  g_return_val_if_fail (self != NULL, -1);
+  g_return_val_if_fail (attr != NULL, -1);
+
+  /*
+   * First, we try to run the syscall locally, since we should avoid the
+   * polkit request unless we have to use it for elevated privileges.
+   */
+  if (-1 != (ret = syscall (__NR_perf_event_open, attr, pid, cpu, group_fd, flags)))
+    {
+      sp_perf_counter_take_fd (self, ret);
+      return ret;
+    }
+
+#ifdef ENABLE_SYSPROFD
+  params = g_variant_new_parsed (
+                       "("
+                               "["
+                                       "{'comm', <%b>},"
+                                       "{'clockid', <%i>},"
+                                       "{'config', <%t>},"
+                                       "{'disabled', <%b>},"
+                                       "{'exclude_idle', <%b>},"
+                                       "{'mmap', <%b>},"
+                                       "{'wakeup_events', <%u>},"
+                                       "{'sample_period', <%t>},"
+                                       "{'sample_type', <%t>},"
+                                       "{'task', <%b>},"
+                                       "{'type', <%u>},"
+                                       "{'use_clockid', <%b>}"
+                               "],"
+                               "%i,"
+                               "%i,"
+                               "%t"
+                       ")",
+      (gboolean)!!attr->comm,
+      (gint32)attr->clockid,
+      (guint64)attr->config,
+      (gboolean)!!attr->disabled,
+      (gboolean)!!attr->exclude_idle,
+      (gboolean)!!attr->mmap,
+      (guint32)attr->wakeup_events,
+      (guint64)attr->sample_period,
+      (guint64)attr->sample_type,
+      (gboolean)!!attr->task,
+      (guint32)attr->type,
+      (gboolean)!!attr->use_clockid,
+      (gint32)pid,
+      (gint32)cpu,
+      (guint64)flags);
+
+  params = g_variant_ref_sink (params);
+
+  if (NULL == (proxy = get_authorized_proxy ()))
+    {
+      errno = EPERM;
+      return -1;
+    }
+
+  res = g_dbus_proxy_call_with_unix_fd_list_sync (proxy,
+                                                  "PerfEventOpen",
+                                                  params,
+                                                  G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION,
+                                                  60000,
+                                                  NULL,
+                                                  &fdlist,
+                                                  NULL,
+                                                  &error);
+
+  if (res == NULL)
+    {
+      g_autofree gchar *str = g_variant_print (params, TRUE);
+
+      g_warning ("PerfEventOpen: %s: %s", error->message, str);
+      return -1;
+    }
+
+  if (!g_variant_is_of_type (res, (const GVariantType *)"(h)"))
+    {
+      g_warning ("Received something other than a handle");
+      return -1;
+    }
+
+  if (fdlist == NULL)
+    {
+      g_warning ("Failed to receive fdlist");
+      return -1;
+    }
+
+  g_variant_get (res, "(h)", &handle);
+
+  if (-1 == (ret = g_unix_fd_list_get (fdlist, handle, &error)))
+    {
+      g_warning ("%s", error->message);
+      return -1;
+    }
+
+  sp_perf_counter_take_fd (self, ret);
+#endif
+
+  return ret;
+}
+
+void
+sp_perf_counter_set_callback (SpPerfCounter         *self,
+                              SpPerfCounterCallback  callback,
+                              gpointer               callback_data,
+                              GDestroyNotify         callback_data_destroy)
+{
+  g_return_if_fail (self != NULL);
+
+  if (self->callback_data_destroy)
+    self->callback_data_destroy (self->callback_data);
+
+  self->callback = callback;
+  self->callback_data = callback_data;
+  self->callback_data_destroy = callback_data_destroy;
+}
+
+void
+sp_perf_counter_enable (SpPerfCounter *self)
+{
+  g_return_if_fail (self != NULL);
+
+  if (g_atomic_int_add (&self->enabled, 1) == 0)
+    {
+      guint i;
+
+      for (i = 0; i < self->info->len; i++)
+        {
+          SpPerfCounterInfo *info = g_ptr_array_index (self->info, i);
+
+          sp_perf_counter_enable_info (self, info);
+        }
+    }
+}
+
+void
+sp_perf_counter_disable (SpPerfCounter *self)
+{
+  g_return_if_fail (self != NULL);
+
+  if (g_atomic_int_dec_and_test (&self->enabled))
+    {
+      guint i;
+
+      for (i = 0; i < self->info->len; i++)
+        {
+          SpPerfCounterInfo *info = g_ptr_array_index (self->info, i);
+
+          if (0 != ioctl (info->fd, PERF_EVENT_IOC_DISABLE))
+            g_warning ("Failed to disable counters");
+
+          if (!info->in_callback)
+            sp_perf_counter_flush (self, info);
+
+          g_source_modify_unix_fd (self->source, info->fdtag, G_IO_ERR);
+        }
+    }
+}
diff --git a/lib/sp-perf-counter.h b/lib/sp-perf-counter.h
new file mode 100644
index 0000000..d90f8b9
--- /dev/null
+++ b/lib/sp-perf-counter.h
@@ -0,0 +1,138 @@
+/* sp-perf-counter.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_PERF_COUNTER_H
+#define SP_PERF_COUNTER_H
+
+#include <glib-object.h>
+#include <linux/perf_event.h>
+
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_PERF_COUNTER (sp_perf_counter_get_type())
+
+typedef struct _SpPerfCounter SpPerfCounter;
+
+#pragma pack(push, 1)
+
+typedef struct
+{
+  /*
+   * These fields are available as the suffix only because we have specified
+   * them when creating attributes. Be careful about using them.
+   * Ideally, we would probably switch from using structures overlaid with
+   * casts to a reader design, which knows about the attributes.
+   */
+  guint32 pid, tid;
+  guint64 time;
+} SpPerfCounterSuffix;
+
+typedef struct
+{
+  struct perf_event_header header;
+  guint32 pid;
+  guint32 ppid;
+  guint32 tid;
+  guint32 ptid;
+  guint64 time;
+} SpPerfCounterEventFork;
+
+typedef struct
+{
+  struct perf_event_header header;
+  guint32 pid;
+  guint32 tid;
+  gchar comm[0];
+} SpPerfCounterEventComm;
+
+typedef struct
+{
+  struct perf_event_header header;
+  guint32 pid;
+  guint32 ppid;
+  guint32 tid;
+  guint32 ptid;
+  guint64 time;
+} SpPerfCounterEventExit;
+
+typedef struct
+{
+  struct perf_event_header header;
+  guint32 pid;
+  guint32 tid;
+  guint64 addr;
+  guint64 len;
+  guint64 pgoff;
+  char filename[0];
+} SpPerfCounterEventMmap;
+
+typedef struct
+{
+  struct perf_event_header header;
+  guint64 ip;
+  guint32 pid;
+  guint32 tid;
+  guint64 time;
+  guint64 n_ips;
+  guint64 ips[0];
+} SpPerfCounterEventSample;
+
+typedef union
+{
+  struct perf_event_header header;
+  guint8                   raw[0];
+  SpPerfCounterEventFork   fork;
+  SpPerfCounterEventComm   comm;
+  SpPerfCounterEventExit   exit;
+  SpPerfCounterEventMmap   mmap;
+  SpPerfCounterEventSample sample;
+} SpPerfCounterEvent;
+
+#pragma pack(pop)
+
+typedef void (*SpPerfCounterCallback) (SpPerfCounterEvent *event,
+                                       guint               cpu,
+                                       gpointer            user_data);
+
+GType          sp_perf_counter_get_type     (void);
+SpPerfCounter *sp_perf_counter_new          (GMainContext           *context);
+void           sp_perf_counter_set_callback (SpPerfCounter          *self,
+                                             SpPerfCounterCallback   callback,
+                                             gpointer                callback_data,
+                                             GDestroyNotify          callback_data_destroy);
+void           sp_perf_counter_add_pid      (SpPerfCounter          *self,
+                                             GPid                    pid);
+gint           sp_perf_counter_open         (SpPerfCounter          *self,
+                                             struct perf_event_attr *attr,
+                                             GPid                    pid,
+                                             gint                    cpu,
+                                             gint                    group_fd,
+                                             gulong                  flags);
+void           sp_perf_counter_take_fd      (SpPerfCounter          *self,
+                                             int                     fd);
+void           sp_perf_counter_enable       (SpPerfCounter          *self);
+void           sp_perf_counter_disable      (SpPerfCounter          *self);
+void           sp_perf_counter_close        (SpPerfCounter          *self,
+                                             gint                    fd);
+SpPerfCounter *sp_perf_counter_ref          (SpPerfCounter          *self);
+void           sp_perf_counter_unref        (SpPerfCounter          *self);
+
+G_END_DECLS
+
+#endif /* SP_PERF_COUNTER_H */
diff --git a/lib/sp-perf-source.c b/lib/sp-perf-source.c
new file mode 100644
index 0000000..8a4f754
--- /dev/null
+++ b/lib/sp-perf-source.c
@@ -0,0 +1,459 @@
+/* sp-perf-source.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+/* Sysprof -- Sampling, systemwide CPU profiler
+ * Copyright 2004, Red Hat, Inc.
+ * Copyright 2004, 2005, Soeren Sandmann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <gio/gio.h>
+#include <glib/gi18n.h>
+#include <errno.h>
+#include <string.h>
+
+#include "sp-clock.h"
+#include "sp-perf-counter.h"
+#include "sp-perf-source.h"
+
+#define N_WAKEUP_EVENTS 149
+
+struct _SpPerfSource
+{
+  GObject          parent_instance;
+
+  SpCaptureWriter *writer;
+  SpPerfCounter   *counter;
+  GHashTable      *pids;
+
+  guint            running : 1;
+};
+
+static void source_iface_init (SpSourceInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (SpPerfSource, sp_perf_source, G_TYPE_OBJECT, 0,
+                        G_IMPLEMENT_INTERFACE (SP_TYPE_SOURCE, source_iface_init))
+
+enum {
+  TARGET_EXITED,
+  N_SIGNALS
+};
+
+static guint signals [N_SIGNALS];
+
+static void
+sp_perf_source_real_target_exited (SpPerfSource *self)
+{
+  g_assert (SP_IS_PERF_SOURCE (self));
+
+  sp_source_emit_finished (SP_SOURCE (self));
+}
+
+static void
+sp_perf_source_finalize (GObject *object)
+{
+  SpPerfSource *self = (SpPerfSource *)object;
+
+  g_clear_pointer (&self->writer, sp_capture_writer_unref);
+  g_clear_pointer (&self->counter, sp_perf_counter_unref);
+  g_clear_pointer (&self->pids, g_hash_table_unref);
+
+  G_OBJECT_CLASS (sp_perf_source_parent_class)->finalize (object);
+}
+
+static void
+sp_perf_source_class_init (SpPerfSourceClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = sp_perf_source_finalize;
+
+  signals [TARGET_EXITED] =
+    g_signal_new_class_handler ("target-exited",
+                                G_TYPE_FROM_CLASS (klass),
+                                G_SIGNAL_RUN_LAST,
+                                G_CALLBACK (sp_perf_source_real_target_exited),
+                                NULL, NULL, NULL, G_TYPE_NONE, 0);
+}
+
+static void
+sp_perf_source_init (SpPerfSource *self)
+{
+  self->pids = g_hash_table_new (NULL, NULL);
+}
+
+static gboolean
+do_emit_exited (gpointer data)
+{
+  g_autoptr(SpPerfSource) self = data;
+
+  g_signal_emit (self, signals [TARGET_EXITED], 0);
+
+  return G_SOURCE_REMOVE;
+}
+
+static void
+sp_perf_source_handle_sample (SpPerfSource                   *self,
+                              gint                            cpu,
+                              const SpPerfCounterEventSample *sample)
+{
+  const guint64 *ips;
+  gint n_ips;
+  guint64 trace[3];
+
+  g_assert (SP_IS_PERF_SOURCE (self));
+  g_assert (sample != NULL);
+
+  ips = sample->ips;
+  n_ips = sample->n_ips;
+
+  if (n_ips == 0)
+    {
+      if (sample->header.misc & PERF_RECORD_MISC_KERNEL)
+        {
+          trace[0] = PERF_CONTEXT_KERNEL;
+          trace[1] = sample->ip;
+          trace[2] = PERF_CONTEXT_USER;
+
+          ips = trace;
+          n_ips = 3;
+        }
+      else
+        {
+          trace[0] = PERF_CONTEXT_USER;
+          trace[1] = sample->ip;
+
+          ips = trace;
+          n_ips = 2;
+        }
+    }
+
+  sp_capture_writer_add_sample (self->writer,
+                                sample->time,
+                                cpu,
+                                sample->pid,
+                                ips,
+                                n_ips);
+}
+
+static void
+sp_perf_source_handle_event (SpPerfCounterEvent *event,
+                             guint               cpu,
+                             gpointer            user_data)
+{
+  SpPerfSource *self = user_data;
+  SpPerfCounterSuffix *suffix;
+
+  g_assert (SP_IS_PERF_SOURCE (self));
+  g_assert (event != NULL);
+
+  switch (event->header.type)
+    {
+    case PERF_RECORD_COMM:
+      suffix = (SpPerfCounterSuffix *)event->raw
+             + G_STRUCT_OFFSET (SpPerfCounterEventComm, comm)
+             + strlen (event->comm.comm)
+             + 1;
+
+      sp_capture_writer_add_process (self->writer,
+                                     suffix->time,
+                                     cpu,
+                                     event->comm.pid,
+                                     event->comm.comm);
+
+      break;
+
+    case PERF_RECORD_EXIT:
+      sp_capture_writer_add_exit (self->writer,
+                                  event->exit.time,
+                                  cpu,
+                                  event->exit.pid);
+
+      if (g_hash_table_contains (self->pids, GINT_TO_POINTER (event->exit.pid)))
+        {
+          g_hash_table_remove (self->pids, GINT_TO_POINTER (event->exit.pid));
+
+          if (self->running && (g_hash_table_size (self->pids) > 0))
+            {
+              self->running = FALSE;
+              sp_perf_counter_disable (self->counter);
+              g_timeout_add (0, do_emit_exited, g_object_ref (self));
+            }
+        }
+
+      break;
+
+    case PERF_RECORD_FORK:
+      sp_capture_writer_add_fork (self->writer,
+                                  event->fork.time,
+                                  cpu,
+                                  event->fork.ppid,
+                                  event->fork.pid);
+
+      /*
+       * TODO: We should add support for "follow fork" of the GPid if we are
+       *       targetting it.
+       */
+
+      break;
+
+    case PERF_RECORD_LOST:
+      break;
+
+    case PERF_RECORD_MMAP:
+      suffix = (SpPerfCounterSuffix *)event->raw
+             + G_STRUCT_OFFSET (SpPerfCounterEventMmap, filename)
+             + strlen (event->mmap.filename)
+             + 1;
+
+      sp_capture_writer_add_map (self->writer,
+                                 suffix->time,
+                                 cpu,
+                                 event->mmap.pid,
+                                 event->mmap.addr,
+                                 event->mmap.addr + event->mmap.len,
+                                 event->mmap.pgoff,
+                                 0,
+                                 event->mmap.filename);
+
+      break;
+
+    case PERF_RECORD_READ:
+      break;
+
+    case PERF_RECORD_SAMPLE:
+      sp_perf_source_handle_sample (self, cpu, &event->sample);
+      break;
+
+    case PERF_RECORD_THROTTLE:
+    case PERF_RECORD_UNTHROTTLE:
+    default:
+      break;
+    }
+}
+
+static gboolean
+sp_perf_source_start_pid (SpPerfSource  *self,
+                          GPid           pid,
+                          GError       **error)
+{
+  struct perf_event_attr attr = { 0 };
+  gulong flags = 0;
+  gint ncpu = g_get_num_processors ();
+  gint cpu = 0;
+  gint fd;
+
+  g_assert (SP_IS_PERF_SOURCE (self));
+
+  attr.sample_type = PERF_SAMPLE_IP
+                   | PERF_SAMPLE_TID
+                   | PERF_SAMPLE_CALLCHAIN
+                   | PERF_SAMPLE_TIME;
+  attr.wakeup_events = N_WAKEUP_EVENTS;
+  attr.disabled = TRUE;
+  attr.mmap = 1;
+  attr.comm = 1;
+  attr.task = 1;
+  attr.exclude_idle = 1;
+  attr.size = sizeof attr;
+  attr.clockid = sp_clock;
+  attr.use_clockid = 1;
+
+  if (pid != -1)
+    {
+      ncpu = 0;
+      cpu = -1;
+    }
+
+  for (; cpu < ncpu; cpu++)
+    {
+      attr.type = PERF_TYPE_HARDWARE;
+      attr.config = PERF_COUNT_HW_CPU_CYCLES;
+      attr.sample_period = 1200000;
+
+      fd = sp_perf_counter_open (self->counter, &attr, pid, cpu, -1, flags);
+
+      if (fd == -1)
+        {
+          /*
+           * We might just not have access to hardware counters, so try to
+           * gracefully fallback to software counters.
+           */
+          attr.type = PERF_TYPE_SOFTWARE;
+          attr.config = PERF_COUNT_SW_CPU_CLOCK;
+          attr.sample_period = 1000000;
+
+          errno = 0;
+
+          fd = sp_perf_counter_open (self->counter, &attr, pid, cpu, -1, flags);
+
+          if (fd == -1)
+            {
+              if (errno == EPERM || errno == EACCES)
+                g_set_error (error,
+                             G_IO_ERROR,
+                             G_IO_ERROR_PERMISSION_DENIED,
+                             _("Sysprof requires authorization to access your computers performance 
counters."));
+              else
+                g_set_error (error,
+                             G_IO_ERROR,
+                             G_IO_ERROR_FAILED,
+                             _("An error occurred while attempting to access performance counters: %s"),
+                             g_strerror (errno));
+
+              sp_source_stop (SP_SOURCE (self));
+
+              return FALSE;
+            }
+        }
+    }
+
+  return TRUE;
+}
+
+static void
+sp_perf_source_start (SpSource *source)
+{
+  SpPerfSource *self = (SpPerfSource *)source;
+  g_autoptr(GError) error = NULL;
+
+  g_assert (SP_IS_PERF_SOURCE (self));
+
+  self->counter = sp_perf_counter_new (NULL);
+
+  sp_perf_counter_set_callback (self->counter,
+                                sp_perf_source_handle_event,
+                                self, NULL);
+
+  if (g_hash_table_size (self->pids) > 0)
+    {
+      GHashTableIter iter;
+      gpointer key;
+
+      g_hash_table_iter_init (&iter, self->pids);
+
+      while (g_hash_table_iter_next (&iter, &key, NULL))
+        {
+          GPid pid = GPOINTER_TO_INT (key);
+
+          if (!sp_perf_source_start_pid (self, pid, &error))
+            {
+              sp_source_emit_failed (source, error);
+              return;
+            }
+        }
+    }
+  else
+    {
+      if (!sp_perf_source_start_pid (self, -1, &error))
+        {
+          sp_source_emit_failed (source, error);
+          return;
+        }
+    }
+
+  self->running = TRUE;
+
+  sp_perf_counter_enable (self->counter);
+
+  sp_source_emit_ready (source);
+}
+
+static void
+sp_perf_source_stop (SpSource *source)
+{
+  SpPerfSource *self = (SpPerfSource *)source;
+
+  g_assert (SP_IS_PERF_SOURCE (self));
+
+  if (self->running)
+    {
+      self->running = FALSE;
+      sp_perf_counter_disable (self->counter);
+    }
+
+  g_clear_pointer (&self->counter, sp_perf_counter_unref);
+
+  sp_source_emit_finished (source);
+}
+
+static void
+sp_perf_source_set_writer (SpSource        *source,
+                           SpCaptureWriter *writer)
+{
+  SpPerfSource *self = (SpPerfSource *)source;
+
+  g_assert (SP_IS_PERF_SOURCE (self));
+  g_assert (writer != NULL);
+
+  self->writer = sp_capture_writer_ref (writer);
+}
+
+static void
+sp_perf_source_add_pid (SpSource *source,
+                        GPid      pid)
+{
+  SpPerfSource *self = (SpPerfSource *)source;
+
+  g_return_if_fail (SP_IS_PERF_SOURCE (self));
+  g_return_if_fail (pid >= -1);
+  g_return_if_fail (self->writer == NULL);
+
+  g_hash_table_add (self->pids, GINT_TO_POINTER (pid));
+}
+
+static void
+source_iface_init (SpSourceInterface *iface)
+{
+  iface->start = sp_perf_source_start;
+  iface->stop = sp_perf_source_stop;
+  iface->set_writer = sp_perf_source_set_writer;
+  iface->add_pid = sp_perf_source_add_pid;
+}
+
+SpSource *
+sp_perf_source_new (void)
+{
+  return g_object_new (SP_TYPE_PERF_SOURCE, NULL);
+}
+
+void
+sp_perf_source_set_target_pid (SpPerfSource *self,
+                               GPid          pid)
+{
+  g_return_if_fail (SP_IS_PERF_SOURCE (self));
+  g_return_if_fail (pid >= -1);
+
+  if (pid == -1)
+    g_hash_table_remove_all (self->pids);
+  else
+    sp_perf_source_add_pid (SP_SOURCE (self), pid);
+}
diff --git a/lib/sp-perf-source.h b/lib/sp-perf-source.h
new file mode 100644
index 0000000..864467b
--- /dev/null
+++ b/lib/sp-perf-source.h
@@ -0,0 +1,36 @@
+/* sp-perf-source.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_PERF_SOURCE_H
+#define SP_PERF_SOURCE_H
+
+#include "sp-source.h"
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_PERF_SOURCE (sp_perf_source_get_type())
+
+G_DECLARE_FINAL_TYPE (SpPerfSource, sp_perf_source, SP, PERF_SOURCE, GObject)
+
+SpSource *sp_perf_source_new            (void);
+void      sp_perf_source_set_target_pid (SpPerfSource *self,
+                                         GPid          pid);
+
+G_END_DECLS
+
+#endif /* SP_PERF_SOURCE_H */
diff --git a/lib/sp-proc-source.c b/lib/sp-proc-source.c
new file mode 100644
index 0000000..efe7093
--- /dev/null
+++ b/lib/sp-proc-source.c
@@ -0,0 +1,347 @@
+/* sp-proc-source.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+/* Sysprof -- Sampling, systemwide CPU profiler
+ * Copyright 2004, Red Hat, Inc.
+ * Copyright 2004, 2005, Soeren Sandmann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "sp-proc-source.h"
+
+struct _SpProcSource
+{
+  GObject          parent_instance;
+  SpCaptureWriter *writer;
+  GArray          *pids;
+};
+
+static void    source_iface_init (SpSourceInterface *iface);
+static gchar **proc_readlines    (const gchar       *format,
+                                  ...)
+  G_GNUC_PRINTF (1, 2);
+
+G_DEFINE_TYPE_EXTENDED (SpProcSource, sp_proc_source, G_TYPE_OBJECT, 0,
+                        G_IMPLEMENT_INTERFACE (SP_TYPE_SOURCE, source_iface_init))
+
+static gchar **
+proc_readlines (const gchar *format,
+                ...)
+{
+  gchar **ret = NULL;
+  gchar *filename = NULL;
+  gchar *contents = NULL;
+  va_list args;
+  gsize len;
+
+  g_assert (format != NULL);
+
+  va_start (args, format);
+  filename = g_strdup_vprintf (format, args);
+  va_end (args);
+
+  if (g_file_get_contents (filename, &contents, &len, NULL))
+    ret = g_strsplit (contents, "\n", 0);
+
+  g_free (contents);
+  g_free (filename);
+
+  return ret;
+}
+
+gchar *
+sp_proc_source_get_command_line (GPid      pid,
+                                 gboolean *is_kernel)
+{
+  gchar *ret;
+  gchar **lines;
+
+
+  if (is_kernel)
+    *is_kernel = FALSE;
+
+  /*
+   * Get the full command line from /proc/pid/cmdline.
+   */
+  if (NULL != (lines = proc_readlines ("/proc/%d/cmdline", pid)))
+    {
+      if (lines [0] && lines [0][0])
+        {
+          ret = g_strdup (lines [0]);
+          g_strfreev (lines);
+          return ret;
+        }
+
+      g_strfreev (lines);
+    }
+
+  /*
+   * We are guessing this is a kernel process based on cmdline being null.
+   */
+  if (is_kernel)
+    *is_kernel = TRUE;
+
+  /*
+   * Check the first line of /proc/pid/status for Name: foo
+   */
+  if (NULL != (lines = proc_readlines ("/proc/%d/status", pid)))
+    {
+      if (lines [0] && g_str_has_prefix (lines [0], "Name:"))
+        {
+          ret = g_strstrip (g_strdup (lines [0] + 5));
+          g_strfreev (lines);
+          return ret;
+        }
+
+      g_strfreev (lines);
+    }
+
+  return NULL;
+}
+
+static void
+sp_proc_source_populate_process (SpProcSource *self,
+                                 GPid          pid)
+{
+  gchar *cmdline;
+
+  g_assert (SP_IS_PROC_SOURCE (self));
+  g_assert (pid > 0);
+
+  if (NULL != (cmdline = sp_proc_source_get_command_line (pid, NULL)))
+    {
+      sp_capture_writer_add_process (self->writer,
+                                     SP_CAPTURE_CURRENT_TIME,
+                                     -1,
+                                     pid,
+                                     cmdline);
+      g_free (cmdline);
+    }
+}
+
+static void
+sp_proc_source_populate_maps (SpProcSource *self,
+                              GPid          pid)
+{
+  g_auto(GStrv) lines = NULL;
+  guint i;
+
+  g_assert (SP_IS_PROC_SOURCE (self));
+  g_assert (pid > 0);
+
+  if (NULL == (lines = proc_readlines ("/proc/%d/maps", pid)))
+    return;
+
+  for (i = 0; lines [i] != NULL; i++)
+    {
+      gchar file[256];
+      gulong start;
+      gulong end;
+      gulong offset;
+      gulong inode;
+      gint r;
+
+      r = sscanf (lines [i],
+                  "%lx-%lx %*15s %lx %*x:%*x %lu %255s",
+                  &start, &end, &offset, &inode, file);
+
+      file [sizeof file - 1] = '\0';
+
+      if (r != 5)
+        continue;
+
+      if (strcmp ("[vdso]", file) == 0)
+        {
+          /*
+           * Søren Sandmann Pedersen says:
+           *
+           * For the vdso, the kernel reports 'offset' as the
+           * the same as the mapping addres. This doesn't make
+           * any sense to me, so we just zero it here. There
+           * is code in binfile.c (read_inode) that returns 0
+           * for [vdso].
+           */
+          offset = 0;
+          inode = 0;
+        }
+
+      sp_capture_writer_add_map (self->writer,
+                                 SP_CAPTURE_CURRENT_TIME,
+                                 -1,
+                                 pid,
+                                 start,
+                                 end,
+                                 offset,
+                                 inode,
+                                 file);
+    }
+}
+
+static void
+sp_proc_source_populate (SpProcSource *self)
+{
+  const gchar *name;
+  GDir *dir;
+
+  g_assert (SP_IS_PROC_SOURCE (self));
+
+  if (self->pids->len > 0)
+    {
+      guint i;
+
+      for (i = 0; i < self->pids->len; i++)
+        {
+          GPid pid = g_array_index (self->pids, GPid, i);
+
+          sp_proc_source_populate_process (self, pid);
+          sp_proc_source_populate_maps (self, pid);
+        }
+
+      return;
+    }
+
+  if (NULL == (dir = g_dir_open ("/proc", 0, NULL)))
+    return;
+
+  while (NULL != (name = g_dir_read_name (dir)))
+    {
+      GPid pid;
+      char *end;
+
+      pid = strtol (name, &end, 10);
+      if (pid <= 0 || *end != '\0')
+        continue;
+
+      sp_proc_source_populate_process (self, pid);
+      sp_proc_source_populate_maps (self, pid);
+    }
+
+  g_dir_close (dir);
+}
+
+static void
+sp_proc_source_start (SpSource *source)
+{
+  SpProcSource *self = (SpProcSource *)source;
+
+  g_assert (SP_IS_PROC_SOURCE (self));
+  g_assert (self->writer != NULL);
+
+  sp_proc_source_populate (self);
+  sp_source_emit_finished (source);
+}
+
+static void
+sp_proc_source_stop (SpSource *source)
+{
+  SpProcSource *self = (SpProcSource *)source;
+
+  g_assert (SP_IS_PROC_SOURCE (self));
+
+  g_clear_pointer (&self->writer, sp_capture_writer_unref);
+}
+
+static void
+sp_proc_source_set_writer (SpSource        *source,
+                           SpCaptureWriter *writer)
+{
+  SpProcSource *self = (SpProcSource *)source;
+
+  g_assert (SP_IS_PROC_SOURCE (self));
+  g_assert (writer != NULL);
+
+  self->writer = sp_capture_writer_ref (writer);
+}
+
+static void
+sp_proc_source_add_pid (SpSource *source,
+                        GPid      pid)
+{
+  SpProcSource *self = (SpProcSource *)source;
+  guint i;
+
+  g_assert (SP_IS_PROC_SOURCE (self));
+  g_assert (pid > -1);
+
+  for (i = 0; i < self->pids->len; i++)
+    {
+      GPid ele = g_array_index (self->pids, GPid, i);
+
+      if (ele == pid)
+        return;
+    }
+
+  g_array_append_val (self->pids, pid);
+}
+
+static void
+source_iface_init (SpSourceInterface *iface)
+{
+  iface->set_writer = sp_proc_source_set_writer;
+  iface->start = sp_proc_source_start;
+  iface->stop = sp_proc_source_stop;
+  iface->add_pid = sp_proc_source_add_pid;
+}
+
+static void
+sp_proc_source_finalize (GObject *object)
+{
+  SpProcSource *self = (SpProcSource *)object;
+
+  g_clear_pointer (&self->writer, sp_capture_writer_unref);
+  g_clear_pointer (&self->pids, g_array_unref);
+
+  G_OBJECT_CLASS (sp_proc_source_parent_class)->finalize (object);
+}
+
+static void
+sp_proc_source_class_init (SpProcSourceClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = sp_proc_source_finalize;
+}
+
+static void
+sp_proc_source_init (SpProcSource *self)
+{
+  self->pids = g_array_new (FALSE, FALSE, sizeof (GPid));
+}
+
+SpSource *
+sp_proc_source_new (void)
+{
+  return g_object_new (SP_TYPE_PROC_SOURCE, NULL);
+}
diff --git a/lib/sp-proc-source.h b/lib/sp-proc-source.h
new file mode 100644
index 0000000..b0883ed
--- /dev/null
+++ b/lib/sp-proc-source.h
@@ -0,0 +1,36 @@
+/* sp-proc-source.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_PROC_SOURCE_H
+#define SP_PROC_SOURCE_H
+
+#include "sp-source.h"
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_PROC_SOURCE (sp_proc_source_get_type())
+
+G_DECLARE_FINAL_TYPE (SpProcSource, sp_proc_source, SP, PROC_SOURCE, GObject)
+
+SpSource *sp_proc_source_new              (void);
+gchar    *sp_proc_source_get_command_line (GPid          pid,
+                                           gboolean     *is_kernel);
+
+G_END_DECLS
+
+#endif /* SP_PROC_SOURCE_H */
diff --git a/lib/sp-process-model-item.c b/lib/sp-process-model-item.c
new file mode 100644
index 0000000..7067dc6
--- /dev/null
+++ b/lib/sp-process-model-item.c
@@ -0,0 +1,191 @@
+/* sp-process-model-item.c
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#include "sp-process-model-item.h"
+#include "sp-proc-source.h"
+
+struct _SpProcessModelItem
+{
+  GObject  parent_instance;
+  GPid     pid;
+  gchar   *command_line;
+  guint    is_kernel : 1;
+};
+
+G_DEFINE_TYPE (SpProcessModelItem, sp_process_model_item, G_TYPE_OBJECT)
+
+enum {
+  PROP_0,
+  PROP_COMMAND_LINE,
+  PROP_PID,
+  N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+sp_process_model_item_finalize (GObject *object)
+{
+  SpProcessModelItem *self = (SpProcessModelItem *)object;
+
+  g_clear_pointer (&self->command_line, g_free);
+
+  G_OBJECT_CLASS (sp_process_model_item_parent_class)->finalize (object);
+}
+
+static void
+sp_process_model_item_get_property (GObject    *object,
+                                    guint       prop_id,
+                                    GValue     *value,
+                                    GParamSpec *pspec)
+{
+  SpProcessModelItem *self = SP_PROCESS_MODEL_ITEM (object);
+
+  switch (prop_id)
+    {
+    case PROP_COMMAND_LINE:
+      g_value_set_string (value, self->command_line);
+      break;
+
+    case PROP_PID:
+      g_value_set_int (value, self->pid);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+sp_process_model_item_set_property (GObject      *object,
+                                    guint         prop_id,
+                                    const GValue *value,
+                                    GParamSpec   *pspec)
+{
+  SpProcessModelItem *self = SP_PROCESS_MODEL_ITEM (object);
+
+  switch (prop_id)
+    {
+    case PROP_COMMAND_LINE:
+      self->command_line = g_value_dup_string (value);
+      break;
+
+    case PROP_PID:
+      self->pid = g_value_get_int (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+sp_process_model_item_class_init (SpProcessModelItemClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = sp_process_model_item_finalize;
+  object_class->get_property = sp_process_model_item_get_property;
+  object_class->set_property = sp_process_model_item_set_property;
+
+  properties [PROP_COMMAND_LINE] =
+    g_param_spec_string ("command-line",
+                         "Command Line",
+                         "Command Line",
+                         NULL,
+                         (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+  properties [PROP_PID] =
+    g_param_spec_int ("pid",
+                      "Pid",
+                      "Pid",
+                      -1,
+                      G_MAXINT,
+                      -1,
+                      (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+sp_process_model_item_init (SpProcessModelItem *self)
+{
+}
+
+SpProcessModelItem *
+sp_process_model_item_new (GPid pid)
+{
+  SpProcessModelItem *ret;
+  gchar *cmdline;
+  gboolean is_kernel;
+
+  cmdline = sp_proc_source_get_command_line (pid, &is_kernel);
+
+  ret = g_object_new (SP_TYPE_PROCESS_MODEL_ITEM,
+                      "command-line", cmdline,
+                      "pid", (int)pid,
+                      NULL);
+  ret->is_kernel = is_kernel;
+
+  g_free (cmdline);
+
+  return ret;
+}
+
+guint
+sp_process_model_item_hash (SpProcessModelItem *self)
+{
+  g_return_val_if_fail (SP_IS_PROCESS_MODEL_ITEM (self), 0);
+
+  return self->pid;
+}
+
+gboolean
+sp_process_model_item_equal (SpProcessModelItem *self,
+                             SpProcessModelItem *other)
+{
+  g_assert (SP_IS_PROCESS_MODEL_ITEM (self));
+  g_assert (SP_IS_PROCESS_MODEL_ITEM (other));
+
+  return ((self->pid == other->pid) &&
+          (g_strcmp0 (self->command_line, other->command_line) == 0));
+}
+
+GPid
+sp_process_model_item_get_pid (SpProcessModelItem *self)
+{
+  g_return_val_if_fail (SP_IS_PROCESS_MODEL_ITEM (self), 0);
+
+  return self->pid;
+}
+
+const gchar *
+sp_process_model_item_get_command_line (SpProcessModelItem *self)
+{
+  g_return_val_if_fail (SP_IS_PROCESS_MODEL_ITEM (self), NULL);
+
+  return self->command_line;
+}
+
+gboolean
+sp_process_model_item_is_kernel (SpProcessModelItem *self)
+{
+  g_return_val_if_fail (SP_IS_PROCESS_MODEL_ITEM (self), FALSE);
+
+  return self->is_kernel;
+}
diff --git a/lib/sp-process-model-item.h b/lib/sp-process-model-item.h
new file mode 100644
index 0000000..850a741
--- /dev/null
+++ b/lib/sp-process-model-item.h
@@ -0,0 +1,40 @@
+/* sp-process-model-item.h
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_PROCESS_MODEL_ITEM_H
+#define SP_PROCESS_MODEL_ITEM_H
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_PROCESS_MODEL_ITEM (sp_process_model_item_get_type())
+
+G_DECLARE_FINAL_TYPE (SpProcessModelItem, sp_process_model_item, SP, PROCESS_MODEL_ITEM, GObject)
+
+SpProcessModelItem *sp_process_model_item_new              (GPid                pid);
+guint               sp_process_model_item_hash             (SpProcessModelItem *self);
+gboolean            sp_process_model_item_equal            (SpProcessModelItem *self,
+                                                            SpProcessModelItem *other);
+GPid                sp_process_model_item_get_pid          (SpProcessModelItem *self);
+const gchar        *sp_process_model_item_get_command_line (SpProcessModelItem *self);
+gboolean            sp_process_model_item_is_kernel        (SpProcessModelItem *self);
+
+G_END_DECLS
+
+#endif /* SP_PROCESS_MODEL_ITEM_H */
diff --git a/lib/sp-process-model-row.c b/lib/sp-process-model-row.c
new file mode 100644
index 0000000..b8e6e77
--- /dev/null
+++ b/lib/sp-process-model-row.c
@@ -0,0 +1,209 @@
+/* sp-process-model-row.c
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#include "sp-process-model-row.h"
+
+typedef struct
+{
+  SpProcessModelItem *item;
+
+  GtkLabel *label;
+  GtkLabel *pid;
+  GtkImage *image;
+  GtkImage *check;
+} SpProcessModelRowPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (SpProcessModelRow, sp_process_model_row, GTK_TYPE_LIST_BOX_ROW)
+
+enum {
+  PROP_0,
+  PROP_ITEM,
+  PROP_SELECTED,
+  N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+GtkWidget *
+sp_process_model_row_new (SpProcessModelItem *item)
+{
+  return g_object_new (SP_TYPE_PROCESS_MODEL_ROW,
+                       "item", item,
+                       NULL);
+}
+
+SpProcessModelItem *
+sp_process_model_row_get_item (SpProcessModelRow *self)
+{
+  SpProcessModelRowPrivate *priv = sp_process_model_row_get_instance_private (self);
+
+  g_return_val_if_fail (SP_IS_PROCESS_MODEL_ROW (self), NULL);
+
+  return priv->item;
+}
+
+static void
+sp_process_model_row_set_item (SpProcessModelRow  *self,
+                               SpProcessModelItem *item)
+{
+  SpProcessModelRowPrivate *priv = sp_process_model_row_get_instance_private (self);
+
+  g_assert (SP_IS_PROCESS_MODEL_ROW (self));
+  g_assert (SP_IS_PROCESS_MODEL_ITEM (item));
+
+  if (g_set_object (&priv->item, item))
+    {
+      const gchar *command_line;
+      g_auto(GStrv) parts = NULL;
+      g_autofree gchar *pidstr = NULL;
+      GPid pid;
+
+      command_line = sp_process_model_item_get_command_line (item);
+      parts = g_strsplit (command_line ?: "", "\n", 0);
+      gtk_label_set_label (priv->label, parts [0]);
+
+      pid = sp_process_model_item_get_pid (item);
+      pidstr = g_strdup_printf ("<small>%u</small>", pid);
+      gtk_label_set_label (priv->pid, pidstr);
+      gtk_label_set_use_markup (priv->pid, TRUE);
+    }
+}
+
+gboolean
+sp_process_model_row_get_selected (SpProcessModelRow *self)
+{
+  SpProcessModelRowPrivate *priv = sp_process_model_row_get_instance_private (self);
+
+  g_return_val_if_fail (SP_IS_PROCESS_MODEL_ROW (self), FALSE);
+
+  return gtk_widget_get_visible (GTK_WIDGET (priv->check));
+}
+
+void
+sp_process_model_row_set_selected (SpProcessModelRow *self,
+                                   gboolean           selected)
+{
+  SpProcessModelRowPrivate *priv = sp_process_model_row_get_instance_private (self);
+
+  g_return_if_fail (SP_IS_PROCESS_MODEL_ROW (self));
+
+  selected = !!selected;
+
+  if (selected != sp_process_model_row_get_selected (self))
+    {
+      gtk_widget_set_visible (GTK_WIDGET (priv->check), selected);
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SELECTED]);
+    }
+}
+
+static void
+sp_process_model_row_finalize (GObject *object)
+{
+  SpProcessModelRow *self = (SpProcessModelRow *)object;
+  SpProcessModelRowPrivate *priv = sp_process_model_row_get_instance_private (self);
+
+  g_clear_object (&priv->item);
+
+  G_OBJECT_CLASS (sp_process_model_row_parent_class)->finalize (object);
+}
+
+static void
+sp_process_model_row_get_property (GObject    *object,
+                                   guint       prop_id,
+                                   GValue     *value,
+                                   GParamSpec *pspec)
+{
+  SpProcessModelRow *self = SP_PROCESS_MODEL_ROW (object);
+
+  switch (prop_id)
+    {
+    case PROP_ITEM:
+      g_value_set_object (value, sp_process_model_row_get_item (self));
+      break;
+
+    case PROP_SELECTED:
+      g_value_set_boolean (value, sp_process_model_row_get_selected (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+sp_process_model_row_set_property (GObject      *object,
+                                   guint         prop_id,
+                                   const GValue *value,
+                                   GParamSpec   *pspec)
+{
+  SpProcessModelRow *self = SP_PROCESS_MODEL_ROW (object);
+
+  switch (prop_id)
+    {
+    case PROP_ITEM:
+      sp_process_model_row_set_item (self, g_value_get_object (value));
+      break;
+
+    case PROP_SELECTED:
+      sp_process_model_row_set_selected (self, g_value_get_boolean (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+sp_process_model_row_class_init (SpProcessModelRowClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->finalize = sp_process_model_row_finalize;
+  object_class->get_property = sp_process_model_row_get_property;
+  object_class->set_property = sp_process_model_row_set_property;
+
+  properties [PROP_ITEM] =
+    g_param_spec_object ("item",
+                         "Item",
+                         "Item",
+                         SP_TYPE_PROCESS_MODEL_ITEM,
+                         (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  properties [PROP_SELECTED] =
+    g_param_spec_boolean ("selected",
+                          "Selected",
+                          "Selected",
+                          FALSE,
+                          (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+
+  gtk_widget_class_set_template_from_resource (widget_class,
+                                               "/org/gnome/sysprof/ui/sp-process-model-row.ui");
+  gtk_widget_class_bind_template_child_private (widget_class, SpProcessModelRow, image);
+  gtk_widget_class_bind_template_child_private (widget_class, SpProcessModelRow, label);
+  gtk_widget_class_bind_template_child_private (widget_class, SpProcessModelRow, pid);
+  gtk_widget_class_bind_template_child_private (widget_class, SpProcessModelRow, check);
+}
+
+static void
+sp_process_model_row_init (SpProcessModelRow *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
diff --git a/lib/sp-process-model-row.h b/lib/sp-process-model-row.h
new file mode 100644
index 0000000..2d9f1df
--- /dev/null
+++ b/lib/sp-process-model-row.h
@@ -0,0 +1,46 @@
+/* sp-process-model-row.h
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_PROCESS_MODEL_ROW_H
+#define SP_PROCESS_MODEL_ROW_H
+
+#include <gtk/gtk.h>
+
+#include "sp-process-model-item.h"
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_PROCESS_MODEL_ROW (sp_process_model_row_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (SpProcessModelRow, sp_process_model_row, SP, PROCESS_MODEL_ROW, GtkListBoxRow)
+
+struct _SpProcessModelRowClass
+{
+  GtkListBoxRowClass parent;
+};
+
+GtkWidget          *sp_process_model_row_new          (SpProcessModelItem *item);
+SpProcessModelItem *sp_process_model_row_get_item     (SpProcessModelRow  *self);
+gboolean            sp_process_model_row_get_selected (SpProcessModelRow  *self);
+void                sp_process_model_row_set_selected (SpProcessModelRow  *self,
+                                                       gboolean            selected);
+
+G_END_DECLS
+
+#endif /* SP_PROCESS_MODEL_ROW_H */
+
diff --git a/lib/sp-process-model.c b/lib/sp-process-model.c
new file mode 100644
index 0000000..eba686e
--- /dev/null
+++ b/lib/sp-process-model.c
@@ -0,0 +1,293 @@
+/* sp-process-model.c
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#include <stdlib.h>
+
+#include "sp-process-model.h"
+#include "sp-process-model-item.h"
+
+#define QUEUE_RELOAD_TIMEOUT_MSEC 100
+
+struct _SpProcessModel
+{
+  GObject    parent_instance;
+  guint      reload_source;
+  GPtrArray *items;
+};
+
+static void list_model_iface_init (GListModelInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (SpProcessModel, sp_process_model, G_TYPE_OBJECT, 0,
+                        G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, list_model_iface_init))
+
+static void
+sp_process_model_finalize (GObject *object)
+{
+  SpProcessModel *self = (SpProcessModel *)object;
+
+  if (self->reload_source)
+    {
+      g_source_remove (self->reload_source);
+      self->reload_source = 0;
+    }
+
+  g_clear_pointer (&self->items, g_ptr_array_unref);
+
+  G_OBJECT_CLASS (sp_process_model_parent_class)->finalize (object);
+}
+
+static void
+sp_process_model_class_init (SpProcessModelClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = sp_process_model_finalize;
+}
+
+static void
+sp_process_model_init (SpProcessModel *self)
+{
+  self->items = g_ptr_array_new_with_free_func (g_object_unref);
+
+  sp_process_model_queue_reload (self);
+}
+
+static guint
+find_index (GPtrArray *ar,
+            GPid       pid)
+{
+  guint i;
+
+  g_assert (ar != NULL);
+
+  for (i = 0; i < ar->len; i++)
+    {
+      SpProcessModelItem *item = g_ptr_array_index (ar, i);
+      GPid item_pid = sp_process_model_item_get_pid (item);
+
+      g_assert (pid != item_pid);
+
+      if (item_pid > pid)
+        return i;
+    }
+
+  return ar->len;
+}
+
+static void
+sp_process_model_merge_cb (GObject      *object,
+                           GAsyncResult *result,
+                           gpointer      user_data)
+{
+  SpProcessModel *self = (SpProcessModel *)object;
+  g_autoptr(GPtrArray) ret = NULL;
+  g_autoptr(GHashTable) old_hash = NULL;
+  g_autoptr(GHashTable) new_hash = NULL;
+  GError *error = NULL;
+  guint i;
+
+  g_assert (SP_IS_PROCESS_MODEL (self));
+  g_assert (G_IS_TASK (result));
+
+  ret = g_task_propagate_pointer (G_TASK (result), &error);
+
+  if (ret == NULL)
+    {
+      g_warning ("%s", error->message);
+      g_clear_error (&error);
+      return;
+    }
+
+  /*
+   * TODO: Clearly this could be optimized to walk both arrays at once
+   *       and do a proper 2-way merge.
+   */
+
+  old_hash = g_hash_table_new ((GHashFunc)sp_process_model_item_hash,
+                               (GEqualFunc)sp_process_model_item_equal);
+  new_hash = g_hash_table_new ((GHashFunc)sp_process_model_item_hash,
+                               (GEqualFunc)sp_process_model_item_equal);
+
+  for (i = 0; i < self->items->len; i++)
+    {
+      SpProcessModelItem *item = g_ptr_array_index (self->items, i);
+
+      g_hash_table_insert (old_hash, item, NULL);
+    }
+
+  for (i = 0; i < ret->len; i++)
+    {
+      SpProcessModelItem *item = g_ptr_array_index (ret, i);
+
+      g_hash_table_insert (new_hash, item, NULL);
+    }
+
+  for (i = self->items->len; i > 0; i--)
+    {
+      guint index = i - 1;
+      SpProcessModelItem *item = g_ptr_array_index (self->items, index);
+
+      if (!g_hash_table_contains (new_hash, item))
+        {
+          g_ptr_array_remove_index (self->items, index);
+          g_list_model_items_changed (G_LIST_MODEL (self), index, 1, 0);
+        }
+    }
+
+  for (i = 0; i < ret->len; i++)
+    {
+      SpProcessModelItem *item = g_ptr_array_index (ret, i);
+      GPid pid;
+      guint index;
+
+      if (g_hash_table_contains (old_hash, item))
+        continue;
+
+      pid = sp_process_model_item_get_pid (item);
+      index = find_index (self->items, pid);
+
+      g_ptr_array_insert (self->items, index, g_object_ref (item));
+      g_list_model_items_changed (G_LIST_MODEL (self), index, 0, 1);
+    }
+}
+
+static gint
+compare_by_pid (gconstpointer a,
+                gconstpointer b)
+{
+  SpProcessModelItem **aitem = (SpProcessModelItem **)a;
+  SpProcessModelItem **bitem = (SpProcessModelItem **)b;
+
+  return sp_process_model_item_get_pid (*aitem) - sp_process_model_item_get_pid (*bitem);
+}
+
+static void
+sp_process_model_reload_worker (GTask        *task,
+                                gpointer      source_object,
+                                gpointer      task_data,
+                                GCancellable *cancellable)
+{
+  g_autoptr(GPtrArray) ret = NULL;
+  const gchar *name;
+  GError *error = NULL;
+  GDir *dir;
+
+  g_assert (SP_IS_PROCESS_MODEL (source_object));
+  g_assert (G_IS_TASK (task));
+
+  dir = g_dir_open ("/proc", 0, &error);
+
+  if (dir == NULL)
+    {
+      g_task_return_error (task, error);
+      return;
+    }
+
+  ret = g_ptr_array_new_with_free_func (g_object_unref);
+
+  while ((name = g_dir_read_name (dir)))
+    {
+      SpProcessModelItem *item;
+      GPid pid;
+      gchar *end;
+
+      pid = strtol (name, &end, 10);
+      if (pid <= 0 || *end != '\0')
+        continue;
+
+      item = sp_process_model_item_new (pid);
+
+      if (sp_process_model_item_is_kernel (item))
+        {
+          g_object_unref (item);
+          continue;
+        }
+
+      g_ptr_array_add (ret, item);
+    }
+
+  g_dir_close (dir);
+
+  g_ptr_array_sort (ret, compare_by_pid);
+  g_task_return_pointer (task, g_ptr_array_ref (ret), (GDestroyNotify)g_ptr_array_unref);
+}
+
+static gboolean
+sp_process_model_do_reload (gpointer user_data)
+{
+  SpProcessModel *self = user_data;
+  g_autoptr(GTask) task = NULL;
+
+  self->reload_source = 0;
+
+  task = g_task_new (self, NULL, sp_process_model_merge_cb, NULL);
+  g_task_run_in_thread (task, sp_process_model_reload_worker);
+
+  return G_SOURCE_REMOVE;
+}
+
+SpProcessModel *
+sp_process_model_new (void)
+{
+  return g_object_new (SP_TYPE_PROCESS_MODEL, NULL);
+}
+
+void
+sp_process_model_queue_reload (SpProcessModel *self)
+{
+  g_return_if_fail (SP_IS_PROCESS_MODEL (self));
+
+  if (self->reload_source == 0)
+    self->reload_source = g_timeout_add (QUEUE_RELOAD_TIMEOUT_MSEC,
+                                         sp_process_model_do_reload,
+                                         self);
+}
+
+static GType
+sp_process_model_get_item_type (GListModel *model)
+{
+  return SP_TYPE_PROCESS_MODEL_ITEM;
+}
+
+static guint
+sp_process_model_get_n_items (GListModel *model)
+{
+  SpProcessModel *self = (SpProcessModel *)model;
+
+  return self->items->len;
+}
+
+static gpointer
+sp_process_model_get_item (GListModel *model,
+                           guint       position)
+{
+  SpProcessModel *self = (SpProcessModel *)model;
+
+  g_return_val_if_fail (SP_IS_PROCESS_MODEL (self), NULL);
+  g_return_val_if_fail (position < self->items->len, NULL);
+
+  return g_object_ref (g_ptr_array_index (self->items, position));
+}
+
+static void
+list_model_iface_init (GListModelInterface *iface)
+{
+  iface->get_item_type = sp_process_model_get_item_type;
+  iface->get_n_items = sp_process_model_get_n_items;
+  iface->get_item = sp_process_model_get_item;
+}
diff --git a/lib/sp-process-model.h b/lib/sp-process-model.h
new file mode 100644
index 0000000..8b16037
--- /dev/null
+++ b/lib/sp-process-model.h
@@ -0,0 +1,35 @@
+/* sp-process-model.h
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_PROCESS_MODEL_H
+#define SP_PROCESS_MODEL_H
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_PROCESS_MODEL (sp_process_model_get_type())
+
+G_DECLARE_FINAL_TYPE (SpProcessModel, sp_process_model, SP, PROCESS_MODEL, GObject)
+
+SpProcessModel *sp_process_model_new          (void);
+void            sp_process_model_queue_reload (SpProcessModel *self);
+
+G_END_DECLS
+
+#endif /* SP_PROCESS_MODEL_H */
diff --git a/lib/sp-profile.c b/lib/sp-profile.c
new file mode 100644
index 0000000..9a4d701
--- /dev/null
+++ b/lib/sp-profile.c
@@ -0,0 +1,81 @@
+/* sp-profile.c
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#include "sp-profile.h"
+
+G_DEFINE_INTERFACE (SpProfile, sp_profile, G_TYPE_OBJECT)
+
+static void
+dummy_generate (SpProfile           *self,
+                GCancellable        *cancellable,
+                GAsyncReadyCallback  callback,
+                gpointer             user_data)
+{
+  g_autoptr(GTask) task = NULL;
+
+  task = g_task_new (self, cancellable, callback, user_data);
+  g_task_return_boolean (task, TRUE);
+}
+
+static gboolean
+dummy_generate_finish (SpProfile     *self,
+                       GAsyncResult  *result,
+                       GError       **error)
+{
+  return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+static void
+sp_profile_default_init (SpProfileInterface *iface)
+{
+  iface->generate = dummy_generate;
+  iface->generate_finish = dummy_generate_finish;
+}
+
+void
+sp_profile_generate (SpProfile           *self,
+                     GCancellable        *cancellable,
+                     GAsyncReadyCallback  callback,
+                     gpointer             user_data)
+{
+  g_return_if_fail (SP_IS_PROFILE (self));
+  g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  SP_PROFILE_GET_IFACE (self)->generate (self, cancellable, callback, user_data);
+}
+
+gboolean
+sp_profile_generate_finish (SpProfile     *self,
+                            GAsyncResult  *result,
+                            GError       **error)
+{
+  g_return_val_if_fail (SP_IS_PROFILE (self), FALSE);
+  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+  return SP_PROFILE_GET_IFACE (self)->generate_finish (self, result, error);
+}
+
+void
+sp_profile_set_reader (SpProfile       *self,
+                       SpCaptureReader *reader)
+{
+  g_return_if_fail (SP_IS_PROFILE (self));
+  g_return_if_fail (reader != NULL);
+
+  SP_PROFILE_GET_IFACE (self)->set_reader (self, reader);
+}
diff --git a/lib/sp-profile.h b/lib/sp-profile.h
new file mode 100644
index 0000000..60942de
--- /dev/null
+++ b/lib/sp-profile.h
@@ -0,0 +1,59 @@
+/* sp-profile.h
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_PROFILE_H
+#define SP_PROFILE_H
+
+#include <gio/gio.h>
+
+#include "sp-capture-reader.h"
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_PROFILE (sp_profile_get_type ())
+
+G_DECLARE_INTERFACE (SpProfile, sp_profile, SP, PROFILE, GObject)
+
+struct _SpProfileInterface
+{
+  GTypeInterface parent;
+
+  void     (*set_reader)      (SpProfile            *self,
+                               SpCaptureReader      *reader);
+  void     (*generate)        (SpProfile            *self,
+                               GCancellable         *cancellable,
+                               GAsyncReadyCallback   callback,
+                               gpointer              user_data);
+  gboolean (*generate_finish) (SpProfile            *self,
+                               GAsyncResult         *result,
+                               GError              **error);
+};
+
+void     sp_profile_set_reader      (SpProfile            *self,
+                                     SpCaptureReader      *reader);
+void     sp_profile_generate        (SpProfile            *self,
+                                     GCancellable         *cancellable,
+                                     GAsyncReadyCallback   callback,
+                                     gpointer              user_data);
+gboolean sp_profile_generate_finish (SpProfile            *self,
+                                     GAsyncResult         *result,
+                                     GError              **error);
+
+G_END_DECLS
+
+#endif /* SP_PROFILE_H */
diff --git a/lib/sp-profiler-menu-button.c b/lib/sp-profiler-menu-button.c
new file mode 100644
index 0000000..6d78aaa
--- /dev/null
+++ b/lib/sp-profiler-menu-button.c
@@ -0,0 +1,857 @@
+/* sp-profiler-menu-button.c
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#include <glib/gi18n.h>
+#include <string.h>
+
+#include "sp-model-filter.h"
+#include "sp-process-model.h"
+#include "sp-process-model-item.h"
+#include "sp-process-model-row.h"
+#include "sp-profiler-menu-button.h"
+
+typedef struct
+{
+  SpProfiler           *profiler;
+  SpModelFilter        *process_filter;
+
+  /* Gtk template widgets */
+  GtkLabel             *label;
+  GtkPopover           *popover;
+  GtkEntry             *process_filter_entry;
+  GtkListBox           *process_list_box;
+  SpProcessModel       *process_model;
+  GtkBox               *processes_box;
+  GtkEntry             *spawn_entry;
+  GtkStack             *stack;
+  GtkSwitch            *whole_system_switch;
+  GtkTreeView          *env_tree_view;
+  GtkTreeViewColumn    *env_key_column;
+  GtkTreeViewColumn    *env_value_column;
+  GtkCellRenderer      *key_cell;
+  GtkCellRenderer      *value_cell;
+  GtkCheckButton       *inherit_environ;
+
+  /* Property Bindings */
+  GBinding             *inherit_binding;
+  GBinding             *list_sensitive_binding;
+  GBinding             *mutable_binding;
+  GBinding             *whole_system_binding;
+
+  /* Signal handlers */
+  gulong                notify_whole_system_handler;
+
+  /* GSources */
+  guint                 save_env_source;
+} SpProfilerMenuButtonPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (SpProfilerMenuButton, sp_profiler_menu_button, GTK_TYPE_MENU_BUTTON)
+
+enum {
+  PROP_0,
+  PROP_PROFILER,
+  N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+GtkWidget *
+sp_profiler_menu_button_new (void)
+{
+  return g_object_new (SP_TYPE_PROFILER_MENU_BUTTON, NULL);
+}
+
+static void
+sp_profiler_menu_button_update_label (SpProfilerMenuButton *self)
+{
+  SpProfilerMenuButtonPrivate *priv = sp_profiler_menu_button_get_instance_private (self);
+  g_autofree gchar *str = NULL;
+  const gchar *visible_child;
+  const GPid *pids;
+  guint n_pids = 0;
+
+  g_assert (SP_IS_PROFILER_MENU_BUTTON (self));
+
+  if (priv->profiler == NULL)
+    {
+      gtk_label_set_label (priv->label, "");
+      return;
+    }
+
+  visible_child = gtk_stack_get_visible_child_name (priv->stack);
+
+  if (g_strcmp0 (visible_child, "spawn") == 0)
+    {
+      const gchar *text;
+
+      text = gtk_entry_get_text (priv->spawn_entry);
+
+      if (text && *text)
+        gtk_label_set_label (priv->label, text);
+      else if (sp_profiler_get_whole_system (priv->profiler))
+        gtk_label_set_label (priv->label, _("All Processes"));
+      else
+        gtk_label_set_label (priv->label, _("New Process"));
+
+      sp_profiler_set_spawn (priv->profiler, text && *text);
+
+      return;
+    }
+
+  sp_profiler_set_spawn (priv->profiler, FALSE);
+
+  pids = sp_profiler_get_pids (priv->profiler, &n_pids);
+
+  if (n_pids == 0 || sp_profiler_get_whole_system (priv->profiler))
+    {
+      gtk_label_set_label (priv->label, _("All Processes"));
+      return;
+    }
+
+  if (n_pids == 1)
+    {
+      str = g_strdup_printf (_("Process %d"), pids[0]);
+      gtk_label_set_label (priv->label, str);
+      return;
+    }
+
+  str = g_strdup_printf (_("%u Processes"), n_pids);
+  gtk_label_set_label (priv->label, str);
+}
+
+static void
+clear_selected_flags (GtkWidget *widget,
+                      gpointer   user_data)
+{
+  sp_process_model_row_set_selected (SP_PROCESS_MODEL_ROW (widget), FALSE);
+}
+
+static void
+add_binding (GBinding      **binding,
+             gpointer        src,
+             const gchar    *src_property,
+             gpointer        dst,
+             const gchar    *dst_property,
+             GBindingFlags   flags)
+{
+  g_assert (binding != NULL);
+  g_assert (*binding == NULL);
+  g_assert (src != NULL);
+  g_assert (src_property != NULL);
+  g_assert (dst != NULL);
+  g_assert (dst_property != NULL);
+
+  *binding = g_object_bind_property (src, src_property,
+                                     dst, dst_property,
+                                     flags);
+  g_object_add_weak_pointer (G_OBJECT (*binding), (gpointer *)binding);
+}
+
+static void
+clear_binding (GBinding **binding)
+{
+  g_assert (binding != NULL);
+  g_assert (!*binding || G_IS_BINDING (*binding));
+
+  if (*binding != NULL)
+    {
+      g_object_remove_weak_pointer (G_OBJECT (*binding), (gpointer *)binding);
+      g_binding_unbind (*binding);
+      *binding = NULL;
+    }
+}
+
+static void
+sp_profiler_menu_button_connect (SpProfilerMenuButton *self)
+{
+  SpProfilerMenuButtonPrivate *priv = sp_profiler_menu_button_get_instance_private (self);
+
+  g_assert (SP_IS_PROFILER_MENU_BUTTON (self));
+  g_assert (SP_IS_PROFILER (priv->profiler));
+
+  add_binding (&priv->mutable_binding,
+               priv->profiler, "is-mutable",
+               self, "sensitive",
+               G_BINDING_SYNC_CREATE);
+
+  add_binding (&priv->whole_system_binding,
+               priv->profiler, "whole-system",
+               priv->whole_system_switch, "active",
+               G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+
+  add_binding (&priv->list_sensitive_binding,
+               priv->profiler, "whole-system",
+               priv->processes_box, "sensitive",
+               G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
+
+  add_binding (&priv->inherit_binding,
+               priv->inherit_environ, "active",
+               priv->profiler, "spawn-inherit-environ",
+               G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+
+  priv->notify_whole_system_handler =
+    g_signal_connect_object (priv->profiler,
+                             "notify::whole-system",
+                             G_CALLBACK (sp_profiler_menu_button_update_label),
+                             self,
+                             G_CONNECT_SWAPPED);
+
+  sp_profiler_menu_button_update_label (self);
+}
+
+static void
+sp_profiler_menu_button_disconnect (SpProfilerMenuButton *self)
+{
+  SpProfilerMenuButtonPrivate *priv = sp_profiler_menu_button_get_instance_private (self);
+
+  g_assert (SP_IS_PROFILER_MENU_BUTTON (self));
+  g_assert (SP_IS_PROFILER (priv->profiler));
+
+  clear_binding (&priv->mutable_binding);
+  clear_binding (&priv->whole_system_binding);
+  clear_binding (&priv->list_sensitive_binding);
+  clear_binding (&priv->inherit_binding);
+
+  g_signal_handler_disconnect (priv->profiler, priv->notify_whole_system_handler);
+  priv->notify_whole_system_handler = 0;
+
+  gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
+
+  g_clear_object (&priv->profiler);
+
+  gtk_container_foreach (GTK_CONTAINER (priv->process_list_box),
+                         clear_selected_flags,
+                         NULL);
+
+  sp_profiler_menu_button_update_label (self);
+}
+
+/**
+ * sp_profiler_menu_button_get_profiler:
+ * @self: An #SpProfilerMenuButton
+ *
+ * Gets the profiler instance that is being configured.
+ *
+ * Returns: (nullable) (transfer none): An #SpProfiler or %NULL.
+ */
+SpProfiler *
+sp_profiler_menu_button_get_profiler (SpProfilerMenuButton *self)
+{
+  SpProfilerMenuButtonPrivate *priv = sp_profiler_menu_button_get_instance_private (self);
+
+  g_return_val_if_fail (SP_IS_PROFILER_MENU_BUTTON (self), NULL);
+
+  return priv->profiler;
+}
+
+void
+sp_profiler_menu_button_set_profiler (SpProfilerMenuButton *self,
+                                      SpProfiler           *profiler)
+{
+  SpProfilerMenuButtonPrivate *priv = sp_profiler_menu_button_get_instance_private (self);
+
+  g_return_if_fail (SP_IS_PROFILER_MENU_BUTTON (self));
+  g_return_if_fail (!profiler || SP_IS_PROFILER (profiler));
+
+  if (priv->profiler != profiler)
+    {
+      if (priv->profiler != NULL)
+        sp_profiler_menu_button_disconnect (self);
+
+      if (profiler != NULL)
+        {
+          priv->profiler = g_object_ref (profiler);
+          sp_profiler_menu_button_connect (self);
+        }
+
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_PROFILER]);
+    }
+}
+
+static void
+sp_profiler_menu_button_row_activated (SpProfilerMenuButton *self,
+                                       SpProcessModelRow    *row,
+                                       GtkListBox           *list_box)
+{
+  SpProfilerMenuButtonPrivate *priv = sp_profiler_menu_button_get_instance_private (self);
+  gboolean selected;
+
+  g_assert (SP_IS_PROFILER_MENU_BUTTON (self));
+  g_assert (SP_IS_PROCESS_MODEL_ROW (row));
+  g_assert (GTK_IS_LIST_BOX (list_box));
+
+  selected = !sp_process_model_row_get_selected (row);
+  sp_process_model_row_set_selected (row, selected);
+
+  if (priv->profiler != NULL)
+    {
+      SpProcessModelItem *item = sp_process_model_row_get_item (row);
+      GPid pid = sp_process_model_item_get_pid (item);
+
+      if (selected)
+        sp_profiler_add_pid (priv->profiler, pid);
+      else
+        sp_profiler_remove_pid (priv->profiler, pid);
+    }
+
+  sp_profiler_menu_button_update_label (self);
+}
+
+static GtkWidget *
+sp_profiler_menu_button_create_row (gpointer itemptr,
+                                    gpointer user_data)
+{
+  SpProcessModelItem *item = itemptr;
+  SpProfilerMenuButton *self = user_data;
+
+  g_assert (SP_IS_PROCESS_MODEL_ITEM (item));
+  g_assert (SP_IS_PROFILER_MENU_BUTTON (self));
+
+  return g_object_new (SP_TYPE_PROCESS_MODEL_ROW,
+                       "item", item,
+                       "visible", TRUE,
+                       NULL);
+}
+
+static void
+sp_profiler_menu_button_clicked (GtkButton *button)
+{
+  SpProfilerMenuButton *self = (SpProfilerMenuButton *)button;
+  SpProfilerMenuButtonPrivate *priv = sp_profiler_menu_button_get_instance_private (self);
+
+  g_assert (SP_IS_PROFILER_MENU_BUTTON (self));
+
+  sp_process_model_queue_reload (priv->process_model);
+
+  GTK_BUTTON_CLASS (sp_profiler_menu_button_parent_class)->clicked (button);
+}
+
+static void
+sp_profiler_menu_button_filter_changed (SpProfilerMenuButton *self,
+                                        GtkEntry             *entry)
+{
+  SpProfilerMenuButtonPrivate *priv = sp_profiler_menu_button_get_instance_private (self);
+
+  g_assert (SP_IS_PROFILER_MENU_BUTTON (self));
+  g_assert (GTK_IS_ENTRY (entry));
+
+  sp_model_filter_invalidate (priv->process_filter);
+}
+
+static gboolean
+sp_profiler_menu_button_filter_func (GObject  *object,
+                                     gpointer  user_data)
+{
+  SpProfilerMenuButton *self = user_data;
+  SpProfilerMenuButtonPrivate *priv = sp_profiler_menu_button_get_instance_private (self);
+  const gchar *cmdline;
+  const gchar *text;
+  gboolean ret;
+
+  g_assert (SP_IS_PROFILER_MENU_BUTTON (self));
+  g_assert (SP_IS_PROCESS_MODEL_ITEM (object));
+
+  text = gtk_entry_get_text (priv->process_filter_entry);
+  if (!text || !*text)
+    return TRUE;
+
+  cmdline = sp_process_model_item_get_command_line (SP_PROCESS_MODEL_ITEM (object));
+  if (!cmdline)
+    return FALSE;
+
+  ret = (strstr (cmdline, text) != NULL);
+
+  return ret;
+}
+
+static void
+sp_profiler_menu_button_constructed (GObject *object)
+{
+  SpProfilerMenuButton *self = (SpProfilerMenuButton *)object;
+  SpProfilerMenuButtonPrivate *priv = sp_profiler_menu_button_get_instance_private (self);
+
+  g_assert (SP_IS_PROFILER_MENU_BUTTON (self));
+
+  priv->process_filter = sp_model_filter_new (G_LIST_MODEL (priv->process_model));
+  sp_model_filter_set_filter_func (priv->process_filter,
+                                   sp_profiler_menu_button_filter_func,
+                                   self, NULL);
+  gtk_list_box_bind_model (priv->process_list_box,
+                           G_LIST_MODEL (priv->process_filter),
+                           sp_profiler_menu_button_create_row,
+                           self, NULL);
+
+  G_OBJECT_CLASS (sp_profiler_menu_button_parent_class)->constructed (object);
+}
+
+static void
+sp_profiler_menu_button_realize (GtkWidget *widget)
+{
+  SpProfilerMenuButton *self = (SpProfilerMenuButton *)widget;
+  SpProfilerMenuButtonPrivate *priv = sp_profiler_menu_button_get_instance_private (self);
+  g_autoptr(GSettings) settings = NULL;
+  g_auto(GStrv) env = NULL;
+
+  GTK_WIDGET_CLASS (sp_profiler_menu_button_parent_class)->realize (widget);
+
+  settings = g_settings_new ("org.gnome.sysprof2");
+
+  env = g_settings_get_strv (settings, "last-spawn-env");
+
+  g_settings_bind (settings, "last-spawn-argv",
+                   priv->spawn_entry, "text",
+                   G_SETTINGS_BIND_DEFAULT);
+  g_settings_bind (settings, "last-spawn-inherit-env",
+                   priv->inherit_environ, "active",
+                   G_SETTINGS_BIND_DEFAULT);
+
+  if (env)
+    {
+      GtkTreeModel *model;
+      GtkTreeIter iter;
+      guint i;
+
+      model = gtk_tree_view_get_model (priv->env_tree_view);
+      gtk_list_store_clear (GTK_LIST_STORE (model));
+
+      for (i = 0; env [i]; i++)
+        {
+          const gchar *key = env [i];
+          const gchar *value = NULL;
+          gchar *eq = strchr (env[i], '=');
+
+          if (eq)
+            {
+              *eq = '\0';
+              value = eq + 1;
+            }
+
+          gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+          gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+                              0, key,
+                              1, value,
+                              -1);
+        }
+
+      gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+    }
+}
+
+static gboolean
+save_environ_to_gsettings (gpointer data)
+{
+  SpProfilerMenuButton *self = data;
+  SpProfilerMenuButtonPrivate *priv = sp_profiler_menu_button_get_instance_private (self);
+  g_autoptr(GPtrArray) ar = NULL;
+  g_autoptr(GSettings) settings = NULL;
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+
+  g_assert (SP_IS_PROFILER_MENU_BUTTON (self));
+
+  priv->save_env_source = 0;
+
+  settings = g_settings_new ("org.gnome.sysprof2");
+
+  model = gtk_tree_view_get_model (priv->env_tree_view);
+
+  ar = g_ptr_array_new_with_free_func (g_free);
+
+  if (gtk_tree_model_get_iter_first (model, &iter))
+    {
+      do
+        {
+          g_autofree gchar *key = NULL;
+          g_autofree gchar *value = NULL;
+
+          gtk_tree_model_get (model, &iter,
+                              0, &key,
+                              1, &value,
+                              -1);
+
+          if (!key || !*key)
+            continue;
+
+          g_ptr_array_add (ar, g_strdup_printf ("%s=%s", key, value ? value : ""));
+        }
+      while (gtk_tree_model_iter_next (model, &iter));
+    }
+
+  g_ptr_array_add (ar, NULL);
+
+  g_settings_set_strv (settings, "last-spawn-env", (const gchar * const *)ar->pdata);
+
+  return G_SOURCE_REMOVE;
+}
+
+
+static void
+sp_profiler_menu_button_destroy (GtkWidget *widget)
+{
+  SpProfilerMenuButton *self = (SpProfilerMenuButton *)widget;
+  SpProfilerMenuButtonPrivate *priv = sp_profiler_menu_button_get_instance_private (self);
+
+  if (priv->profiler != NULL)
+    {
+      sp_profiler_menu_button_disconnect (self);
+      g_clear_object (&priv->profiler);
+    }
+
+  if (priv->save_env_source)
+    save_environ_to_gsettings (self);
+
+  g_clear_object (&priv->process_filter);
+
+  GTK_WIDGET_CLASS (sp_profiler_menu_button_parent_class)->destroy (widget);
+}
+
+static void
+sp_profiler_menu_button_get_property (GObject    *object,
+                                      guint       prop_id,
+                                      GValue     *value,
+                                      GParamSpec *pspec)
+{
+  SpProfilerMenuButton *self = SP_PROFILER_MENU_BUTTON (object);
+
+  switch (prop_id)
+    {
+    case PROP_PROFILER:
+      g_value_set_object (value, sp_profiler_menu_button_get_profiler (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+sp_profiler_menu_button_set_property (GObject      *object,
+                                      guint         prop_id,
+                                      const GValue *value,
+                                      GParamSpec   *pspec)
+{
+  SpProfilerMenuButton *self = SP_PROFILER_MENU_BUTTON (object);
+
+  switch (prop_id)
+    {
+    case PROP_PROFILER:
+      sp_profiler_menu_button_set_profiler (self, g_value_get_object (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+sp_profiler_menu_button_class_init (SpProfilerMenuButtonClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass);
+
+  object_class->constructed = sp_profiler_menu_button_constructed;
+  object_class->get_property = sp_profiler_menu_button_get_property;
+  object_class->set_property = sp_profiler_menu_button_set_property;
+
+  widget_class->destroy = sp_profiler_menu_button_destroy;
+  widget_class->realize = sp_profiler_menu_button_realize;
+
+  button_class->clicked = sp_profiler_menu_button_clicked;
+
+  properties [PROP_PROFILER] =
+    g_param_spec_object ("profiler",
+                         "Profiler",
+                         "Profiler",
+                         SP_TYPE_PROFILER,
+                         (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/sysprof/ui/sp-profiler-menu-button.ui");
+  gtk_widget_class_bind_template_child_private (widget_class, SpProfilerMenuButton, env_key_column);
+  gtk_widget_class_bind_template_child_private (widget_class, SpProfilerMenuButton, env_tree_view);
+  gtk_widget_class_bind_template_child_private (widget_class, SpProfilerMenuButton, env_value_column);
+  gtk_widget_class_bind_template_child_private (widget_class, SpProfilerMenuButton, inherit_environ);
+  gtk_widget_class_bind_template_child_private (widget_class, SpProfilerMenuButton, key_cell);
+  gtk_widget_class_bind_template_child_private (widget_class, SpProfilerMenuButton, label);
+  gtk_widget_class_bind_template_child_private (widget_class, SpProfilerMenuButton, popover);
+  gtk_widget_class_bind_template_child_private (widget_class, SpProfilerMenuButton, process_filter_entry);
+  gtk_widget_class_bind_template_child_private (widget_class, SpProfilerMenuButton, process_list_box);
+  gtk_widget_class_bind_template_child_private (widget_class, SpProfilerMenuButton, process_model);
+  gtk_widget_class_bind_template_child_private (widget_class, SpProfilerMenuButton, processes_box);
+  gtk_widget_class_bind_template_child_private (widget_class, SpProfilerMenuButton, spawn_entry);
+  gtk_widget_class_bind_template_child_private (widget_class, SpProfilerMenuButton, stack);
+  gtk_widget_class_bind_template_child_private (widget_class, SpProfilerMenuButton, value_cell);
+  gtk_widget_class_bind_template_child_private (widget_class, SpProfilerMenuButton, whole_system_switch);
+}
+
+static void
+sp_profiler_menu_button_env_row_changed (SpProfilerMenuButton *self,
+                                         GtkTreePath          *tree_path,
+                                         GtkTreeIter          *iter,
+                                         gpointer              user_data)
+{
+  SpProfilerMenuButtonPrivate *priv = sp_profiler_menu_button_get_instance_private (self);
+  g_autoptr(GPtrArray) env = NULL;
+  GtkTreeModel *model;
+
+  g_assert (SP_IS_PROFILER_MENU_BUTTON (self));
+  g_assert (tree_path != NULL);
+  g_assert (iter != NULL);
+
+  /* queue saving settings to gsettings */
+  if (priv->save_env_source)
+    g_source_remove (priv->save_env_source);
+  priv->save_env_source = g_timeout_add_seconds (1, save_environ_to_gsettings, self);
+
+  /* sync the environ to the profiler */
+  env = g_ptr_array_new_with_free_func (g_free);
+  model = gtk_tree_view_get_model (priv->env_tree_view);
+  if (gtk_tree_model_get_iter_first (model, iter))
+    {
+      do
+        {
+          g_autofree gchar *key = NULL;
+          g_autofree gchar *value = NULL;
+
+          gtk_tree_model_get (model, iter,
+                              0, &key,
+                              1, &value,
+                              -1);
+
+          if (key && *key)
+            g_ptr_array_add (env, g_strdup_printf ("%s=%s", key, value));
+        }
+      while (gtk_tree_model_iter_next (model, iter));
+    }
+  g_ptr_array_add (env, NULL);
+  sp_profiler_set_spawn_env (priv->profiler, (const gchar * const *)env->pdata);
+}
+
+static void
+on_backspace (SpProfilerMenuButton *self,
+              GtkEntry             *entry)
+{
+  SpProfilerMenuButtonPrivate *priv = sp_profiler_menu_button_get_instance_private (self);
+
+  if (g_object_get_data (G_OBJECT (entry), "CELL_WAS_EMPTY"))
+    {
+      GtkTreeModel *model;
+      GtkTreeSelection *selection;
+      GtkTreeIter iter;
+
+      model = gtk_tree_view_get_model (priv->env_tree_view);
+      selection = gtk_tree_view_get_selection (priv->env_tree_view);
+
+      if (gtk_tree_selection_get_selected (selection, NULL, &iter))
+        {
+          gtk_cell_renderer_stop_editing (priv->key_cell, TRUE);
+          gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
+        }
+    }
+  else
+    g_object_set_data (G_OBJECT (entry), "CELL_WAS_EMPTY",
+                       GINT_TO_POINTER (*gtk_entry_get_text (entry) == '\0'));
+}
+
+static void
+sp_profiler_menu_button_env_key_editing_started (SpProfilerMenuButton *self,
+                                                 GtkCellEditable      *editable,
+                                                 const gchar          *path,
+                                                 GtkCellRenderer      *cell)
+{
+  g_signal_connect_object (editable,
+                           "backspace",
+                           G_CALLBACK (on_backspace),
+                           self,
+                           G_CONNECT_AFTER | G_CONNECT_SWAPPED);
+}
+
+static void
+sp_profiler_menu_button_env_key_edited (SpProfilerMenuButton *self,
+                                        const gchar          *path,
+                                        const gchar          *new_text,
+                                        GtkCellRendererText  *cell)
+{
+  SpProfilerMenuButtonPrivate *priv = sp_profiler_menu_button_get_instance_private (self);
+  GtkTreeModel *model;
+  GtkTreePath *tree_path;
+  GtkTreeIter iter;
+
+  g_assert (SP_IS_PROFILER_MENU_BUTTON (self));
+  g_assert (path != NULL);
+  g_assert (new_text != NULL);
+  g_assert (GTK_IS_CELL_RENDERER_TEXT (cell));
+
+  model = gtk_tree_view_get_model (priv->env_tree_view);
+
+  tree_path = gtk_tree_path_new_from_string (path);
+
+  if (gtk_tree_model_get_iter (model, &iter, tree_path))
+    {
+      gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+                          0, new_text,
+                          -1);
+
+      if (!gtk_tree_model_iter_next (model, &iter))
+        gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+
+      gtk_tree_view_set_cursor_on_cell (priv->env_tree_view,
+                                        tree_path,
+                                        priv->env_value_column,
+                                        priv->value_cell,
+                                        TRUE);
+    }
+
+  gtk_tree_path_free (tree_path);
+}
+
+static void
+sp_profiler_menu_button_env_value_edited (SpProfilerMenuButton *self,
+                                          const gchar          *path,
+                                          const gchar          *new_text,
+                                          GtkCellRendererText  *cell)
+{
+  SpProfilerMenuButtonPrivate *priv = sp_profiler_menu_button_get_instance_private (self);
+
+  GtkTreeModel *model;
+  GtkTreePath *tree_path;
+  GtkTreeIter iter;
+
+  g_assert (SP_IS_PROFILER_MENU_BUTTON (self));
+  g_assert (path != NULL);
+  g_assert (new_text != NULL);
+  g_assert (GTK_IS_CELL_RENDERER_TEXT (cell));
+
+  model = gtk_tree_view_get_model (priv->env_tree_view);
+
+  tree_path = gtk_tree_path_new_from_string (path);
+
+  if (gtk_tree_model_get_iter (model, &iter, tree_path))
+    {
+      gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+                          1, new_text,
+                          -1);
+
+      if (!gtk_tree_model_iter_next (model, &iter))
+        gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+
+      gtk_tree_path_next (tree_path);
+
+      gtk_tree_view_set_cursor_on_cell (priv->env_tree_view,
+                                        tree_path,
+                                        priv->env_key_column,
+                                        priv->key_cell,
+                                        TRUE);
+    }
+
+  gtk_tree_path_free (tree_path);
+}
+
+static void
+sp_profiler_menu_button_validate_spawn (SpProfilerMenuButton *self,
+                                        GtkEntry             *entry)
+{
+  SpProfilerMenuButtonPrivate *priv = sp_profiler_menu_button_get_instance_private (self);
+  g_auto(GStrv) argv = NULL;
+  const gchar *icon_name = NULL;
+  const gchar *text;
+  gint argc;
+
+  g_assert (SP_IS_PROFILER_MENU_BUTTON (self));
+  g_assert (GTK_IS_ENTRY (entry));
+
+  text = gtk_entry_get_text (entry);
+
+  if (!g_shell_parse_argv (text, &argc, &argv, NULL))
+    {
+      icon_name = "dialog-warning-symbolic";
+      sp_profiler_set_spawn_argv (priv->profiler, NULL);
+    }
+  else
+    sp_profiler_set_spawn_argv (priv->profiler, (const gchar * const *)argv);
+
+  gtk_entry_set_icon_from_icon_name (entry,
+                                     GTK_ENTRY_ICON_SECONDARY,
+                                     icon_name);
+}
+
+static void
+sp_profiler_menu_button_init (SpProfilerMenuButton *self)
+{
+  SpProfilerMenuButtonPrivate *priv = sp_profiler_menu_button_get_instance_private (self);
+
+  gtk_widget_init_template (GTK_WIDGET (self));
+
+  g_signal_connect_object (priv->process_filter_entry,
+                           "changed",
+                           G_CALLBACK (sp_profiler_menu_button_filter_changed),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (priv->spawn_entry,
+                           "changed",
+                           G_CALLBACK (sp_profiler_menu_button_update_label),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (priv->spawn_entry,
+                           "changed",
+                           G_CALLBACK (sp_profiler_menu_button_validate_spawn),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (priv->stack,
+                           "notify::visible-child",
+                           G_CALLBACK (sp_profiler_menu_button_update_label),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (priv->process_list_box,
+                           "row-activated",
+                           G_CALLBACK (sp_profiler_menu_button_row_activated),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (priv->key_cell,
+                           "edited",
+                           G_CALLBACK (sp_profiler_menu_button_env_key_edited),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (priv->value_cell,
+                           "edited",
+                           G_CALLBACK (sp_profiler_menu_button_env_value_edited),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (gtk_tree_view_get_model (priv->env_tree_view),
+                           "row-changed",
+                           G_CALLBACK (sp_profiler_menu_button_env_row_changed),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (priv->key_cell,
+                           "editing-started",
+                           G_CALLBACK (sp_profiler_menu_button_env_key_editing_started),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
+}
diff --git a/lib/sp-profiler-menu-button.h b/lib/sp-profiler-menu-button.h
new file mode 100644
index 0000000..fcce9d9
--- /dev/null
+++ b/lib/sp-profiler-menu-button.h
@@ -0,0 +1,44 @@
+/* sp-profiler-menu-button.h
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_PROFILER_MENU_BUTTON_H
+#define SP_PROFILER_MENU_BUTTON_H
+
+#include <gtk/gtk.h>
+
+#include "sp-profiler.h"
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_PROFILER_MENU_BUTTON (sp_profiler_menu_button_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (SpProfilerMenuButton, sp_profiler_menu_button, SP, PROFILER_MENU_BUTTON, 
GtkMenuButton)
+
+struct _SpProfilerMenuButtonClass
+{
+  GtkMenuButtonClass parent_class;
+};
+
+GtkWidget  *sp_profiler_menu_button_new          (void);
+void        sp_profiler_menu_button_set_profiler (SpProfilerMenuButton *self,
+                                                  SpProfiler           *profiler);
+SpProfiler *sp_profiler_menu_button_get_profiler (SpProfilerMenuButton *self);
+
+G_END_DECLS
+
+#endif /* SP_PROFILER_MENU_BUTTON_H */
diff --git a/lib/sp-profiler.c b/lib/sp-profiler.c
new file mode 100644
index 0000000..73b6388
--- /dev/null
+++ b/lib/sp-profiler.c
@@ -0,0 +1,983 @@
+/* sp-profiler.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <errno.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#include "sp-profiler.h"
+
+typedef struct
+{
+  SpCaptureWriter *writer;
+
+  /* All sources added */
+  GPtrArray *sources;
+
+  /* Array of GError failures */
+  GPtrArray *failures;
+
+  /* Sources currently starting */
+  GPtrArray *starting;
+
+  /* Sources currently stopping */
+  GPtrArray *stopping;
+
+  /* Sources that have failed or finished */
+  GPtrArray *finished_or_failed;
+
+  /* Pids to notify children about before prepare */
+  GArray *pids;
+
+  /* Timer for simple time tracking */
+  GTimer *timer;
+  guint timer_notify_source;
+
+  /* Arguments and environment variables for spawning */
+  gchar **spawn_argv;
+  gchar **spawn_env;
+
+  /* State flags */
+  guint is_running : 1;
+  guint is_stopping : 1;
+  guint is_starting : 1;
+
+  /*
+   * If we should spawn argv when starting up. This allows UI to set
+   * spawn argv/env but enable disable with a toggle.
+   */
+  guint spawn : 1;
+
+  /* If we should inherit the environment when spawning */
+  guint spawn_inherit_environ : 1;
+
+  /*
+   * If we should profile the entire system. Setting this results in pids
+   * being ignored. This is primarily useful for UI to toggle on/off the
+   * feature of per-process vs whole-system.
+   */
+  guint whole_system : 1;
+} SpProfilerPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (SpProfiler, sp_profiler, G_TYPE_OBJECT)
+
+enum {
+  PROP_0,
+  PROP_IS_MUTABLE,
+  PROP_IS_RUNNING,
+  PROP_ELAPSED,
+  PROP_SPAWN,
+  PROP_SPAWN_INHERIT_ENVIRON,
+  PROP_WHOLE_SYSTEM,
+  N_PROPS
+};
+
+enum {
+  FAILED,
+  STOPPED,
+  N_SIGNALS
+};
+
+static GParamSpec *properties [N_PROPS];
+static guint signals [N_SIGNALS];
+
+static inline gint
+_g_ptr_array_find (GPtrArray *ar,
+                   gpointer   item)
+{
+  guint i;
+
+  for (i = 0; i < ar->len; i++)
+    {
+      if (item == g_ptr_array_index (ar, i))
+        return i;
+    }
+
+  return -1;
+}
+
+static inline gboolean
+_g_ptr_array_contains (GPtrArray *ar,
+                       gpointer   item)
+{
+  return (-1 != _g_ptr_array_find (ar, item));
+}
+
+gdouble
+sp_profiler_get_elapsed (SpProfiler *self)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+
+  g_return_val_if_fail (SP_IS_PROFILER (self), 0.0);
+
+  return (priv->timer != NULL) ? g_timer_elapsed (priv->timer, NULL) : 0.0;
+}
+
+static void
+sp_profiler_clear_timer (SpProfiler *self)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+
+  g_assert (SP_IS_PROFILER (self));
+
+  g_clear_pointer (&priv->timer, g_timer_destroy);
+
+  if (priv->timer_notify_source != 0)
+    {
+      g_source_remove (priv->timer_notify_source);
+      priv->timer_notify_source = 0;
+    }
+}
+
+static void
+sp_profiler_real_stopped (SpProfiler *self)
+{
+  g_assert (SP_IS_PROFILER (self));
+
+  sp_profiler_clear_timer (self);
+}
+
+static gboolean
+sp_profiler_notify_elapsed_cb (gpointer data)
+{
+  SpProfiler *self = data;
+
+  g_assert (SP_IS_PROFILER (self));
+
+  g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ELAPSED]);
+
+  return G_SOURCE_CONTINUE;
+}
+
+static void
+sp_profiler_dispose (GObject *object)
+{
+  SpProfiler *self = (SpProfiler *)object;
+
+  if (sp_profiler_get_is_running (self))
+    {
+      sp_profiler_stop (self);
+      return;
+    }
+
+  sp_profiler_clear_timer (self);
+
+  G_OBJECT_CLASS (sp_profiler_parent_class)->dispose (object);
+}
+
+static void
+sp_profiler_finalize (GObject *object)
+{
+  SpProfiler *self = (SpProfiler *)object;
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+
+  g_clear_pointer (&priv->writer, sp_capture_writer_unref);
+  g_clear_pointer (&priv->sources, g_ptr_array_unref);
+  g_clear_pointer (&priv->starting, g_ptr_array_unref);
+  g_clear_pointer (&priv->stopping, g_ptr_array_unref);
+  g_clear_pointer (&priv->finished_or_failed, g_ptr_array_unref);
+  g_clear_pointer (&priv->pids, g_array_unref);
+
+  G_OBJECT_CLASS (sp_profiler_parent_class)->finalize (object);
+}
+
+static void
+sp_profiler_get_property (GObject    *object,
+                          guint       prop_id,
+                          GValue     *value,
+                          GParamSpec *pspec)
+{
+  SpProfiler *self = SP_PROFILER (object);
+
+  switch (prop_id)
+    {
+    case PROP_IS_MUTABLE:
+      g_value_set_boolean (value, sp_profiler_get_is_mutable (self));
+      break;
+
+    case PROP_IS_RUNNING:
+      g_value_set_boolean (value, sp_profiler_get_is_running (self));
+      break;
+
+    case PROP_WHOLE_SYSTEM:
+      g_value_set_boolean (value, sp_profiler_get_whole_system (self));
+      break;
+
+    case PROP_SPAWN:
+      g_value_set_boolean (value, sp_profiler_get_spawn (self));
+      break;
+
+    case PROP_SPAWN_INHERIT_ENVIRON:
+      g_value_set_boolean (value, sp_profiler_get_spawn_inherit_environ (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+sp_profiler_set_property (GObject      *object,
+                          guint         prop_id,
+                          const GValue *value,
+                          GParamSpec   *pspec)
+{
+  SpProfiler *self = SP_PROFILER (object);
+
+  switch (prop_id)
+    {
+    case PROP_WHOLE_SYSTEM:
+      sp_profiler_set_whole_system (self, g_value_get_boolean (value));
+      break;
+
+    case PROP_SPAWN:
+      sp_profiler_set_spawn (self, g_value_get_boolean (value));
+      break;
+
+    case PROP_SPAWN_INHERIT_ENVIRON:
+      sp_profiler_set_spawn_inherit_environ (self, g_value_get_boolean (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+sp_profiler_class_init (SpProfilerClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = sp_profiler_dispose;
+  object_class->finalize = sp_profiler_finalize;
+  object_class->get_property = sp_profiler_get_property;
+  object_class->set_property = sp_profiler_set_property;
+
+  klass->stopped = sp_profiler_real_stopped;
+
+  /**
+   * SpProfiler:elapsed:
+   *
+   * This property is updated on a second basis while recording so that
+   * UIs can keep a timer of the elapsed time while recording.
+   *
+   * It contains a double with seconds as whole integers and fractions
+   * of second after the decimal point.
+   */
+  properties [PROP_ELAPSED] =
+    g_param_spec_double ("elapsed",
+                         "Elapsed Time",
+                         "The amount of time elapsed while recording",
+                         0.0,
+                         G_MAXDOUBLE,
+                         0.0,
+                         (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * SpProfiler:is-running:
+   *
+   * If the profiler has been started. Note that after being started, this
+   * property won't change back to %FALSE until all sources have stopped
+   * and notified of asynchronous completion.
+   */
+  properties [PROP_IS_RUNNING] =
+    g_param_spec_boolean ("is-running",
+                          "Is Running",
+                          "If the profiler has been started",
+                          FALSE,
+                          (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * SpProfiler:is-mutable:
+   *
+   * This property is useful from a UI standpoint to desensitize
+   * configuration widgets once the profiler can no longer be modified.
+   */
+  properties [PROP_IS_MUTABLE] =
+    g_param_spec_boolean ("is-mutable",
+                          "Is Mutable",
+                          "If the profiler can be modified",
+                          FALSE,
+                          (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+  properties [PROP_SPAWN] =
+    g_param_spec_boolean ("spawn",
+                          "Spawn",
+                          "If a child should process should be spawned",
+                          FALSE,
+                          (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+  properties [PROP_SPAWN_INHERIT_ENVIRON] =
+    g_param_spec_boolean ("spawn-inherit-environ",
+                          "Spawn Inherit Environ",
+                          "If a child should inherit the current environment",
+                          FALSE,
+                          (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * SpProfiler:whole-system:
+   *
+   * This property denotes if the whole system should be profiled instead of
+   * a single process. This is useful for UI to toggle between process
+   * selection and all processes.
+   *
+   * Setting this to %TRUE will result in the pids added to be ignored
+   * during startup.
+   */
+  properties [PROP_WHOLE_SYSTEM] =
+    g_param_spec_boolean ("whole-system",
+                          "Whole System",
+                          "If the whole system should be profiled",
+                          TRUE,
+                          (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+
+  signals [STOPPED] = g_signal_new ("stopped",
+                                    G_TYPE_FROM_CLASS (klass),
+                                    G_SIGNAL_RUN_LAST,
+                                    G_STRUCT_OFFSET (SpProfilerClass, stopped),
+                                    NULL, NULL, NULL, G_TYPE_NONE, 0);
+
+  signals [FAILED] = g_signal_new ("failed",
+                                    G_TYPE_FROM_CLASS (klass),
+                                    G_SIGNAL_RUN_LAST,
+                                    G_STRUCT_OFFSET (SpProfilerClass, failed),
+                                    NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_ERROR);
+
+}
+
+static void
+sp_profiler_init (SpProfiler *self)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+
+  priv->whole_system = TRUE;
+
+  priv->failures = g_ptr_array_new_with_free_func ((GDestroyNotify)g_error_free);
+  priv->sources = g_ptr_array_new_with_free_func (g_object_unref);
+  priv->starting = g_ptr_array_new_with_free_func (g_object_unref);
+  priv->stopping = g_ptr_array_new_with_free_func (g_object_unref);
+  priv->finished_or_failed = g_ptr_array_new_with_free_func (g_object_unref);
+  priv->pids = g_array_new (FALSE, FALSE, sizeof (GPid));
+}
+
+SpProfiler *
+sp_profiler_new (void)
+{
+  return g_object_new (SP_TYPE_PROFILER, NULL);
+}
+
+static void
+sp_profiler_finish_startup (SpProfiler *self)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+  guint i;
+
+  g_assert (SP_IS_PROFILER (self));
+  g_assert (priv->is_starting == TRUE);
+  g_assert (priv->starting->len == 0);
+
+  sp_profiler_clear_timer (self);
+
+  priv->timer = g_timer_new ();
+
+  /*
+   * Add a source to update our watchers of elapsed time.
+   * We use 1000 instead of add_seconds(1) so that we are
+   * not subject to as much drift.
+   */
+  priv->timer_notify_source =
+    g_timeout_add (1000,
+                   sp_profiler_notify_elapsed_cb,
+                   self);
+
+  for (i = 0; i < priv->sources->len; i++)
+    {
+      SpSource *source = g_ptr_array_index (priv->sources, i);
+
+      sp_source_start (source);
+    }
+
+  priv->is_starting = FALSE;
+
+  /*
+   * If any of the sources failed during startup, we will have a non-empty
+   * failures list.
+   */
+  if (priv->failures->len > 0)
+    {
+      const GError *error = g_ptr_array_index (priv->failures, 0);
+
+      g_object_ref (self);
+      g_signal_emit (self, signals [FAILED], 0, error);
+      sp_profiler_stop (self);
+      g_object_unref (self);
+      return;
+    }
+
+  priv->is_running = TRUE;
+
+  g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_IS_RUNNING]);
+  g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_IS_MUTABLE]);
+
+  /*
+   * If all the sources are transient (in that they just generate information
+   * and then exit), we could be finished as soon as we complete startup.
+   *
+   * If we detect this, we stop immediately.
+   */
+  if (priv->finished_or_failed->len == priv->sources->len)
+    sp_profiler_stop (self);
+}
+
+void
+sp_profiler_start (SpProfiler *self)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+  guint i;
+
+  g_return_if_fail (SP_IS_PROFILER (self));
+  g_return_if_fail (priv->is_running == FALSE);
+  g_return_if_fail (priv->is_stopping == FALSE);
+  g_return_if_fail (priv->is_starting == FALSE);
+
+  if (priv->writer == NULL)
+    {
+      SpCaptureWriter *writer;
+      int fd;
+
+      if ((-1 == (fd = syscall (__NR_memfd_create, "[sysprof]", 0))) ||
+          (NULL == (writer = sp_capture_writer_new_from_fd (fd, 0))))
+        {
+          const GError error = {
+            G_FILE_ERROR,
+            g_file_error_from_errno (errno),
+            (gchar *)g_strerror (errno)
+          };
+
+          if (fd != -1)
+            close (fd);
+
+          g_signal_emit (self, signals [FAILED], 0, &error);
+
+          return;
+        }
+
+      sp_profiler_set_writer (self, writer);
+      g_clear_pointer (&writer, sp_capture_writer_unref);
+    }
+
+  priv->is_running = TRUE;
+  priv->is_starting = TRUE;
+
+  if (priv->failures->len > 0)
+    g_ptr_array_remove_range (priv->failures, 0, priv->failures->len);
+
+  if (priv->spawn && priv->spawn_argv && priv->spawn_argv[0])
+    {
+      g_autoptr(GPtrArray) ar = g_ptr_array_new_with_free_func (g_free);
+      GPid pid;
+      GError *error = NULL;
+
+      if (priv->spawn_inherit_environ)
+        {
+          gchar **environ = g_get_environ ();
+
+          for (i = 0; environ[i]; i++)
+            g_ptr_array_add (ar, environ[i]);
+          g_free (environ);
+        }
+
+      if (priv->spawn_env)
+        {
+          for (i = 0; priv->spawn_env[i]; i++)
+            g_ptr_array_add (ar, g_strdup (priv->spawn_env[i]));
+        }
+
+      g_ptr_array_add (ar, NULL);
+
+      if (!g_spawn_async (g_get_home_dir (),
+                          priv->spawn_argv,
+                          (gchar **)ar->pdata,
+                          (G_SPAWN_SEARCH_PATH |
+                           G_SPAWN_STDOUT_TO_DEV_NULL |
+                           G_SPAWN_STDOUT_TO_DEV_NULL),
+                          NULL,
+                          NULL,
+                          &pid,
+                          &error))
+        g_ptr_array_add (priv->failures, error);
+      else
+        g_array_append_val (priv->pids, pid);
+    }
+
+  for (i = 0; i < priv->sources->len; i++)
+    {
+      SpSource *source = g_ptr_array_index (priv->sources, i);
+      guint j;
+
+      if (priv->whole_system == FALSE)
+        {
+          for (j = 0; j < priv->pids->len; j++)
+            {
+              GPid pid = g_array_index (priv->pids, GPid, j);
+
+              sp_source_add_pid (source, pid);
+            }
+        }
+
+      sp_source_set_writer (source, priv->writer);
+      sp_source_prepare (source);
+    }
+
+  for (i = 0; i < priv->sources->len; i++)
+    {
+      SpSource *source = g_ptr_array_index (priv->sources, i);
+
+      if (!sp_source_get_is_ready (source))
+        g_ptr_array_add (priv->starting, g_object_ref (source));
+    }
+
+  if (priv->starting->len == 0)
+    sp_profiler_finish_startup (self);
+}
+
+static void
+sp_profiler_finish_stopping (SpProfiler *self)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+
+  g_assert (SP_IS_PROFILER (self));
+  g_assert (priv->is_starting == FALSE);
+  g_assert (priv->is_stopping == TRUE);
+  g_assert (priv->stopping->len == 0);
+
+  if (priv->failures->len > 0)
+    {
+      const GError *error = g_ptr_array_index (priv->failures, 0);
+
+      g_signal_emit (self, signals [FAILED], 0, error);
+    }
+
+  priv->is_running = FALSE;
+  priv->is_stopping = FALSE;
+
+  g_signal_emit (self, signals [STOPPED], 0);
+
+  g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_IS_RUNNING]);
+  g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_IS_MUTABLE]);
+}
+
+void
+sp_profiler_stop (SpProfiler *self)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+  guint i;
+
+  g_return_if_fail (SP_IS_PROFILER (self));
+
+  if (priv->is_stopping || (!priv->is_starting && !priv->is_running))
+    return;
+
+  priv->is_stopping = TRUE;
+
+  /*
+   * First we add everything to the stopping list, so that we can
+   * be notified of when they have completed. If everything stopped
+   * synchronously, the stopping list will be empty after calling
+   * sp_source_stop() for every source. Otherwise, we need to delay
+   * stopping for a little bit.
+   */
+
+  for (i = 0; i < priv->sources->len; i++)
+    {
+      SpSource *source = g_ptr_array_index (priv->sources, i);
+
+      if (!_g_ptr_array_contains (priv->finished_or_failed, source))
+        g_ptr_array_add (priv->stopping, g_object_ref (source));
+    }
+
+  for (i = 0; i < priv->sources->len; i++)
+    {
+      SpSource *source = g_ptr_array_index (priv->sources, i);
+
+      sp_source_stop (source);
+    }
+
+  if (priv->is_stopping && priv->stopping->len == 0)
+    sp_profiler_finish_stopping (self);
+}
+
+gboolean
+sp_profiler_get_is_running (SpProfiler *self)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+
+  g_return_val_if_fail (SP_IS_PROFILER (self), FALSE);
+
+  return priv->is_running;
+}
+
+void
+sp_profiler_set_writer (SpProfiler      *self,
+                        SpCaptureWriter *writer)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+
+  g_return_if_fail (SP_IS_PROFILER (self));
+  g_return_if_fail (priv->is_running == FALSE);
+  g_return_if_fail (priv->is_stopping == FALSE);
+  g_return_if_fail (writer != NULL);
+
+  if (priv->writer != writer)
+    {
+      g_clear_pointer (&priv->writer, sp_capture_writer_unref);
+
+      if (writer != NULL)
+        priv->writer = sp_capture_writer_ref (writer);
+    }
+}
+
+static void
+sp_profiler_track_completed (SpProfiler *self,
+                             SpSource   *source)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+  gint i;
+
+  g_assert (SP_IS_PROFILER (self));
+  g_assert (SP_IS_SOURCE (source));
+
+  if (!_g_ptr_array_contains (priv->finished_or_failed, source))
+    g_ptr_array_add (priv->finished_or_failed, g_object_ref (source));
+
+  if (priv->is_starting)
+    {
+      i = _g_ptr_array_find (priv->starting, source);
+
+      if (i >= 0)
+        {
+          g_ptr_array_remove_index (priv->starting, i);
+          if (priv->starting->len == 0)
+            sp_profiler_finish_startup (self);
+        }
+    }
+
+  if (priv->is_stopping)
+    {
+      i = _g_ptr_array_find (priv->stopping, source);
+
+      if (i >= 0)
+        {
+          g_ptr_array_remove_index_fast (priv->stopping, i);
+
+          if ((priv->is_stopping == TRUE) && (priv->stopping->len == 0))
+            sp_profiler_finish_stopping (self);
+        }
+    }
+
+  if (!priv->is_starting)
+    {
+      if (priv->finished_or_failed->len == priv->sources->len)
+        sp_profiler_stop (self);
+    }
+}
+
+static void
+sp_profiler_source_finished (SpProfiler *self,
+                             SpSource   *source)
+{
+  g_assert (SP_IS_PROFILER (self));
+  g_assert (SP_IS_SOURCE (source));
+
+  sp_profiler_track_completed (self, source);
+}
+
+static void
+sp_profiler_source_ready (SpProfiler *self,
+                          SpSource   *source)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+  guint i;
+
+  g_assert (SP_IS_PROFILER (self));
+  g_assert (SP_IS_SOURCE (source));
+
+  for (i = 0; i < priv->starting->len; i++)
+    {
+      SpSource *ele = g_ptr_array_index (priv->starting, i);
+
+      if (ele == source)
+        {
+          g_ptr_array_remove_index_fast (priv->starting, i);
+
+          if ((priv->is_starting == TRUE) && (priv->starting->len == 0))
+            sp_profiler_finish_startup (self);
+
+          break;
+        }
+    }
+}
+
+static void
+sp_profiler_source_failed (SpProfiler   *self,
+                           const GError *reason,
+                           SpSource     *source)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+
+  g_assert (SP_IS_PROFILER (self));
+  g_assert (reason != NULL);
+  g_assert (SP_IS_SOURCE (source));
+
+  sp_profiler_track_completed (self, source);
+
+  /* Failure emitted out of band */
+  if (!priv->is_starting && !priv->is_stopping && !priv->is_running)
+    return;
+
+  g_ptr_array_add (priv->failures, g_error_copy (reason));
+
+  /* Ignore during start/stop, we handle this in other places */
+  if (priv->is_starting || priv->is_stopping)
+    return;
+
+  if (priv->is_running)
+    sp_profiler_stop (self);
+}
+
+void
+sp_profiler_add_source (SpProfiler *self,
+                        SpSource   *source)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+
+  g_return_if_fail (SP_IS_PROFILER (self));
+  g_return_if_fail (SP_IS_SOURCE (source));
+  g_return_if_fail (priv->is_running == FALSE);
+  g_return_if_fail (priv->is_starting == FALSE);
+  g_return_if_fail (priv->is_stopping == FALSE);
+
+  g_signal_connect_object (source,
+                           "failed",
+                           G_CALLBACK (sp_profiler_source_failed),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (source,
+                           "finished",
+                           G_CALLBACK (sp_profiler_source_finished),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (source,
+                           "ready",
+                           G_CALLBACK (sp_profiler_source_ready),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+
+  g_ptr_array_add (priv->sources, g_object_ref (source));
+}
+
+void
+sp_profiler_add_pid (SpProfiler *self,
+                     GPid        pid)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+
+  g_return_if_fail (SP_IS_PROFILER (self));
+  g_return_if_fail (pid > -1);
+  g_return_if_fail (priv->is_starting == FALSE);
+  g_return_if_fail (priv->is_stopping == FALSE);
+  g_return_if_fail (priv->is_running == FALSE);
+
+  g_array_append_val (priv->pids, pid);
+}
+
+void
+sp_profiler_remove_pid (SpProfiler *self,
+                        GPid        pid)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+  guint i;
+
+  g_return_if_fail (SP_IS_PROFILER (self));
+  g_return_if_fail (pid > -1);
+  g_return_if_fail (priv->is_starting == FALSE);
+  g_return_if_fail (priv->is_stopping == FALSE);
+  g_return_if_fail (priv->is_running == FALSE);
+
+  for (i = 0; i < priv->pids->len; i++)
+    {
+      GPid ele = g_array_index (priv->pids, GPid, i);
+
+      if (ele == pid)
+        {
+          g_array_remove_index_fast (priv->pids, i);
+          break;
+        }
+    }
+}
+
+gboolean
+sp_profiler_get_is_mutable (SpProfiler *self)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+
+  g_return_val_if_fail (SP_IS_PROFILER (self), FALSE);
+
+  return !(priv->is_starting || priv->is_stopping || priv->is_running);
+}
+
+gboolean
+sp_profiler_get_whole_system (SpProfiler *self)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+
+  g_return_val_if_fail (SP_IS_PROFILER (self), FALSE);
+
+  return priv->whole_system;
+}
+
+void
+sp_profiler_set_whole_system (SpProfiler *self,
+                              gboolean    whole_system)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+
+  g_return_if_fail (SP_IS_PROFILER (self));
+
+  whole_system = !!whole_system;
+
+  if (whole_system != priv->whole_system)
+    {
+      priv->whole_system = whole_system;
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_WHOLE_SYSTEM]);
+    }
+}
+
+const GPid *
+sp_profiler_get_pids (SpProfiler *self,
+                      guint      *n_pids)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+
+  g_return_val_if_fail (SP_IS_PROFILER (self), NULL);
+  g_return_val_if_fail (n_pids != NULL, NULL);
+
+  *n_pids = priv->pids->len;
+
+  return (GPid *)(gpointer)priv->pids->data;
+}
+
+/**
+ * sp_profiler_get_writer:
+ *
+ * Returns: (nullable) (transfer none): An #SpCaptureWriter or %NULL.
+ */
+SpCaptureWriter *
+sp_profiler_get_writer (SpProfiler *self)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+
+  g_return_val_if_fail (SP_IS_PROFILER (self), NULL);
+
+  return priv->writer;
+}
+
+gboolean
+sp_profiler_get_spawn (SpProfiler *self)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+
+  g_return_val_if_fail (SP_IS_PROFILER (self), FALSE);
+
+  return priv->spawn;
+}
+
+void
+sp_profiler_set_spawn (SpProfiler *self,
+                       gboolean    spawn)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+
+  g_return_if_fail (SP_IS_PROFILER (self));
+
+  spawn = !!spawn;
+
+  if (priv->spawn != spawn)
+    {
+      priv->spawn = spawn;
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SPAWN]);
+    }
+}
+
+gboolean
+sp_profiler_get_spawn_inherit_environ (SpProfiler *self)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+
+  g_return_val_if_fail (SP_IS_PROFILER (self), FALSE);
+
+  return priv->spawn_inherit_environ;
+}
+
+void
+sp_profiler_set_spawn_inherit_environ (SpProfiler *self,
+                                       gboolean    spawn_inherit_environ)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+
+  g_return_if_fail (SP_IS_PROFILER (self));
+
+  spawn_inherit_environ = !!spawn_inherit_environ;
+
+  if (priv->spawn_inherit_environ != spawn_inherit_environ)
+    {
+      priv->spawn_inherit_environ = spawn_inherit_environ;
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SPAWN_INHERIT_ENVIRON]);
+    }
+}
+
+void
+sp_profiler_set_spawn_argv (SpProfiler          *self,
+                            const gchar * const *spawn_argv)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+
+  g_return_if_fail (SP_IS_PROFILER (self));
+
+  g_strfreev (priv->spawn_argv);
+  priv->spawn_argv = g_strdupv ((gchar **)spawn_argv);
+}
+
+void
+sp_profiler_set_spawn_env (SpProfiler          *self,
+                           const gchar * const *spawn_env)
+{
+  SpProfilerPrivate *priv = sp_profiler_get_instance_private (self);
+
+  g_return_if_fail (SP_IS_PROFILER (self));
+
+  g_strfreev (priv->spawn_env);
+  priv->spawn_env = g_strdupv ((gchar **)spawn_env);
+}
diff --git a/lib/sp-profiler.h b/lib/sp-profiler.h
new file mode 100644
index 0000000..34663ea
--- /dev/null
+++ b/lib/sp-profiler.h
@@ -0,0 +1,92 @@
+/* sp-profiler.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_PROFILER_H
+#define SP_PROFILER_H
+
+#include "sp-capture-writer.h"
+#include "sp-source.h"
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_PROFILER (sp_profiler_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (SpProfiler, sp_profiler, SP, PROFILER, GObject)
+
+struct _SpProfilerClass
+{
+  GObjectClass parent_class;
+
+  /**
+   * SpProfiler::failed:
+   * @self: A #SpProfiler
+   * @reason: A #GError representing the reason for the failure
+   *
+   * This signal is emitted if the profiler failed. Note that
+   * #SpProfiler::stopped will also be emitted, but does not allow for
+   * receiving the error condition.
+   */
+  void (*failed) (SpProfiler   *self,
+                  const GError *error);
+
+  /**
+   * SpProfiler::stopped:
+   * @self: A #SpProfiler
+   *
+   * This signal is emitted when a profiler is stopped. It will always be
+   * emitted after a sp_profiler_start() has been called, either after
+   * completion of sp_profiler_stop() or after a failure or after asynchronous
+   * completion of stopping.
+   */
+  void (*stopped) (SpProfiler *self);
+};
+
+SpProfiler      *sp_profiler_new                       (void);
+gdouble          sp_profiler_get_elapsed               (SpProfiler          *self);
+void             sp_profiler_add_source                (SpProfiler          *self,
+                                                        SpSource            *source);
+void             sp_profiler_set_writer                (SpProfiler          *self,
+                                                        SpCaptureWriter     *writer);
+SpCaptureWriter *sp_profiler_get_writer                (SpProfiler          *self);
+gboolean         sp_profiler_get_is_running            (SpProfiler          *self);
+void             sp_profiler_start                     (SpProfiler          *self);
+void             sp_profiler_stop                      (SpProfiler          *self);
+void             sp_profiler_add_pid                   (SpProfiler          *self,
+                                                        GPid                 pid);
+void             sp_profiler_remove_pid                (SpProfiler          *self,
+                                                        GPid                 pid);
+gboolean         sp_profiler_get_is_mutable            (SpProfiler          *self);
+gboolean         sp_profiler_get_whole_system          (SpProfiler          *self);
+void             sp_profiler_set_whole_system          (SpProfiler          *self,
+                                                        gboolean             whole_system);
+const GPid      *sp_profiler_get_pids                  (SpProfiler          *self,
+                                                        guint               *n_pids);
+gboolean         sp_profiler_get_spawn                 (SpProfiler          *self);
+void             sp_profiler_set_spawn                 (SpProfiler          *self,
+                                                        gboolean             spawn);
+void             sp_profiler_set_spawn_argv            (SpProfiler          *self,
+                                                        const gchar * const *spawn_argv);
+void             sp_profiler_set_spawn_env             (SpProfiler          *self,
+                                                        const gchar * const *spawn_env);
+gboolean         sp_profiler_get_spawn_inherit_environ (SpProfiler          *self);
+void             sp_profiler_set_spawn_inherit_environ (SpProfiler          *self,
+                                                        gboolean             spawn_inherit_environ);
+
+G_END_DECLS
+
+#endif /* SP_PROFILER_H */
diff --git a/lib/sp-recording-state-view.c b/lib/sp-recording-state-view.c
new file mode 100644
index 0000000..6762b5e
--- /dev/null
+++ b/lib/sp-recording-state-view.c
@@ -0,0 +1,193 @@
+/* sp-recording-state-view.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#include "sp-recording-state-view.h"
+
+typedef struct
+{
+  SpProfiler *profiler;
+  gulong      notify_elapsed_handler;
+  GtkLabel   *elapsed;
+} SpRecordingStateViewPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (SpRecordingStateView, sp_recording_state_view, GTK_TYPE_BIN)
+
+enum {
+  PROP_0,
+  PROP_PROFILER,
+  N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+GtkWidget *
+sp_recording_state_view_new (void)
+{
+  return g_object_new (SP_TYPE_RECORDING_STATE_VIEW, NULL);
+}
+
+static void
+sp_recording_state_view_notify_elapsed (SpRecordingStateView *self,
+                                        GParamSpec           *pspec,
+                                        SpProfiler           *profiler)
+{
+  SpRecordingStateViewPrivate *priv = sp_recording_state_view_get_instance_private (self);
+  g_autofree gchar *str = NULL;
+  gint64 elapsed;
+  guint hours;
+  guint minutes;
+  guint seconds;
+
+  g_assert (SP_IS_RECORDING_STATE_VIEW (self));
+  g_assert (SP_IS_PROFILER (profiler));
+
+  elapsed = (gint64)sp_profiler_get_elapsed (profiler);
+
+  hours = elapsed / (60 * 60);
+  if (hours > 0)
+    minutes = (elapsed % (hours * 60 * 60)) / 60;
+  else
+    minutes = elapsed / 60;
+  seconds = elapsed % 60;
+
+  if (hours == 0)
+    str = g_strdup_printf ("%02u:%02u", minutes, seconds);
+  else
+    str = g_strdup_printf ("%02u:%02u:%02u", hours, minutes, seconds);
+
+  gtk_label_set_label (priv->elapsed, str);
+}
+
+static void
+sp_recording_state_view_destroy (GtkWidget *widget)
+{
+  SpRecordingStateView *self = (SpRecordingStateView *)widget;
+  SpRecordingStateViewPrivate *priv = sp_recording_state_view_get_instance_private (self);
+
+  if (priv->profiler != NULL)
+    {
+      g_signal_handler_disconnect (priv->profiler, priv->notify_elapsed_handler);
+      g_clear_object (&priv->profiler);
+    }
+
+  GTK_WIDGET_CLASS (sp_recording_state_view_parent_class)->destroy (widget);
+}
+
+static void
+sp_recording_state_view_get_property (GObject    *object,
+                                      guint       prop_id,
+                                      GValue     *value,
+                                      GParamSpec *pspec)
+{
+  SpRecordingStateView *self = SP_RECORDING_STATE_VIEW (object);
+  SpRecordingStateViewPrivate *priv = sp_recording_state_view_get_instance_private (self);
+
+  switch (prop_id)
+    {
+    case PROP_PROFILER:
+      g_value_set_object (value, priv->profiler);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+sp_recording_state_view_set_property (GObject      *object,
+                                      guint         prop_id,
+                                      const GValue *value,
+                                      GParamSpec   *pspec)
+{
+  SpRecordingStateView *self = SP_RECORDING_STATE_VIEW (object);
+
+  switch (prop_id)
+    {
+    case PROP_PROFILER:
+      sp_recording_state_view_set_profiler (self, g_value_get_object (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+sp_recording_state_view_class_init (SpRecordingStateViewClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->get_property = sp_recording_state_view_get_property;
+  object_class->set_property = sp_recording_state_view_set_property;
+
+  widget_class->destroy = sp_recording_state_view_destroy;
+
+  properties [PROP_PROFILER] =
+    g_param_spec_object ("profiler",
+                         "Profiler",
+                         "Profiler",
+                         SP_TYPE_PROFILER,
+                         (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+
+  gtk_widget_class_set_template_from_resource (widget_class,
+                                               "/org/gnome/sysprof/ui/sp-recording-state-view.ui");
+  gtk_widget_class_bind_template_child_private (widget_class, SpRecordingStateView, elapsed);
+}
+
+static void
+sp_recording_state_view_init (SpRecordingStateView *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+sp_recording_state_view_set_profiler (SpRecordingStateView *self,
+                                      SpProfiler           *profiler)
+{
+  SpRecordingStateViewPrivate *priv = sp_recording_state_view_get_instance_private (self);
+
+  g_assert (SP_IS_RECORDING_STATE_VIEW (self));
+  g_assert (!profiler || SP_IS_PROFILER (profiler));
+
+  gtk_label_set_label (priv->elapsed, "00:00");
+
+  if (profiler != priv->profiler)
+    {
+      if (priv->profiler != NULL)
+        {
+          g_signal_handler_disconnect (priv->profiler, priv->notify_elapsed_handler);
+          g_clear_object (&priv->profiler);
+        }
+
+      gtk_label_set_label (priv->elapsed, "00:00");
+
+      if (profiler != NULL)
+        {
+          priv->profiler = g_object_ref (profiler);
+          priv->notify_elapsed_handler =
+            g_signal_connect_object (profiler,
+                                     "notify::elapsed",
+                                     G_CALLBACK (sp_recording_state_view_notify_elapsed),
+                                     self,
+                                     G_CONNECT_SWAPPED);
+        }
+    }
+}
diff --git a/lib/sp-recording-state-view.h b/lib/sp-recording-state-view.h
new file mode 100644
index 0000000..37b3b82
--- /dev/null
+++ b/lib/sp-recording-state-view.h
@@ -0,0 +1,43 @@
+/* sp-recording-state-view.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_RECORDING_STATE_VIEW_H
+#define SP_RECORDING_STATE_VIEW_H
+
+#include <gtk/gtk.h>
+
+#include "sp-profiler.h"
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_RECORDING_STATE_VIEW (sp_recording_state_view_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (SpRecordingStateView, sp_recording_state_view, SP, RECORDING_STATE_VIEW, GtkBin)
+
+struct _SpRecordingStateViewClass
+{
+  GtkBinClass parent;
+};
+
+GtkWidget *sp_recording_state_view_new          (void);
+void       sp_recording_state_view_set_profiler (SpRecordingStateView *self,
+                                                 SpProfiler           *profiler);
+
+G_END_DECLS
+
+#endif /* SP_RECORDING_STATE_VIEW_H */
diff --git a/lib/sp-scrolled-window.c b/lib/sp-scrolled-window.c
new file mode 100644
index 0000000..82c8ce2
--- /dev/null
+++ b/lib/sp-scrolled-window.c
@@ -0,0 +1,280 @@
+/* sp-scrolled-window.c
+ *
+ * Copyright (C) 2014 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#include <glib/gi18n.h>
+
+#include "sp-scrolled-window.h"
+
+typedef struct
+{
+  gint max_content_height;
+  gint max_content_width;
+} SpScrolledWindowPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (SpScrolledWindow, sp_scrolled_window, GTK_TYPE_SCROLLED_WINDOW)
+
+enum {
+  PROP_0,
+  PROP_MAX_CONTENT_HEIGHT,
+  PROP_MAX_CONTENT_WIDTH,
+  LAST_PROP
+};
+
+static GParamSpec *properties [LAST_PROP];
+
+GtkWidget *
+sp_scrolled_window_new (void)
+{
+  return g_object_new (SP_TYPE_SCROLLED_WINDOW, NULL);
+}
+
+gint
+sp_scrolled_window_get_max_content_height (SpScrolledWindow *self)
+{
+  SpScrolledWindowPrivate *priv = sp_scrolled_window_get_instance_private (self);
+
+  g_return_val_if_fail (SP_IS_SCROLLED_WINDOW (self), -1);
+
+  return priv->max_content_height;
+}
+
+/**
+ * sp_scrolled_window_set_max_content_height:
+ * @max_content_height: the max allowed height request or -1 to ignore.
+ *
+ * This function will set the "max-content-height" property. This property is
+ * used to determine the maximum height that the scrolled window will request.
+ *
+ * This is useful if you want to have a scrolled window grow with the child
+ * allocation, but only up to a certain height.
+ */
+void
+sp_scrolled_window_set_max_content_height (SpScrolledWindow *self,
+                                           gint               max_content_height)
+{
+  SpScrolledWindowPrivate *priv = sp_scrolled_window_get_instance_private (self);
+
+  g_return_if_fail (SP_IS_SCROLLED_WINDOW (self));
+
+  if (max_content_height != priv->max_content_height)
+    {
+      priv->max_content_height = max_content_height;
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_MAX_CONTENT_HEIGHT]);
+      gtk_widget_queue_resize (GTK_WIDGET (self));
+    }
+}
+
+gint
+sp_scrolled_window_get_max_content_width (SpScrolledWindow *self)
+{
+  SpScrolledWindowPrivate *priv = sp_scrolled_window_get_instance_private (self);
+
+  g_return_val_if_fail (SP_IS_SCROLLED_WINDOW (self), -1);
+
+  return priv->max_content_width;
+}
+
+/**
+ * sp_scrolled_window_set_max_content_width:
+ * @max_content_width: the max allowed width request or -1 to ignore.
+ *
+ * This function will set the "max-content-width" property. This property is
+ * used to determine the maximum width that the scrolled window will request.
+ *
+ * This is useful if you want to have a scrolled window grow with the child
+ * allocation, but only up to a certain width.
+ */
+void
+sp_scrolled_window_set_max_content_width (SpScrolledWindow *self,
+                                           gint               max_content_width)
+{
+  SpScrolledWindowPrivate *priv = sp_scrolled_window_get_instance_private (self);
+
+  g_return_if_fail (SP_IS_SCROLLED_WINDOW (self));
+
+  if (max_content_width != priv->max_content_width)
+    {
+      priv->max_content_width = max_content_width;
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_MAX_CONTENT_HEIGHT]);
+      gtk_widget_queue_resize (GTK_WIDGET (self));
+    }
+}
+
+static void
+sp_scrolled_window_get_preferred_height (GtkWidget *widget,
+                                          gint      *minimum_height,
+                                          gint      *natural_height)
+{
+  SpScrolledWindow *self = (SpScrolledWindow *)widget;
+  SpScrolledWindowPrivate *priv = sp_scrolled_window_get_instance_private (self);
+
+  g_return_if_fail (SP_IS_SCROLLED_WINDOW (self));
+
+  GTK_WIDGET_CLASS (sp_scrolled_window_parent_class)->get_preferred_height (widget, minimum_height, 
natural_height);
+
+  if (natural_height)
+    {
+      if (priv->max_content_height > -1)
+        {
+          GtkWidget *child;
+          GtkStyleContext *style;
+          GtkBorder border;
+          gint child_min_height;
+          gint child_nat_height;
+          gint additional;
+
+          if (!(child = gtk_bin_get_child (GTK_BIN (widget))))
+            return;
+
+          style = gtk_widget_get_style_context (widget);
+          gtk_style_context_get_border (style, gtk_style_context_get_state (style), &border);
+          additional = border.top + border.bottom;
+
+          gtk_widget_get_preferred_height (child, &child_min_height, &child_nat_height);
+
+          if ((child_nat_height > *natural_height) && (priv->max_content_height > *natural_height))
+            *natural_height = MIN (priv->max_content_height, child_nat_height) + additional;
+        }
+    }
+}
+
+static void
+sp_scrolled_window_get_preferred_width (GtkWidget *widget,
+                                         gint      *minimum_width,
+                                         gint      *natural_width)
+{
+  SpScrolledWindow *self = (SpScrolledWindow *)widget;
+  SpScrolledWindowPrivate *priv = sp_scrolled_window_get_instance_private (self);
+
+  g_return_if_fail (SP_IS_SCROLLED_WINDOW (self));
+
+  GTK_WIDGET_CLASS (sp_scrolled_window_parent_class)->get_preferred_width (widget, minimum_width, 
natural_width);
+
+  if (natural_width)
+    {
+      if (priv->max_content_width > -1)
+        {
+          GtkWidget *child;
+          GtkStyleContext *style;
+          GtkBorder border;
+          gint child_min_width;
+          gint child_nat_width;
+          gint additional;
+
+          if (!(child = gtk_bin_get_child (GTK_BIN (widget))))
+            return;
+
+          style = gtk_widget_get_style_context (widget);
+          gtk_style_context_get_border (style, gtk_style_context_get_state (style), &border);
+          additional = border.left = border.right + 1;
+
+          gtk_widget_get_preferred_width (child, &child_min_width, &child_nat_width);
+
+          if ((child_nat_width > *natural_width) && (priv->max_content_width > *natural_width))
+            *natural_width = MIN (priv->max_content_width, child_nat_width) + additional;
+        }
+    }
+}
+
+static void
+sp_scrolled_window_get_property (GObject    *object,
+                                  guint       prop_id,
+                                  GValue     *value,
+                                  GParamSpec *pspec)
+{
+  SpScrolledWindow *self = SP_SCROLLED_WINDOW (object);
+
+  switch (prop_id)
+    {
+    case PROP_MAX_CONTENT_HEIGHT:
+      g_value_set_int (value, sp_scrolled_window_get_max_content_height (self));
+      break;
+
+    case PROP_MAX_CONTENT_WIDTH:
+      g_value_set_int (value, sp_scrolled_window_get_max_content_width (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+sp_scrolled_window_set_property (GObject      *object,
+                                  guint         prop_id,
+                                  const GValue *value,
+                                  GParamSpec   *pspec)
+{
+  SpScrolledWindow *self = SP_SCROLLED_WINDOW (object);
+
+  switch (prop_id)
+    {
+    case PROP_MAX_CONTENT_HEIGHT:
+      sp_scrolled_window_set_max_content_height (self, g_value_get_int (value));
+      break;
+
+    case PROP_MAX_CONTENT_WIDTH:
+      sp_scrolled_window_set_max_content_width (self, g_value_get_int (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+sp_scrolled_window_class_init (SpScrolledWindowClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->get_property = sp_scrolled_window_get_property;
+  object_class->set_property = sp_scrolled_window_set_property;
+
+  widget_class->get_preferred_width = sp_scrolled_window_get_preferred_width;
+  widget_class->get_preferred_height = sp_scrolled_window_get_preferred_height;
+
+  properties [PROP_MAX_CONTENT_HEIGHT] =
+    g_param_spec_int ("max-content-height",
+                      "Max Content Height",
+                      "The maximum height request that can be made.",
+                      -1,
+                      G_MAXINT,
+                      -1,
+                      (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  properties [PROP_MAX_CONTENT_WIDTH] =
+    g_param_spec_int ("max-content-width",
+                      "Max Content Width",
+                      "The maximum width request that can be made.",
+                      -1,
+                      G_MAXINT,
+                      -1,
+                      (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, LAST_PROP, properties);
+}
+
+static void
+sp_scrolled_window_init (SpScrolledWindow *self)
+{
+  SpScrolledWindowPrivate *priv = sp_scrolled_window_get_instance_private (self);
+
+  priv->max_content_height = -1;
+  priv->max_content_width = -1;
+}
diff --git a/lib/sp-scrolled-window.h b/lib/sp-scrolled-window.h
new file mode 100644
index 0000000..4b636d3
--- /dev/null
+++ b/lib/sp-scrolled-window.h
@@ -0,0 +1,45 @@
+/* sp-scrolled-window.h
+ *
+ * Copyright (C) 2014 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_SCROLLED_WINDOW_H
+#define SP_SCROLLED_WINDOW_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_SCROLLED_WINDOW (sp_scrolled_window_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (SpScrolledWindow, sp_scrolled_window, SP, SCROLLED_WINDOW, GtkScrolledWindow)
+
+struct _SpScrolledWindowClass
+{
+  GtkScrolledWindowClass parent_class;
+};
+
+GtkWidget *sp_scrolled_window_new                    (void);
+gint       sp_scrolled_window_get_max_content_height (SpScrolledWindow *self);
+void       sp_scrolled_window_set_max_content_height (SpScrolledWindow *self,
+                                                      gint              max_content_height);
+gint       sp_scrolled_window_get_max_content_width  (SpScrolledWindow *self);
+void       sp_scrolled_window_set_max_content_width  (SpScrolledWindow *self,
+                                                      gint              max_content_width);
+
+G_END_DECLS
+
+#endif /* SP_SCROLLED_WINDOW_H */
diff --git a/lib/sp-source.c b/lib/sp-source.c
new file mode 100644
index 0000000..6a3225c
--- /dev/null
+++ b/lib/sp-source.c
@@ -0,0 +1,137 @@
+/* sp-source.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#include "sp-source.h"
+
+G_DEFINE_INTERFACE (SpSource, sp_source, G_TYPE_OBJECT)
+
+enum {
+  FAILED,
+  FINISHED,
+  READY,
+  N_SIGNALS
+};
+
+static guint signals [N_SIGNALS];
+
+static void
+sp_source_default_init (SpSourceInterface *iface)
+{
+  signals [FAILED] = g_signal_new ("failed",
+                                   G_TYPE_FROM_INTERFACE (iface),
+                                   G_SIGNAL_RUN_LAST,
+                                   0,
+                                   NULL, NULL, NULL,
+                                   G_TYPE_NONE, 1, G_TYPE_ERROR);
+
+  signals [FINISHED] = g_signal_new ("finished",
+                                     G_TYPE_FROM_INTERFACE (iface),
+                                     G_SIGNAL_RUN_LAST,
+                                     0, NULL, NULL, NULL, G_TYPE_NONE, 0);
+
+  signals [READY] = g_signal_new ("ready",
+                                  G_TYPE_FROM_INTERFACE (iface),
+                                  G_SIGNAL_RUN_LAST,
+                                  0, NULL, NULL, NULL, G_TYPE_NONE, 0);
+}
+
+void
+sp_source_add_pid (SpSource *self,
+                   GPid      pid)
+{
+  g_return_if_fail (SP_IS_SOURCE (self));
+  g_return_if_fail (pid != FALSE);
+
+  if (SP_SOURCE_GET_IFACE (self)->add_pid)
+    SP_SOURCE_GET_IFACE (self)->add_pid (self, pid);
+}
+
+void
+sp_source_emit_finished (SpSource *self)
+{
+  g_return_if_fail (SP_IS_SOURCE (self));
+
+  g_signal_emit (self, signals [FINISHED], 0);
+}
+
+void
+sp_source_emit_failed (SpSource     *self,
+                       const GError *error)
+{
+  g_return_if_fail (SP_IS_SOURCE (self));
+  g_return_if_fail (error != NULL);
+
+  g_signal_emit (self, signals [FAILED], 0, error);
+}
+
+void
+sp_source_emit_ready (SpSource *self)
+{
+  g_return_if_fail (SP_IS_SOURCE (self));
+
+  g_signal_emit (self, signals [READY], 0);
+}
+
+gboolean
+sp_source_get_is_ready (SpSource *self)
+{
+  g_return_val_if_fail (SP_IS_SOURCE (self), FALSE);
+
+  if (SP_SOURCE_GET_IFACE (self)->get_is_ready)
+    return SP_SOURCE_GET_IFACE (self)->get_is_ready (self);
+
+  return TRUE;
+}
+
+void
+sp_source_prepare (SpSource *self)
+{
+  g_return_if_fail (SP_IS_SOURCE (self));
+
+  if (SP_SOURCE_GET_IFACE (self)->prepare)
+    SP_SOURCE_GET_IFACE (self)->prepare (self);
+}
+
+void
+sp_source_set_writer (SpSource        *self,
+                      SpCaptureWriter *writer)
+{
+  g_return_if_fail (SP_IS_SOURCE (self));
+  g_return_if_fail (writer != NULL);
+
+  if (SP_SOURCE_GET_IFACE (self)->set_writer)
+    SP_SOURCE_GET_IFACE (self)->set_writer (self, writer);
+}
+
+void
+sp_source_start (SpSource *self)
+{
+  g_return_if_fail (SP_IS_SOURCE (self));
+
+  if (SP_SOURCE_GET_IFACE (self)->start)
+    SP_SOURCE_GET_IFACE (self)->start (self);
+}
+
+void
+sp_source_stop (SpSource *self)
+{
+  g_return_if_fail (SP_IS_SOURCE (self));
+
+  if (SP_SOURCE_GET_IFACE (self)->stop)
+    SP_SOURCE_GET_IFACE (self)->stop (self);
+}
diff --git a/lib/sp-source.h b/lib/sp-source.h
new file mode 100644
index 0000000..2a337a5
--- /dev/null
+++ b/lib/sp-source.h
@@ -0,0 +1,133 @@
+/* sp-source.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_SOURCE_H
+#define SP_SOURCE_H
+
+#include <glib-object.h>
+
+#include "sp-capture-writer.h"
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_SOURCE (sp_source_get_type())
+
+G_DECLARE_INTERFACE (SpSource, sp_source, SP, SOURCE, GObject)
+
+struct _SpSourceInterface
+{
+  GTypeInterface parent_iface;
+
+  /**
+   * SpSource::get_is_ready:
+   * @self: A SpSource.
+   *
+   * This function should return %TRUE if the source is ready to start
+   * profiling. If the source is not ready until after sp_source_start() has
+   * been called, use sp_source_emit_ready() to notify the profiler that the
+   * source is ready for profiling.
+   *
+   * Returns: %TRUE if the source is ready to start profiling.
+   */
+  gboolean (*get_is_ready) (SpSource *self);
+
+  /**
+   * SpSource::set_writer:
+   * @self: A #SpSource.
+   * @writer: A #SpCaptureWriter
+   *
+   * Sets the #SpCaptureWriter to use when profiling. @writer is only safe to
+   * use from the main thread. If you need to capture from a thread, you should
+   * create a memory-based #SpCaptureWriter and then splice that into this
+   * writer from the main thread when profiling completes.
+   *
+   * See sp_capture_writer_splice() for information on splicing writers.
+   */
+  void (*set_writer) (SpSource        *self,
+                      SpCaptureWriter *writer);
+
+  /**
+   * SpSource::prepare:
+   *
+   * This function is called before profiling has started. The source should
+   * prepare any pre-profiling setup here. It may perform this work
+   * asynchronously, but must g_object_notify() the SpSource::is-ready
+   * property once that asynchronous work has been performed. Until it
+   * is ready, #SpSource::is-ready must return FALSE.
+   */
+  void (*prepare) (SpSource *self);
+
+  /**
+   * SpSource::add_pid:
+   * @self: A #SpSource
+   * @pid: A pid_t > -1
+   *
+   * This function is used to notify the #SpSource that a new process,
+   * identified by @pid, should be profiled. By default, sources should
+   * assume all processes, and only restrict to a given set of pids if
+   * this function is called.
+   */
+  void (*add_pid) (SpSource *self,
+                   GPid      pid);
+
+  /**
+   * SpSource::start:
+   * @self: A #SpSource.
+   *
+   * Start profiling as configured.
+   *
+   * If a failure occurs while processing, the source should notify the
+   * profiling session via sp_source_emit_failed() from the main thread.
+   */
+  void (*start) (SpSource *self);
+
+  /**
+   * SpSource::stop:
+   * @self: A #SpSource.
+   *
+   * Stop capturing a profile. The source should immediately stop
+   * profiling and perform any cleanup tasks required. If doing
+   * off-main-thread capturing, this is a good time to splice your
+   * capture into the capture file set with sp_source_set_writer().
+   *
+   * If you need to perform asynchronous cleanup, call
+   * sp_source_emit_finished() once that work has completed. If you do
+   * not need to perform asynchronous cleanup, call
+   * sp_source_emit_finished() from this function.
+   *
+   * sp_source_emit_finished() must be called from the main-thread.
+   */
+  void (*stop) (SpSource *self);
+};
+
+void     sp_source_add_pid       (SpSource        *self,
+                                  GPid             pid);
+void     sp_source_emit_ready    (SpSource        *self);
+void     sp_source_emit_finished (SpSource        *self);
+void     sp_source_emit_failed   (SpSource        *self,
+                                  const GError    *error);
+gboolean sp_source_get_is_ready  (SpSource        *self);
+void     sp_source_prepare       (SpSource        *self);
+void     sp_source_set_writer    (SpSource        *self,
+                                  SpCaptureWriter *writer);
+void     sp_source_start         (SpSource        *self);
+void     sp_source_stop          (SpSource        *self);
+
+G_END_DECLS
+
+#endif /* SP_SOURCE_H */
diff --git a/lib/sp-symbol-resolver.c b/lib/sp-symbol-resolver.c
new file mode 100644
index 0000000..7e20c1a
--- /dev/null
+++ b/lib/sp-symbol-resolver.c
@@ -0,0 +1,72 @@
+/* sp-symbol-resolver.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#include "sp-symbol-resolver.h"
+
+G_DEFINE_INTERFACE (SpSymbolResolver, sp_symbol_resolver, G_TYPE_OBJECT)
+
+static void
+sp_symbol_resolver_default_init (SpSymbolResolverInterface *iface)
+{
+}
+
+void
+sp_symbol_resolver_load (SpSymbolResolver *self,
+                         SpCaptureReader  *reader)
+{
+  g_return_if_fail (SP_IS_SYMBOL_RESOLVER (self));
+  g_return_if_fail (reader != NULL);
+
+  if (SP_SYMBOL_RESOLVER_GET_IFACE (self)->load)
+    SP_SYMBOL_RESOLVER_GET_IFACE (self)->load (self, reader);
+}
+
+/**
+ * sp_symbol_resolver_resolve:
+ * @self: A #SpSymbolResolver
+ * @time: The time of the sample
+ * @pid: The process generating the sample
+ * @address: the sample address
+ * @tag: (out): A tag for the symbol.
+ *
+ * Gets the symbol name for @address that was part of process @pid
+ * at @time. Optionally, you can set @tag to a quark describing the
+ * symbol. This can be used to provide a bit more information when
+ * rendering the treeview. You might choose to describe the library
+ * such as "GObject" or "GTK+" or "Linux" for the kernel.
+ *
+ * Returns: (nullable) (transfer full): A newly allocated string, or %NULL.
+ */
+gchar *
+sp_symbol_resolver_resolve (SpSymbolResolver *self,
+                            guint64           time,
+                            GPid              pid,
+                            SpCaptureAddress  address,
+                            GQuark           *tag)
+{
+  GQuark dummy;
+
+  g_return_val_if_fail (SP_IS_SYMBOL_RESOLVER (self), NULL);
+
+  if (tag == NULL)
+    tag = &dummy;
+
+  *tag = 0;
+
+  return SP_SYMBOL_RESOLVER_GET_IFACE (self)->resolve (self, time, pid, address, tag);
+}
diff --git a/lib/sp-symbol-resolver.h b/lib/sp-symbol-resolver.h
new file mode 100644
index 0000000..3a82205
--- /dev/null
+++ b/lib/sp-symbol-resolver.h
@@ -0,0 +1,55 @@
+/* sp-symbol-resolver.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_SYMBOL_RESOLVER_H
+#define SP_SYMBOL_RESOLVER_H
+
+#include <glib-object.h>
+
+#include "sp-capture-reader.h"
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_SYMBOL_RESOLVER (sp_symbol_resolver_get_type())
+
+G_DECLARE_INTERFACE (SpSymbolResolver, sp_symbol_resolver, SP, SYMBOL_RESOLVER, GObject)
+
+struct _SpSymbolResolverInterface
+{
+  GTypeInterface parent_interface;
+
+  void   (*load)    (SpSymbolResolver *self,
+                     SpCaptureReader  *reader);
+  gchar *(*resolve) (SpSymbolResolver *self,
+                     guint64           time,
+                     GPid              pid,
+                     SpCaptureAddress  address,
+                     GQuark           *tag);
+};
+
+void   sp_symbol_resolver_load    (SpSymbolResolver *self,
+                                   SpCaptureReader  *reader);
+gchar *sp_symbol_resolver_resolve (SpSymbolResolver *self,
+                                   guint64           time,
+                                   GPid              pid,
+                                   SpCaptureAddress  address,
+                                   GQuark           *tag);
+
+G_END_DECLS
+
+#endif /* SP_SYMBOL_RESOLVER_H */
diff --git a/lib/sysprof-version.h.in b/lib/sysprof-version.h.in
new file mode 100644
index 0000000..869dbb0
--- /dev/null
+++ b/lib/sysprof-version.h.in
@@ -0,0 +1,97 @@
+/* sysprof-version.h.in
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#ifndef SYSPROF_VERSION_H
+#define SYSPROF_VERSION_H
+
+#if !defined(SYSPROF_INSIDE) && !defined(SYSPROF_COMPILATION)
+# error "Only <sysprof.h> can be included directly."
+#endif
+
+/**
+ * SECTION:sysprof-version
+ * @short_description: sysprof version checking
+ *
+ * sysprof provides macros to check the version of the library
+ * at compile-time
+ */
+
+/**
+ * SYSPROF_MAJOR_VERSION:
+ *
+ * sysprof major version component (e.g. 1 if %SYSPROF_VERSION is 1.2.3)
+ */
+#define SYSPROF_MAJOR_VERSION (@MAJOR_VERSION@)
+
+/**
+ * SYSPROF_MINOR_VERSION:
+ *
+ * sysprof minor version component (e.g. 2 if %SYSPROF_VERSION is 1.2.3)
+ */
+#define SYSPROF_MINOR_VERSION (@MINOR_VERSION@)
+
+/**
+ * SYSPROF_MICRO_VERSION:
+ *
+ * sysprof micro version component (e.g. 3 if %SYSPROF_VERSION is 1.2.3)
+ */
+#define SYSPROF_MICRO_VERSION (@MICRO_VERSION@)
+
+/**
+ * SYSPROF_VERSION
+ *
+ * sysprof version.
+ */
+#define SYSPROF_VERSION (@VERSION@)
+
+/**
+ * SYSPROF_VERSION_S:
+ *
+ * sysprof version, encoded as a string, useful for printing and
+ * concatenation.
+ */
+#define SYSPROF_VERSION_S "@VERSION@"
+
+#define SYSPROF_ENCODE_VERSION(major,minor,micro) \
+        ((major) << 24 | (minor) << 16 | (micro) << 8)
+
+/**
+ * SYSPROF_VERSION_HEX:
+ *
+ * sysprof version, encoded as an hexadecimal number, useful for
+ * integer comparisons.
+ */
+#define SYSPROF_VERSION_HEX \
+        (SYSPROF_ENCODE_VERSION (SYSPROF_MAJOR_VERSION, SYSPROF_MINOR_VERSION, SYSPROF_MICRO_VERSION))
+
+/**
+ * SYSPROF_CHECK_VERSION:
+ * @major: required major version
+ * @minor: required minor version
+ * @micro: required micro version
+ *
+ * Compile-time version checking. Evaluates to %TRUE if the version
+ * of sysprof is greater than the required one.
+ */
+#define SYSPROF_CHECK_VERSION(major,minor,micro)   \
+        (SYSPROF_MAJOR_VERSION > (major) || \
+         (SYSPROF_MAJOR_VERSION == (major) && SYSPROF_MINOR_VERSION > (minor)) || \
+         (SYSPROF_MAJOR_VERSION == (major) && SYSPROF_MINOR_VERSION == (minor) && \
+          SYSPROF_MICRO_VERSION >= (micro)))
+
+#endif /* SYSPROF_VERSION_H */
diff --git a/lib/sysprof.h b/lib/sysprof.h
new file mode 100644
index 0000000..776bb26
--- /dev/null
+++ b/lib/sysprof.h
@@ -0,0 +1,59 @@
+/* sysprof.h
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#ifndef SYSPROF_H
+#define SYSPROF_H
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define SYSPROF_INSIDE
+# include "sp-address.h"
+# include "sp-callgraph-profile.h"
+# include "sp-callgraph-view.h"
+# include "sp-capture-reader.h"
+# include "sp-capture-writer.h"
+# include "sp-cell-renderer-percent.h"
+# include "sp-clock.h"
+# include "sp-elf-symbol-resolver.h"
+# include "sp-empty-state-view.h"
+# include "sp-error.h"
+# include "sp-gjs-source.h"
+# include "sp-jitmap-symbol-resolver.h"
+# include "sp-kernel-symbol.h"
+# include "sp-kernel-symbol-resolver.h"
+# include "sp-map-lookaside.h"
+# include "sp-model-filter.h"
+# include "sp-recording-state-view.h"
+# include "sp-perf-source.h"
+# include "sp-proc-source.h"
+# include "sp-process-model.h"
+# include "sp-process-model-item.h"
+# include "sp-process-model-row.h"
+# include "sp-profile.h"
+# include "sp-profiler.h"
+# include "sp-profiler-menu-button.h"
+# include "sp-source.h"
+# include "sp-symbol-resolver.h"
+# include "sysprof-version.h"
+#undef SYSPROF_INSIDE
+
+G_END_DECLS
+
+#endif /* SYSPROF_H */
diff --git a/lib/util/binfile.c b/lib/util/binfile.c
new file mode 100644
index 0000000..be181c3
--- /dev/null
+++ b/lib/util/binfile.c
@@ -0,0 +1,540 @@
+/* MemProf -- memory profiler and leak detector
+ * Copyright 1999, 2000, 2001, Red Hat, Inc.
+ * Copyright 2002, Kristian Rietveld
+ *
+ * Sysprof -- Sampling, systemwide CPU profiler
+ * Copyright 2004, 2005, 2006, 2007, Soeren Sandmann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* Most interesting code in this file is lifted from bfdutils.c
+ * and process.c from Memprof,
+ */
+#include "config.h"
+
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdint.h>
+
+#include "binfile.h"
+#include "elfparser.h"
+#include "util.h"
+
+struct bin_file_t
+{
+    int         ref_count;
+
+    GList *     elf_files;
+
+    char *      filename;
+
+    char *      undefined_name;
+
+    gulong      text_offset;
+
+    gboolean    inode_check;
+    ino_t       inode;
+};
+
+static ino_t
+read_inode (const char *filename)
+{
+    struct stat statbuf;
+
+    if (strcmp (filename, "[vdso]") == 0)
+        return (ino_t)0;
+
+    if (stat (filename, &statbuf) < 0)
+        return (ino_t)-1;
+
+    return statbuf.st_ino;
+}
+
+static gboolean
+already_warned (const char *name)
+{
+    static GPtrArray *warnings;
+    guint i;
+
+    if (!warnings)
+        warnings = g_ptr_array_new ();
+
+    for (i = 0; i < warnings->len; ++i)
+    {
+        if (strcmp (warnings->pdata[i], name) == 0)
+            return TRUE;
+    }
+
+    g_ptr_array_add (warnings, g_strdup (name));
+
+    return FALSE;
+}
+
+static const char *const debug_file_directory = DEBUGDIR;
+
+static ElfParser *
+get_build_id_file (ElfParser *elf)
+{
+    const char *build_id;
+    GList *tries = NULL, *list;
+    char *init, *rest;
+    ElfParser *result = NULL;
+    char *tmp;
+
+    build_id = elf_parser_get_build_id (elf);
+
+    if (!build_id)
+        return NULL;
+
+    if (strlen (build_id) < 4)
+        return NULL;
+
+    init = g_strndup (build_id, 2);
+    rest = g_strdup_printf ("%s%s", build_id + 2, ".debug");
+
+    tmp = g_build_filename (
+        "/usr", "lib", "debug", ".build-id", init, rest, NULL);
+    tries = g_list_append (tries, tmp);
+
+    tmp = g_build_filename (
+        debug_file_directory, ".build-id", init, rest, NULL);
+    tries = g_list_append (tries, tmp);
+
+    for (list = tries; list != NULL; list = list->next)
+    {
+        char *name = list->data;
+        ElfParser *parser = elf_parser_new (name, NULL);
+
+        if (parser)
+        {
+            const char *file_id = elf_parser_get_build_id (parser);
+
+            if (file_id && strcmp (build_id, file_id) == 0)
+            {
+                result = parser;
+                break;
+            }
+
+            elf_parser_free (parser);
+        }
+    }
+
+    g_list_foreach (tries, (GFunc)g_free, NULL);
+    g_list_free (tries);
+
+    g_free (init);
+    g_free (rest);
+
+    return result;
+}
+
+static ElfParser *
+get_debuglink_file (ElfParser   *elf,
+                    const char  *filename,
+                    char       **new_name)
+{
+#define N_TRIES 4
+    const char *basename;
+    char *dir;
+    guint32 crc32;
+    GList *tries = NULL, *list;
+    ElfParser *result = NULL;
+    const char *build_id;
+
+    if (!elf)
+        return NULL;
+
+    basename = elf_parser_get_debug_link (elf, &crc32);
+
+    build_id = elf_parser_get_build_id (elf);
+
+#if 0
+    g_print ("   debug link for %s is %s\n", filename, basename);
+#endif
+
+    if (!basename)
+        return NULL;
+
+    dir = g_path_get_dirname (filename);
+
+    tries = g_list_append (tries, g_build_filename (dir, basename, NULL));
+    tries = g_list_append (tries, g_build_filename (dir, ".debug", basename, NULL));
+    tries = g_list_append (tries, g_build_filename ("/usr", "lib", "debug", dir, basename, NULL));
+    tries = g_list_append (tries, g_build_filename (debug_file_directory, dir, basename, NULL));
+
+    for (list = tries; list != NULL; list = list->next)
+    {
+        const char *name = list->data;
+        ElfParser *parser = elf_parser_new (name, NULL);
+        guint32 file_crc;
+        const char *file_build_id;
+
+        if (parser)
+        {
+            /* If both files have build ids, and they don't match,
+             * there is no point computing a CRC32 that we know
+             * will fail
+             */
+            file_build_id = elf_parser_get_build_id (parser);
+            if (build_id && file_build_id && strcmp (build_id, file_build_id) != 0)
+                goto skip;
+
+            file_crc = elf_parser_get_crc32 (parser);
+
+            if (file_crc == crc32)
+            {
+                result = parser;
+                *new_name = g_strdup (name);
+                break;
+            }
+            else
+            {
+                if (!already_warned (name))
+                {
+                    g_print ("warning: %s has wrong crc %x, %s has crc %x)\n",
+                             name, file_crc, filename, crc32);
+                }
+            }
+
+        skip:
+            elf_parser_free (parser);
+        }
+    }
+
+    g_free (dir);
+
+    g_list_foreach (tries, (GFunc)g_free, NULL);
+    g_list_free (tries);
+
+    return result;
+}
+
+static GList *
+get_debug_binaries (GList      *files,
+                    ElfParser  *elf,
+                    const char *filename)
+{
+    ElfParser *build_id_file;
+    GHashTable *seen_names;
+    GList *free_us = NULL;
+
+    build_id_file = get_build_id_file (elf);
+
+    if (build_id_file)
+        return g_list_prepend (files, build_id_file);
+
+    /* .gnu_debuglink is actually a chain of debuglinks, and
+     * there have been real-world cases where following it was
+     * necessary to get useful debug information.
+     */
+    seen_names = g_hash_table_new (g_str_hash, g_str_equal);
+
+    while (elf)
+    {
+        char *debug_name;
+
+        if (g_hash_table_lookup (seen_names, filename))
+            break;
+
+        g_hash_table_insert (seen_names, (char *)filename, (char *)filename);
+
+        elf = get_debuglink_file (elf, filename, &debug_name);
+
+        if (elf)
+        {
+            files = g_list_prepend (files, elf);
+            free_us = g_list_prepend (free_us, debug_name);
+            filename = debug_name;
+        }
+    }
+
+    g_list_foreach (free_us, (GFunc)g_free, NULL);
+    g_list_free (free_us);
+
+    g_hash_table_destroy (seen_names);
+
+    return files;
+}
+
+static char **
+get_lines (const char *format,
+           ...)
+  G_GNUC_PRINTF (1, 2);
+
+static char **
+get_lines (const char *format,
+           ...)
+{
+    va_list args;
+    char *filename;
+    char **result = NULL;
+    char *contents;
+
+    va_start (args, format);
+    filename = g_strdup_vprintf (format, args);
+    va_end (args);
+
+    if (g_file_get_contents (filename, &contents, NULL, NULL))
+    {
+        result = g_strsplit (contents, "\n", -1);
+
+        g_free (contents);
+    }
+
+    g_free (filename);
+
+    return result;
+}
+
+static const uint8_t *
+get_vdso_bytes (size_t *length)
+{
+    static const uint8_t *bytes = NULL;
+    static size_t n_bytes = 0;
+    static gboolean has_data;
+
+    if (!has_data)
+    {
+        char **lines = get_lines ("/proc/%d/maps", getpid());
+        int i;
+
+        for (i = 0; lines[i] != NULL; ++i)
+        {
+            char file[256];
+            gulong start;
+            gulong end;
+            int count = sscanf (
+                lines[i], "%lx-%lx %*15s %*x %*x:%*x %*u %255s",
+                &start, &end, file);
+
+            if (count == 3 && strcmp (file, "[vdso]") == 0)
+            {
+                n_bytes = end - start;
+
+                /* Dup the memory here so that valgrind will only
+                 * report one 1 byte invalid read instead of
+                 * a ton when the elf parser scans the vdso
+                 *
+                 * The reason we get a spurious invalid read from
+                 * valgrind is that we are getting the address directly
+                 * from /proc/maps, and valgrind knows that its mmap()
+                 * wrapper never returned that address. But since it
+                 * is a legal mapping, it is legal to read it.
+                 */
+                bytes = g_memdup ((uint8_t *)start, n_bytes);
+
+                has_data = TRUE;
+            }
+        }
+    }
+
+    if (length)
+        *length = n_bytes;
+
+    return bytes;
+}
+
+bin_file_t *
+bin_file_new (const char *filename)
+{
+    ElfParser *elf = NULL;
+    bin_file_t *bf;
+
+    bf = g_new0 (bin_file_t, 1);
+
+    bf->inode_check = FALSE;
+    bf->filename = g_strdup (filename);
+    bf->undefined_name = g_strdup_printf ("In file %s", filename);
+    bf->ref_count = 1;
+    bf->elf_files = NULL;
+
+    if (strcmp (filename, "[vdso]") == 0)
+    {
+        const guint8 *vdso_bytes;
+        gsize length;
+
+        vdso_bytes = get_vdso_bytes (&length);
+
+        if (vdso_bytes)
+            elf = elf_parser_new_from_data (vdso_bytes, length);
+    }
+    else
+    {
+        elf = elf_parser_new (filename, NULL);
+    }
+
+    if (elf)
+    {
+        /* We need the text offset of the actual binary, not the
+         * (potential) debug binaries
+         */
+        bf->text_offset = elf_parser_get_text_offset (elf);
+
+        bf->elf_files = get_debug_binaries (bf->elf_files, elf, filename);
+        bf->elf_files = g_list_append (bf->elf_files, elf);
+
+        bf->inode = read_inode (filename);
+    }
+
+    return bf;
+}
+
+void
+bin_file_free (bin_file_t *bin_file)
+{
+    if (--bin_file->ref_count == 0)
+    {
+        g_list_foreach (bin_file->elf_files, (GFunc)elf_parser_free, NULL);
+        g_list_free (bin_file->elf_files);
+
+        g_free (bin_file->filename);
+        g_free (bin_file->undefined_name);
+        g_free (bin_file);
+    }
+}
+
+const bin_symbol_t *
+bin_file_lookup_symbol (bin_file_t    *bin_file,
+                        gulong      address)
+{
+    GList *list;
+
+#if 0
+    g_print ("-=-=-=- \n");
+
+    g_print ("bin file lookup lookup %d\n", address);
+#endif
+
+    address -= bin_file->text_offset;
+
+#if 0
+    g_print ("lookup %d in %s\n", address, bin_file->filename);
+#endif
+
+    for (list = bin_file->elf_files; list != NULL; list = list->next)
+    {
+        ElfParser *elf = list->data;
+        const ElfSym *sym = elf_parser_lookup_symbol (elf, address);
+
+        if (sym)
+        {
+#if 0
+            g_print ("found  %lx => %s\n", address,
+                     bin_symbol_get_name (bin_file, sym));
+#endif
+            return (const bin_symbol_t *)sym;
+        }
+    }
+
+#if 0
+    g_print ("%lx undefined in %s (textoffset %x)\n",
+             address + bin_file->text_offset,
+             bin_file->filename,
+             bin_file->text_offset);
+#endif
+
+    return (const bin_symbol_t *)bin_file->undefined_name;
+}
+
+gboolean
+bin_file_check_inode (bin_file_t *bin_file,
+                      ino_t       inode)
+{
+    if (bin_file->inode == inode)
+        return TRUE;
+
+    if (!bin_file->elf_files)
+        return FALSE;
+
+    if (!bin_file->inode_check)
+    {
+        g_print ("warning: Inode mismatch for %s (disk: %"G_GUINT64_FORMAT", memory: %"G_GUINT64_FORMAT")\n",
+                 bin_file->filename, (guint64)bin_file->inode, (guint64)inode);
+
+        bin_file->inode_check = TRUE;
+    }
+
+    return FALSE;
+}
+
+static const ElfSym *
+get_elf_sym (bin_file_t *file,
+             const bin_symbol_t *symbol,
+             ElfParser **elf_ret)
+{
+    GList *list;
+
+    for (list = file->elf_files; list != NULL; list = list->next)
+    {
+        const ElfSym *sym = (const ElfSym *)symbol;
+        ElfParser *elf = list->data;
+
+        if (elf_parser_owns_symbol (elf, sym))
+        {
+            *elf_ret = elf;
+            return sym;
+        }
+    }
+
+    g_critical ("Internal error: unrecognized symbol pointer");
+
+    *elf_ret = NULL;
+    return NULL;
+}
+
+const char *
+bin_symbol_get_name (bin_file_t *file,
+                     const bin_symbol_t *symbol)
+{
+    if (file->undefined_name == (char *)symbol)
+    {
+        return file->undefined_name;
+    }
+    else
+    {
+        ElfParser *elf;
+        const ElfSym *sym;
+
+        sym = get_elf_sym (file, symbol, &elf);
+
+        return elf_parser_get_sym_name (elf, sym);
+    }
+}
+
+gulong
+bin_symbol_get_address (bin_file_t      *file,
+                        const bin_symbol_t *symbol)
+{
+    if (file->undefined_name == (char *)symbol)
+    {
+        return 0x0;
+    }
+    else
+    {
+        ElfParser *elf;
+        const ElfSym *sym;
+
+        sym = get_elf_sym (file, symbol, &elf);
+
+        return elf_parser_get_sym_address (elf, sym);
+    }
+}
diff --git a/lib/binfile.h b/lib/util/binfile.h
similarity index 65%
rename from lib/binfile.h
rename to lib/util/binfile.h
index 03c3a41..42a7847 100644
--- a/lib/binfile.h
+++ b/lib/util/binfile.h
@@ -32,15 +32,15 @@ typedef struct bin_symbol_t bin_symbol_t;
 
 /* Binary File */
 
-bin_file_t *        bin_file_new           (const char      *filename);
-void             bin_file_free          (bin_file_t         *bin_file);
+bin_file_t *        bin_file_new           (const char         *filename);
+void                bin_file_free          (bin_file_t         *bin_file);
 const bin_symbol_t *bin_file_lookup_symbol (bin_file_t         *bin_file,
-                                        gulong           address);
-gboolean         bin_file_check_inode   (bin_file_t         *bin_file,
-                                        ino_t            inode);
-const char *     bin_symbol_get_name    (bin_file_t         *bin_file,
-                                        const bin_symbol_t *symbol);
-gulong          bin_symbol_get_address (bin_file_t         *bin_file,
-                                        const bin_symbol_t *symbol);
+                                            gulong              address);
+gboolean            bin_file_check_inode   (bin_file_t         *bin_file,
+                                            ino_t               inode);
+const char *        bin_symbol_get_name    (bin_file_t         *bin_file,
+                                            const bin_symbol_t *symbol);
+gulong              bin_symbol_get_address (bin_file_t         *bin_file,
+                                            const bin_symbol_t *symbol);
 
 #endif
diff --git a/lib/util/demangle.cpp b/lib/util/demangle.cpp
new file mode 100644
index 0000000..1f941cd
--- /dev/null
+++ b/lib/util/demangle.cpp
@@ -0,0 +1,40 @@
+/* demangle.cpp
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#include <cxxabi.h>
+#include <stdlib.h>
+
+#include "demangle.h"
+
+gchar *
+sysprof_cplus_demangle (const gchar *name)
+{
+  char *real_name;
+  gchar *ret;
+  int status;
+
+  real_name = abi::__cxa_demangle (name, 0, 0, &status);
+
+  if (real_name == NULL)
+    return NULL;
+
+  ret = g_strdup (real_name);
+  free (real_name);
+
+  return ret;
+}
diff --git a/lib/util/demangle.h b/lib/util/demangle.h
new file mode 100644
index 0000000..0783ad5
--- /dev/null
+++ b/lib/util/demangle.h
@@ -0,0 +1,30 @@
+/* demangle.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef DEMANGLE_H
+#define DEMANGLE_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+gchar *sysprof_cplus_demangle (const gchar *name);
+
+G_END_DECLS
+
+#endif /* DEMANGLE_H */
diff --git a/lib/util/elfparser.c b/lib/util/elfparser.c
new file mode 100644
index 0000000..2d4cb52
--- /dev/null
+++ b/lib/util/elfparser.c
@@ -0,0 +1,811 @@
+/* Sysprof -- Sampling, systemwide CPU profiler
+ * Copyright 2006, 2007, Soeren Sandmann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <elf.h>
+#include <sys/mman.h>
+
+#include "demangle.h"
+#include "elfparser.h"
+
+typedef struct Section Section;
+
+struct ElfSym
+{
+    gulong table;
+    gulong offset;
+    gulong address;
+};
+
+struct Section
+{
+    const gchar *       name;
+    gsize               offset;
+    gsize               size;
+    gboolean            allocated;
+    gulong              load_address;
+    guint               type;
+};
+
+struct ElfParser
+{
+    gboolean            is_64;
+    const guchar *      data;
+    gsize               length;
+
+    guint               n_sections;
+    Section **          sections;
+
+    guint               n_symbols;
+    ElfSym *            symbols;
+    gsize               sym_strings;
+
+    GMappedFile *       file;
+
+    char *              filename;
+
+    gboolean            checked_build_id;
+    char *              build_id;
+
+    const Section *     text_section;
+};
+
+/* FIXME: All of these should in principle do endian swapping,
+ * but sysprof never has to deal with binaries of a different
+ * endianness than sysprof itself
+ */
+#define GET_FIELD(parser, offset, struct_name, idx, field_name)         \
+    (((parser))->is_64?                                                 \
+     ((Elf64_ ## struct_name *)(((parser)->data + offset)) + (idx))->field_name : \
+     ((Elf32_ ## struct_name *)(((parser)->data + offset)) + (idx))->field_name)
+
+#define GET_UINT32(parser, offset)                                      \
+    *((uint32_t *)(parser->data + offset))                              \
+
+#define GET_SIZE(parser, struct_name)                                   \
+    (((parser)->is_64?                                                  \
+      sizeof (Elf64_ ## struct_name) :                                  \
+      sizeof (Elf32_ ## struct_name)))
+
+#define MAKE_ELF_UINT_ACCESSOR(field_name)                              \
+    static uint64_t field_name  (ElfParser *parser)                     \
+    {                                                                   \
+        return GET_FIELD (parser, 0, Ehdr, 0, field_name);              \
+    }
+
+MAKE_ELF_UINT_ACCESSOR (e_shoff)
+MAKE_ELF_UINT_ACCESSOR (e_shnum)
+MAKE_ELF_UINT_ACCESSOR (e_shstrndx)
+
+#define MAKE_SECTION_HEADER_ACCESSOR(field_name)                        \
+    static uint64_t field_name (ElfParser *parser, int nth_section)     \
+    {                                                                   \
+        gsize offset = e_shoff (parser);                                \
+                                                                        \
+        return GET_FIELD (parser, offset, Shdr, nth_section, field_name); \
+    }
+
+MAKE_SECTION_HEADER_ACCESSOR (sh_name);
+MAKE_SECTION_HEADER_ACCESSOR (sh_type);
+MAKE_SECTION_HEADER_ACCESSOR (sh_flags);
+MAKE_SECTION_HEADER_ACCESSOR (sh_addr);
+MAKE_SECTION_HEADER_ACCESSOR (sh_offset);
+MAKE_SECTION_HEADER_ACCESSOR (sh_size);
+
+#define MAKE_SYMBOL_ACCESSOR(field_name)                                \
+    static uint64_t field_name (ElfParser *parser, gulong offset, gulong nth)   \
+    {                                                                   \
+        return GET_FIELD (parser, offset, Sym, nth, field_name);        \
+    }
+
+MAKE_SYMBOL_ACCESSOR(st_name);
+MAKE_SYMBOL_ACCESSOR(st_info);
+MAKE_SYMBOL_ACCESSOR(st_value);
+MAKE_SYMBOL_ACCESSOR(st_size);
+MAKE_SYMBOL_ACCESSOR(st_shndx);
+
+static void
+section_free (Section *section)
+{
+    g_free (section);
+}
+
+static const Section *
+find_section (ElfParser *parser,
+              const char *name,
+              guint       type)
+{
+    guint i;
+
+    for (i = 0; i < parser->n_sections; ++i)
+    {
+        Section *section = parser->sections[i];
+
+        if (strcmp (section->name, name) == 0 && section->type == type)
+            return section;
+    }
+
+    return NULL;
+}
+
+static gboolean
+parse_elf_signature (const guchar *data,
+                     gsize         length,
+                     gboolean     *is_64,
+                     gboolean     *is_be)
+{
+    /* FIXME: this function should be able to return an error */
+    if (length < EI_NIDENT)
+    {
+        /* FIXME set error */
+        return FALSE;
+    }
+
+    if (data[EI_CLASS] != ELFCLASS32 &&
+        data[EI_CLASS] != ELFCLASS64)
+    {
+        /* FIXME set error */
+        return FALSE;
+    }
+
+    if (data[EI_DATA] != ELFDATA2LSB &&
+        data[EI_DATA] != ELFDATA2MSB)
+    {
+        /* FIXME set error */
+        return FALSE;
+    }
+
+    if (is_64)
+        *is_64 = (data[EI_CLASS] == ELFCLASS64);
+
+    if (is_be)
+        *is_be = (data[EI_DATA] == ELFDATA2MSB);
+
+    return TRUE;
+}
+
+ElfParser *
+elf_parser_new_from_data (const guchar *data,
+                          gsize length)
+{
+    ElfParser *parser;
+    gboolean is_64, is_big_endian;
+    int section_names_idx;
+    const guchar *section_names;
+    G_GNUC_UNUSED gsize section_headers;
+    guint i;
+
+    if (!parse_elf_signature (data, length, &is_64, &is_big_endian))
+    {
+        /* FIXME: set error */
+        return NULL;
+    }
+
+    parser = g_new0 (ElfParser, 1);
+
+    parser->is_64 = is_64;
+    parser->data = data;
+    parser->length = length;
+
+#if 0
+    g_print ("  new parser : %p\n", parser);
+#endif
+
+    /* Read ELF header */
+
+    parser->n_sections = e_shnum (parser);
+    section_names_idx = e_shstrndx (parser);
+    section_headers = e_shoff (parser);
+
+    /* Read section headers */
+    parser->sections = g_new0 (Section *, parser->n_sections);
+
+    section_names = parser->data + sh_offset (parser, section_names_idx);
+
+    for (i = 0; i < parser->n_sections; ++i)
+    {
+        Section *section = g_new (Section, 1);
+
+        section->name = (char *)(section_names + sh_name (parser, i));
+        section->size = sh_size (parser, i);
+        section->offset = sh_offset (parser, i);
+        section->allocated = !!(sh_flags (parser, i) & SHF_ALLOC);
+
+        if (section->allocated)
+            section->load_address = sh_addr (parser, i);
+        else
+            section->load_address = 0;
+
+        section->type = sh_type (parser, i);
+
+        parser->sections[i] = section;
+    }
+
+    /* Cache the text section */
+    parser->text_section = find_section (parser, ".text", SHT_PROGBITS);
+    if (!parser->text_section)
+        parser->text_section = find_section (parser, ".text", SHT_NOBITS);
+
+    parser->filename = NULL;
+    parser->build_id = NULL;
+
+    return parser;
+}
+
+ElfParser *
+elf_parser_new (const char *filename,
+                GError **err)
+{
+    const guchar *data;
+    gsize length;
+    ElfParser *parser;
+
+    GMappedFile *file = g_mapped_file_new (filename, FALSE, NULL);
+
+    if (!file)
+        return NULL;
+
+#if 0
+    g_print ("elf parser new : %s\n", filename);
+#endif
+
+    data = (guchar *)g_mapped_file_get_contents (file);
+    length = g_mapped_file_get_length (file);
+
+#if 0
+    g_print ("data %p: for %s\n", data, filename);
+#endif
+
+    parser = elf_parser_new_from_data (data, length);
+
+#if 0
+    g_print ("Parser for %s: %p\n", filename, parser);
+#endif
+
+    if (!parser)
+    {
+        g_mapped_file_unref (file);
+        return NULL;
+    }
+
+    parser->filename = g_strdup (filename);
+
+    parser->file = file;
+
+#if 0
+    g_print ("Elf file: %s  (debug: %s)\n",
+             filename, elf_parser_get_debug_link (parser, NULL));
+
+    if (!parser->symbols)
+        g_print ("at this point %s has no symbols\n", filename);
+#endif
+
+    return parser;
+}
+
+guint32
+elf_parser_get_crc32 (ElfParser *parser)
+{
+    static const unsigned long crc32_table[256] = {
+        0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+        0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+        0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+        0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+        0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+        0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+        0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+        0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+        0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+        0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+        0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+        0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+        0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+        0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+        0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+        0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+        0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+        0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+        0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+        0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+        0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+        0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+        0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+        0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+        0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+        0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+        0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+        0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+        0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+        0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+        0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+        0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+        0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+        0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+        0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+        0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+        0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+        0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+        0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+        0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+        0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+        0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+        0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+    };
+    const guchar *data;
+    gsize length;
+    gulong crc;
+    gsize i;
+
+    data = parser->data;
+    length = parser->length;
+
+    crc = 0xffffffff;
+
+    madvise ((char *)data, length, MADV_SEQUENTIAL);
+
+    for (i = 0; i < length; ++i)
+        crc = crc32_table[(crc ^ data[i]) & 0xff] ^ (crc >> 8);
+
+    /* We just read the entire file into memory, but we only really
+     * need the symbol table, so swap the whole thing out.
+     *
+     * We could be more exact here, but it's only a few minor
+     * pagefaults.
+     */
+    if (parser->file)
+        madvise ((char *)data, length, MADV_DONTNEED);
+
+    return ~crc & 0xffffffff;
+}
+
+void
+elf_parser_free (ElfParser *parser)
+{
+    guint i;
+
+    for (i = 0; i < parser->n_sections; ++i)
+        section_free (parser->sections[i]);
+    g_free (parser->sections);
+
+    if (parser->file)
+        g_mapped_file_unref (parser->file);
+
+    g_free (parser->symbols);
+
+    if (parser->filename)
+        g_free (parser->filename);
+
+    if (parser->build_id)
+        g_free (parser->build_id);
+
+    g_free (parser);
+}
+
+gchar *
+elf_demangle (const char *name)
+{
+    gchar *demangled = sysprof_cplus_demangle (name);
+
+    if (demangled)
+        return demangled;
+    else
+        return g_strdup (name);
+}
+
+/*
+ * Looking up symbols
+ */
+static int
+compare_sym (const void *a, const void *b)
+{
+    const ElfSym *sym_a = a;
+    const ElfSym *sym_b = b;
+
+    if (sym_a->address < sym_b->address)
+        return -1;
+    else if (sym_a->address == sym_b->address)
+        return 0;
+    else
+        return 1;
+}
+
+#if 0
+static void
+dump_symbols (ElfParser *parser, ElfSym *syms, guint n_syms)
+{
+    int i;
+
+    for (i = 0; i < n_syms; ++i)
+    {
+        ElfSym *s = &(syms[i]);
+
+        g_print ("   %s: %lx\n", elf_parser_get_sym_name (parser, s), s->address);
+    }
+}
+#endif
+
+static void
+read_table (ElfParser *parser,
+            const Section *sym_table,
+            const Section *str_table)
+{
+    int sym_size = GET_SIZE (parser, Sym);
+    guint i, n_symbols;
+
+#if 0
+    g_print ("elf: Reading table for %s\n", parser->filename? parser->filename : "<unknown>");
+#endif
+
+    parser->n_symbols = sym_table->size / sym_size;
+    parser->symbols = g_new (ElfSym, parser->n_symbols);
+
+#if 0
+    g_print ("sym table offset: %d\n", sym_table->offset);
+#endif
+
+    n_symbols = 0;
+#if 0
+    g_print ("n syms: %d\n", parser->n_symbols);
+#endif
+    for (i = 0; i < parser->n_symbols; ++i)
+    {
+        guint info;
+        gulong addr;
+        gulong shndx;
+
+        info = st_info (parser, sym_table->offset, i);
+        addr = st_value (parser, sym_table->offset, i);
+        shndx = st_shndx (parser, sym_table->offset, i);
+
+#if 0
+        g_print ("read symbol: %s (section: %d)\n", get_string_indirct (parser->parser,
+                                                                         parser->sym_format, "st_name",
+                                                                         str_table->offset),
+                 shndx);
+#endif
+
+        if (addr != 0                                           &&
+            shndx < parser->n_sections                          &&
+            parser->sections[shndx] == parser->text_section     &&
+            (info & 0xf) == STT_FUNC                            &&
+            ((info >> 4) == STB_GLOBAL ||
+             (info >> 4) == STB_LOCAL  ||
+             (info >> 4) == STB_WEAK))
+        {
+            parser->symbols[n_symbols].address = addr;
+            parser->symbols[n_symbols].table = sym_table->offset;
+            parser->symbols[n_symbols].offset = i;
+
+            n_symbols++;
+
+#if 0
+            g_print ("    symbol: %s:   %lx\n",
+                     get_string_indirect (parser->parser,
+                                          parser->sym_format, "st_name",
+                                          str_table->offset),
+                     addr - parser->text_section->load_address);
+            g_print ("        sym %d in %p (info: %d:%d) (func:global  %d:%d)\n",
+                     addr, parser, info & 0xf, info >> 4, STT_FUNC, STB_GLOBAL);
+#endif
+        }
+        else if (addr != 0)
+        {
+#if 0
+            g_print ("        rejecting %d in %p (info: %d:%d) (func:global  %d:%d)\n",
+                     addr, parser, info & 0xf, info >> 4, STT_FUNC, STB_GLOBAL);
+#endif
+        }
+    }
+
+    parser->sym_strings = str_table->offset;
+    parser->n_symbols = n_symbols;
+
+    /* Allocate space for at least one symbol, so that parser->symbols will be
+     * non-NULL. If it ends up being NULL, we will be parsing the file over and
+     * over.
+     */
+    parser->symbols = g_renew (ElfSym, parser->symbols, parser->n_symbols + 1);
+
+    qsort (parser->symbols, parser->n_symbols, sizeof (ElfSym), compare_sym);
+}
+
+static void
+read_symbols (ElfParser *parser)
+{
+    const Section *symtab = find_section (parser, ".symtab", SHT_SYMTAB);
+    const Section *strtab = find_section (parser, ".strtab", SHT_STRTAB);
+    const Section *dynsym = find_section (parser, ".dynsym", SHT_DYNSYM);
+    const Section *dynstr = find_section (parser, ".dynstr", SHT_STRTAB);
+
+    if (symtab && strtab)
+    {
+#if 0
+        g_print ("reading symbol table of %s\n", parser->filename);
+#endif
+        read_table (parser, symtab, strtab);
+    }
+    else if (dynsym && dynstr)
+    {
+#if 0
+        g_print ("reading dynamic symbol table of %s\n", parser->filename);
+#endif
+        read_table (parser, dynsym, dynstr);
+    }
+    else
+    {
+        /* To make sure parser->symbols is non-NULL */
+        parser->n_symbols = 0;
+        parser->symbols = g_new (ElfSym, 1);
+    }
+}
+
+static ElfSym *
+do_lookup (ElfSym *symbols,
+           gulong  address,
+           int     first,
+           int     last)
+{
+    if (address >= symbols[last].address)
+    {
+        return &(symbols[last]);
+    }
+    else if (last - first < 3)
+    {
+        while (last >= first)
+        {
+            if (address >= symbols[last].address)
+                return &(symbols[last]);
+
+            last--;
+        }
+
+        return NULL;
+    }
+    else
+    {
+        int mid = (first + last) / 2;
+
+        if (symbols[mid].address > address)
+            return do_lookup (symbols, address, first, mid);
+        else
+            return do_lookup (symbols, address, mid, last);
+    }
+}
+
+/* Address should be given in 'offset into text segment' */
+const ElfSym *
+elf_parser_lookup_symbol (ElfParser *parser,
+                          gulong     address)
+{
+    const ElfSym *result;
+
+    if (!parser->symbols)
+    {
+#if 0
+        g_print ("reading symbols at %p\n", parser);
+#endif
+        read_symbols (parser);
+    }
+
+    if (parser->n_symbols == 0)
+        return NULL;
+
+    if (!parser->text_section)
+        return NULL;
+
+    address += parser->text_section->load_address;
+
+#if 0
+    g_print ("elf: the address we are looking up is %p\n", address);
+#endif
+
+    result = do_lookup (parser->symbols, address, 0, parser->n_symbols - 1);
+
+#if 0
+    if (result)
+    {
+        g_print ("  elf: found %s at %lx\n", elf_parser_get_sym_name (parser, result), result->address);
+    }
+    else
+    {
+        g_print ("elf: not found\n");
+    }
+#endif
+
+    if (result)
+    {
+        gulong size = st_size (parser, result->table, result->offset);
+
+        if (size > 0 && result->address + size <= address)
+        {
+#if 0
+            g_print ("  elf: ends at %lx, so rejecting\n",
+                     result->address + size);
+#endif
+            result = NULL;
+        }
+    }
+
+    if (result)
+    {
+        /* Reject the symbols if the address is outside the text section */
+        if (address > parser->text_section->load_address + parser->text_section->size)
+            result = NULL;
+    }
+
+    return result;
+}
+
+gulong
+elf_parser_get_text_offset (ElfParser *parser)
+{
+    g_return_val_if_fail (parser != NULL, (gulong)-1);
+
+    if (!parser->text_section)
+        return (gulong)-1;
+
+    return parser->text_section->offset;
+}
+
+static gchar *
+make_hex_string (const guchar *data, int n_bytes)
+{
+    static const char hex_digits[] = {
+        '0', '1', '2', '3', '4', '5', '6', '7',
+        '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+    };
+    GString *string = g_string_new (NULL);
+    int i;
+
+    for (i = 0; i < n_bytes; ++i)
+    {
+        char c = data[i];
+
+        g_string_append_c (string, hex_digits[(c & 0xf0) >> 4]);
+        g_string_append_c (string, hex_digits[(c & 0x0f)]);
+    }
+
+    return g_string_free (string, FALSE);
+}
+
+const gchar *
+elf_parser_get_build_id (ElfParser *parser)
+{
+    if (!parser->checked_build_id)
+    {
+        const Section *build_id =
+            find_section (parser, ".note.gnu.build-id", SHT_NOTE);
+        guint64 name_size;
+        guint64 desc_size;
+        guint64 type;
+        const char *name;
+        guint64 offset;
+
+        parser->checked_build_id = TRUE;
+
+        if (!build_id)
+            return NULL;
+
+        offset = build_id->offset;
+
+        name_size = GET_FIELD (parser, offset, Nhdr, 0, n_namesz);
+        desc_size = GET_FIELD (parser, offset, Nhdr, 0, n_descsz);
+        type      = GET_FIELD (parser, offset, Nhdr, 0, n_type);
+
+        offset += GET_SIZE (parser, Nhdr);
+
+        name = (char *)(parser->data + offset);
+
+        if (strncmp (name, ELF_NOTE_GNU, name_size) != 0 || type != NT_GNU_BUILD_ID)
+            return NULL;
+
+        offset += strlen (name);
+
+        offset = (offset + 3) & (~0x3);
+
+        parser->build_id = make_hex_string (parser->data + offset, desc_size);
+    }
+
+    return parser->build_id;
+}
+
+const char *
+elf_parser_get_debug_link (ElfParser *parser, guint32 *crc32)
+{
+    guint64 offset;
+    const Section *debug_link = find_section (parser, ".gnu_debuglink",
+                                              SHT_PROGBITS);
+    const gchar *result;
+
+    if (!debug_link)
+        return NULL;
+
+    offset = debug_link->offset;
+
+    result = (char *)(parser->data + offset);
+
+    if (crc32)
+    {
+        int len = strlen (result) + 1;
+        offset = (offset + len + 3) & ~0x3;
+
+        *crc32 = GET_UINT32 (parser, offset);
+    }
+
+    return result;
+}
+
+static const guchar *
+get_section (ElfParser *parser,
+             const char *name)
+{
+    const Section *section = find_section (parser, name, SHT_PROGBITS);
+
+    if (section)
+        return parser->data + section->offset;
+    else
+        return NULL;
+}
+
+const guchar *
+elf_parser_get_eh_frame   (ElfParser   *parser)
+{
+    return get_section (parser, ".eh_frame");
+}
+
+const guchar *
+elf_parser_get_debug_frame   (ElfParser   *parser)
+{
+    return get_section (parser, ".debug_frame");
+}
+
+const char *
+elf_parser_get_sym_name (ElfParser *parser,
+                         const ElfSym *sym)
+{
+    g_return_val_if_fail (parser != NULL, NULL);
+
+    return (char *)(parser->data + parser->sym_strings +
+                    st_name (parser, sym->table, sym->offset));
+}
+
+gboolean
+elf_parser_owns_symbol (ElfParser *parser,
+                        const ElfSym *sym)
+{
+    ElfSym *first, *last;
+
+    if (!parser->n_symbols)
+        return FALSE;
+
+    first = parser->symbols;
+    last = parser->symbols + parser->n_symbols - 1;
+
+    return first <= sym && sym <= last;
+}
+
+gulong
+elf_parser_get_sym_address (ElfParser *parser,
+                            const ElfSym *sym)
+{
+    return sym->address - parser->text_section->load_address;
+}
+
+/*
+ * Utility functions
+ */
diff --git a/lib/elfparser.h b/lib/util/elfparser.h
similarity index 100%
rename from lib/elfparser.h
rename to lib/util/elfparser.h
diff --git a/lib/stackstash.c b/lib/util/stackstash.c
similarity index 61%
rename from lib/stackstash.c
rename to lib/util/stackstash.c
index 44912e4..9b33359 100644
--- a/lib/stackstash.c
+++ b/lib/util/stackstash.c
@@ -21,41 +21,41 @@
 
 struct StackStash
 {
-    int                        ref_count;
-    StackNode *                root;
-    GHashTable *       nodes_by_data;
-    GDestroyNotify     destroy;
+    int                 ref_count;
+    StackNode *         root;
+    GHashTable *        nodes_by_data;
+    GDestroyNotify      destroy;
 
-    StackNode *                cached_nodes;
-    GPtrArray *                blocks;
+    StackNode *         cached_nodes;
+    GPtrArray *         blocks;
 };
 
 static void
 decorate_node (StackNode *node,
-              StackStash *stash)
+               StackStash *stash)
 {
     StackNode *n;
 
     if (!node)
-       return;
+        return;
 
     decorate_node (node->siblings, stash);
     decorate_node (node->children, stash);
 
     node->next = g_hash_table_lookup (stash->nodes_by_data, &node->data);
     g_hash_table_insert (stash->nodes_by_data, &node->data, node);
-       
+
     /* FIXME: This could be done more efficiently
      * by keeping track of the ancestors we have seen.
      */
     node->toplevel = TRUE;
     for (n = node->parent; n != NULL; n = n->parent)
     {
-       if (n->data == node->data)
-       {
-           node->toplevel = FALSE;
-           break;
-       }
+        if (n->data == node->data)
+        {
+            node->toplevel = FALSE;
+            break;
+        }
     }
 }
 
@@ -80,7 +80,7 @@ static void
 stack_stash_decorate (StackStash *stash)
 {
     if (stash->nodes_by_data)
-       return;
+        return;
 
     stash->nodes_by_data = g_hash_table_new (address_hash, address_equal);
 
@@ -89,8 +89,8 @@ stack_stash_decorate (StackStash *stash)
 
 static void
 free_key (gpointer key,
-         gpointer value,
-         gpointer data)
+          gpointer value,
+          gpointer data)
 {
     GDestroyNotify destroy = data;
     uint64_t u64 = *(uint64_t *)key;
@@ -103,14 +103,14 @@ stack_stash_undecorate (StackStash *stash)
 {
     if (stash->nodes_by_data)
     {
-       if (stash->destroy)
-       {
-           g_hash_table_foreach (
-               stash->nodes_by_data, free_key, stash->destroy);
-       }
-       
-       g_hash_table_destroy (stash->nodes_by_data);
-       stash->nodes_by_data = NULL;
+        if (stash->destroy)
+        {
+            g_hash_table_foreach (
+                stash->nodes_by_data, free_key, stash->destroy);
+        }
+
+        g_hash_table_destroy (stash->nodes_by_data);
+        stash->nodes_by_data = NULL;
     }
 }
 
@@ -118,7 +118,7 @@ static GHashTable *
 get_nodes_by_data (StackStash *stash)
 {
     if (!stash->nodes_by_data)
-       stack_stash_decorate (stash);
+        stack_stash_decorate (stash);
 
     return stash->nodes_by_data;
 }
@@ -133,16 +133,16 @@ stack_node_new (StackStash *stash)
 #define BLOCK_SIZE 32768
 #define N_NODES (BLOCK_SIZE / sizeof (StackNode))
 
-       StackNode *block = g_malloc (BLOCK_SIZE);
-       int i;
+        StackNode *block = g_malloc (BLOCK_SIZE);
+        guint i;
 
-       for (i = 0; i < N_NODES; ++i)
-       {
-           block[i].next = stash->cached_nodes;
-           stash->cached_nodes = &(block[i]);
-       }
+        for (i = 0; i < N_NODES; ++i)
+        {
+            block[i].next = stash->cached_nodes;
+            stash->cached_nodes = &(block[i]);
+        }
 
-       g_ptr_array_add (stash->blocks, block);
+        g_ptr_array_add (stash->blocks, block);
     }
 
     node = stash->cached_nodes;
@@ -155,7 +155,7 @@ stack_node_new (StackStash *stash)
     node->size = 0;
     node->next = NULL;
     node->total = 0;
-    
+
     return node;
 }
 
@@ -169,7 +169,7 @@ create_stack_stash (GDestroyNotify destroy)
     stash->nodes_by_data = NULL;
     stash->ref_count = 1;
     stash->destroy = destroy;
-    
+
     stash->cached_nodes = NULL;
     stash->blocks = g_ptr_array_new ();
 
@@ -187,76 +187,76 @@ stack_stash_new (GDestroyNotify destroy)
 static void
 stack_stash_free (StackStash *stash)
 {
-    int i;
-    
+    guint i;
+
     stack_stash_undecorate (stash);
 
     for (i = 0; i < stash->blocks->len; ++i)
-       g_free (stash->blocks->pdata[i]);
-    
+        g_free (stash->blocks->pdata[i]);
+
     g_ptr_array_free (stash->blocks, TRUE);
-    
+
     g_free (stash);
 }
 
 StackNode *
-stack_stash_add_trace (StackStash *stash,
-                      uint64_t   *addrs,
-                      int         n_addrs,
-                      int         size)
+stack_stash_add_trace (StackStash     *stash,
+                       const uint64_t *addrs,
+                       int             n_addrs,
+                       int             size)
 {
     StackNode **location = &(stash->root);
     StackNode *parent = NULL;
     int i;
 
     if (!n_addrs)
-       return NULL;
+        return NULL;
 
     if (stash->nodes_by_data)
-       stack_stash_undecorate (stash);
-    
+        stack_stash_undecorate (stash);
+
     for (i = n_addrs - 1; i >= 0; --i)
     {
-       StackNode *match = NULL;
-       StackNode *prev;
-
-       /* FIXME: On x86-64 we don't get proper stacktraces which means
-        * each node can have tons of children. That makes this loop
-        * here show up on profiles.
-        *
-        * Not sure what can be done about it aside from actually fixing
-        * x86-64 to get stacktraces.
-        */
-       prev = NULL;
-       for (match = *location; match; prev = match, match = match->siblings)
-       {
-           if (match->data == addrs[i])
-           {
-               if (prev)
-               {
-                   /* move to front */
-                   prev->siblings = match->siblings;
-                   match->siblings = *location;
-                   *location = match;
-               }
-               
-               break;
-           }
-       }
-
-       if (!match)
-       {
-           match = stack_node_new (stash);
-           match->data = addrs[i];
-           match->siblings = *location;
-           match->parent = parent;
-           *location = match;
-       }
-
-       match->total += size;
-
-       location = &(match->children);
-       parent = match;
+        StackNode *match = NULL;
+        StackNode *prev;
+
+        /* FIXME: On x86-64 we don't get proper stacktraces which means
+         * each node can have tons of children. That makes this loop
+         * here show up on profiles.
+         *
+         * Not sure what can be done about it aside from actually fixing
+         * x86-64 to get stacktraces.
+         */
+        prev = NULL;
+        for (match = *location; match; prev = match, match = match->siblings)
+        {
+            if (match->data == addrs[i])
+            {
+                if (prev)
+                {
+                    /* move to front */
+                    prev->siblings = match->siblings;
+                    match->siblings = *location;
+                    *location = match;
+                }
+
+                break;
+            }
+        }
+
+        if (!match)
+        {
+            match = stack_node_new (stash);
+            match->data = addrs[i];
+            match->siblings = *location;
+            match->parent = parent;
+            *location = match;
+        }
+
+        match->total += size;
+
+        location = &(match->children);
+        parent = match;
     }
 
     parent->size += size;
@@ -266,46 +266,46 @@ stack_stash_add_trace (StackStash *stash,
 
 static void
 do_callback (StackNode *node,
-            StackLink *trace,
-            StackFunction func,
-            gpointer data)
+             StackLink *trace,
+             StackFunction func,
+             gpointer data)
 {
     StackLink link;
 
     if (trace)
-       trace->prev = &link;
-       
+        trace->prev = &link;
+
     link.next = trace;
     link.prev = NULL;
-    
+
     while (node)
     {
-       link.data = node->data;
-       
-       if (node->size)
-           func (&link, node->size, data);
-       
-       do_callback (node->children, &link, func, data);
-       
-       node = node->siblings;
+        link.data = node->data;
+
+        if (node->size)
+            func (&link, node->size, data);
+
+        do_callback (node->children, &link, func, data);
+
+        node = node->siblings;
     }
 
     if (trace)
-       trace->prev = NULL;
+        trace->prev = NULL;
 }
 
 void
 stack_stash_foreach (StackStash      *stash,
-                    StackFunction    stack_func,
-                    gpointer         data)
+                     StackFunction    stack_func,
+                     gpointer         data)
 {
     do_callback (stash->root, NULL, stack_func, data);
 }
 
 void
 stack_node_foreach_trace (StackNode     *node,
-                         StackFunction  func,
-                         gpointer       data)
+                          StackFunction  func,
+                          gpointer       data)
 {
     StackLink link;
 
@@ -314,8 +314,8 @@ stack_node_foreach_trace (StackNode     *node,
     link.prev = NULL;
 
     if (node->size)
-       func (&link, node->size, data);
-    
+        func (&link, node->size, data);
+
     do_callback (node->children, &link, func, data);
 }
 
@@ -324,7 +324,7 @@ stack_stash_unref (StackStash *stash)
 {
     stash->ref_count--;
     if (stash->ref_count == 0)
-       stack_stash_free (stash);
+        stack_stash_free (stash);
 }
 
 StackStash *
@@ -336,19 +336,19 @@ stack_stash_ref (StackStash *stash)
 
 StackNode *
 stack_stash_find_node (StackStash      *stash,
-                      gpointer         data)
+                       gpointer         data)
 {
     uint64_t u64 = POINTER_TO_U64 (data);
-    
+
     g_return_val_if_fail (stash != NULL, NULL);
-    
+
     return g_hash_table_lookup (get_nodes_by_data (stash), &u64);
 }
 
 typedef struct
 {
     StackNodeFunc func;
-    gpointer     data;
+    gpointer      data;
 } Info;
 
 static void
@@ -361,13 +361,13 @@ do_foreach (gpointer key, gpointer value, gpointer data)
 
 void
 stack_stash_foreach_by_address (StackStash *stash,
-                               StackNodeFunc func,
-                               gpointer      data)
+                                StackNodeFunc func,
+                                gpointer      data)
 {
     Info info;
     info.func = func;
     info.data = data;
-       
+
     g_hash_table_foreach (get_nodes_by_data (stash), do_foreach, &info);
 }
 
@@ -379,9 +379,9 @@ stack_stash_get_root (StackStash *stash)
 
 void
 stack_stash_set_root (StackStash     *stash,
-                     StackNode      *root)
+                      StackNode      *root)
 {
     g_return_if_fail (stash->root == NULL);
-    
+
     stash->root = root;
 }
diff --git a/lib/stackstash.h b/lib/util/stackstash.h
similarity index 56%
rename from lib/stackstash.h
rename to lib/util/stackstash.h
index 4fad001..9d2909b 100644
--- a/lib/stackstash.h
+++ b/lib/util/stackstash.h
@@ -27,60 +27,59 @@ typedef struct StackStash StackStash;
 typedef struct StackNode StackNode;
 typedef struct StackLink StackLink;
 
-#define U64_TO_POINTER(u)      ((void *)(intptr_t)u)
-#define POINTER_TO_U64(p)      ((uint64_t)(intptr_t)p)
+#define U64_TO_POINTER(u)       ((void *)(intptr_t)u)
+#define POINTER_TO_U64(p)       ((uint64_t)(intptr_t)p)
 
 struct StackNode
 {
-    uint64_t   data;
+    uint64_t    data;
 
-    guint      total : 32;
-    guint      size : 31;
-    guint      toplevel : 1;
-    
-    StackNode *        parent;
-    StackNode *        siblings;
-    StackNode *        children;
+    guint       total : 32;
+    guint       size : 31;
+    guint       toplevel : 1;
+
+    StackNode * parent;
+    StackNode * siblings;
+    StackNode * children;
 
     StackNode * next;
 };
 
 struct StackLink
 {
-    uint64_t   data;
+    uint64_t    data;
     StackLink  *next;
     StackLink  *prev;
 };
 
 typedef void (* StackFunction) (StackLink *trace,
-                               gint       size,
-                               gpointer   data);
+                                gint       size,
+                                gpointer   data);
 
 typedef void (* StackNodeFunc) (StackNode *node,
-                               gpointer   data);
+                                gpointer   data);
 
-/* Stach */
 StackStash *stack_stash_new                (GDestroyNotify  destroy);
-StackNode * stack_node_new                 (StackStash     *stash);
-StackNode * stack_stash_add_trace          (StackStash     *stash,
-                                           uint64_t       *addrs,
-                                           gint            n_addrs,
-                                           int             size);
+StackNode  *stack_node_new                 (StackStash     *stash);
+StackNode  *stack_stash_add_trace          (StackStash     *stash,
+                                            const uint64_t *addrs,
+                                            gint            n_addrs,
+                                            int             size);
 void        stack_stash_foreach            (StackStash     *stash,
-                                           StackFunction   stack_func,
-                                           gpointer        data);
+                                            StackFunction   stack_func,
+                                            gpointer        data);
 void        stack_node_foreach_trace       (StackNode      *node,
-                                           StackFunction   stack_func,
-                                           gpointer        data);
+                                            StackFunction   stack_func,
+                                            gpointer        data);
 StackNode  *stack_stash_find_node          (StackStash     *stash,
-                                           gpointer        address);
+                                            gpointer        address);
 void        stack_stash_foreach_by_address (StackStash     *stash,
-                                           StackNodeFunc   func,
-                                           gpointer        data);
+                                            StackNodeFunc   func,
+                                            gpointer        data);
 StackNode  *stack_stash_get_root           (StackStash     *stash);
 StackStash *stack_stash_ref                (StackStash     *stash);
 void        stack_stash_unref              (StackStash     *stash);
-void       stack_stash_set_root           (StackStash     *stash,
-                                           StackNode      *root);
+void        stack_stash_set_root           (StackStash     *stash,
+                                            StackNode      *root);
 
 #endif
diff --git a/lib/util/util.h b/lib/util/util.h
new file mode 100644
index 0000000..591722d
--- /dev/null
+++ b/lib/util/util.h
@@ -0,0 +1,32 @@
+#ifndef SP_UTIL_H
+#define SP_UTIL_H
+
+#if defined(__i386__)
+#define read_barrier()           asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
+#endif
+
+#if defined(__x86_64__)
+#define read_barrier()           asm volatile("lfence" ::: "memory")
+#endif
+
+#ifdef __powerpc__
+#define read_barrier()           asm volatile ("sync" ::: "memory")
+#endif
+
+#ifdef __s390__
+#define read_barrier()           asm volatile("bcr 15,0" ::: "memory")
+#endif
+
+#ifdef __sh__
+#if defined(__SH4A__) || defined(__SH5__)
+# define read_barrier()          asm volatile("synco" ::: "memory")
+#else
+# define read_barrier()          asm volatile("" ::: "memory")
+#endif
+#endif
+
+#ifdef __hppa__
+#define read_barrier()           asm volatile("" ::: "memory")
+#endif
+
+#endif /* SP_UTIL_H */
diff --git a/m4/Makefile.am b/m4/Makefile.am
new file mode 100644
index 0000000..ae44c94
--- /dev/null
+++ b/m4/Makefile.am
@@ -0,0 +1 @@
+-include $(top_srcdir)/git.mk
diff --git a/m4/appstream-xml.m4 b/m4/appstream-xml.m4
new file mode 100644
index 0000000..1472802
--- /dev/null
+++ b/m4/appstream-xml.m4
@@ -0,0 +1,86 @@
+# appstream-xml.m4
+#
+# serial 6
+
+dnl APPSTREAM_XML
+dnl Installs and validates AppData XML files.
+dnl
+dnl Call APPSTREAM_XML in configure.ac to check for the appstream-util tool.
+dnl Add @APPSTREAM_XML_RULES@ to a Makefile.am to substitute the make rules. Add
+dnl .appdata.xml files to appstream_XML in Makefile.am and they will be validated
+dnl at make check time, if appstream-util is installed, as well as installed
+dnl to the correct location automatically. Add --enable-appstream-util to
+dnl DISTCHECK_CONFIGURE_FLAGS in Makefile.am to require valid AppData XML when
+dnl doing a distcheck.
+dnl
+dnl Adding files to appstream_XML does not distribute them automatically.
+
+AC_DEFUN([APPSTREAM_XML],
+[
+  m4_pattern_allow([AM_V_GEN])
+  AC_ARG_ENABLE([appstream-util],
+                [AS_HELP_STRING([--disable-appstream-util],
+                                [Disable validating AppData XML files during check phase])])
+
+  AS_IF([test "x$enable_appstream_validate" != "xno"],
+        [AC_PATH_PROG([APPSTREAM_UTIL], [appstream-util])
+         AS_IF([test "x$APPSTREAM_UTIL" = "x"],
+               [have_appstream_validate=no],
+               [have_appstream_validate=yes
+                AC_SUBST([APPSTREAM_UTIL])])],
+        [have_appstream_validate=no])
+
+  AS_IF([test "x$have_appstream_validate" != "xno"],
+        [appstream_validate=yes],
+        [appstream_validate=no
+         AS_IF([test "x$enable_appstream_validate" = "xyes"],
+               [AC_MSG_ERROR([AppData validation was requested but appstream-util was not found])])])
+
+  AC_SUBST([appstreamxmldir], [${datadir}/appdata])
+
+  APPSTREAM_XML_RULES='
+.PHONY : uninstall-appstream-xml install-appstream-xml clean-appstream-xml
+
+mostlyclean-am: clean-appstream-xml
+
+%.appdata.valid: %.appdata.xml
+       $(AM_V_GEN) if test -f "$<"; then d=; else d="$(srcdir)/"; fi; \
+               if test -n "$(APPSTREAM_UTIL)"; \
+                       then $(APPSTREAM_UTIL) --nonet validate $${d}$<; fi \
+               && touch [$]@
+
+check-am: $(appstream_XML:.appdata.xml=.appdata.valid)
+uninstall-am: uninstall-appstream-xml
+install-data-am: install-appstream-xml
+
+.SECONDARY: $(appstream_XML)
+
+install-appstream-xml: $(appstream_XML)
+       @$(NORMAL_INSTALL)
+       if test -n "$^"; then \
+               test -z "$(appstreamxmldir)" || $(MKDIR_P) "$(DESTDIR)$(appstreamxmldir)"; \
+               $(INSTALL_DATA) $^ "$(DESTDIR)$(appstreamxmldir)"; \
+       fi
+
+uninstall-appstream-xml:
+       @$(NORMAL_UNINSTALL)
+       @list='\''$(appstream_XML)'\''; test -n "$(appstreamxmldir)" || list=; \
+       files=`for p in $$list; do echo $$p; done | sed -e '\''s|^.*/||'\''`; \
+       test -n "$$files" || exit 0; \
+       echo " ( cd '\''$(DESTDIR)$(appstreamxmldir)'\'' && rm -f" $$files ")"; \
+       cd "$(DESTDIR)$(appstreamxmldir)" && rm -f $$files
+
+clean-appstream-xml:
+       rm -f $(appstream_XML:.appdata.xml=.appdata.valid)
+'
+  _APPSTREAM_XML_SUBST(APPSTREAM_XML_RULES)
+])
+
+dnl _APPSTREAM_XML_SUBST(VARIABLE)
+dnl Abstract macro to do either _AM_SUBST_NOTMAKE or AC_SUBST
+AC_DEFUN([_APPSTREAM_XML_SUBST],
+[
+AC_SUBST([$1])
+m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([$1])])
+]
+)
diff --git a/m4/ax_append_compile_flags.m4 b/m4/ax_append_compile_flags.m4
new file mode 100644
index 0000000..2bb27ef
--- /dev/null
+++ b/m4/ax_append_compile_flags.m4
@@ -0,0 +1,67 @@
+# ===========================================================================
+#  http://www.gnu.org/software/autoconf-archive/ax_append_compile_flags.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_APPEND_COMPILE_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+#   For every FLAG1, FLAG2 it is checked whether the compiler works with the
+#   flag.  If it does, the flag is added FLAGS-VARIABLE
+#
+#   If FLAGS-VARIABLE is not specified, the current language's flags (e.g.
+#   CFLAGS) is used.  During the check the flag is always added to the
+#   current language's flags.
+#
+#   If EXTRA-FLAGS is defined, it is added to the current language's default
+#   flags (e.g. CFLAGS) when the check is done.  The check is thus made with
+#   the flags: "CFLAGS EXTRA-FLAGS FLAG".  This can for example be used to
+#   force the compiler to issue an error when a bad flag is given.
+#
+#   INPUT gives an alternative input source to AC_COMPILE_IFELSE.
+#
+#   NOTE: This macro depends on the AX_APPEND_FLAG and
+#   AX_CHECK_COMPILE_FLAG. Please keep this macro in sync with
+#   AX_APPEND_LINK_FLAGS.
+#
+# LICENSE
+#
+#   Copyright (c) 2011 Maarten Bosmans <mkbosmans gmail com>
+#
+#   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/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 5
+
+AC_DEFUN([AX_APPEND_COMPILE_FLAGS],
+[AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG])
+AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
+for flag in $1; do
+  AX_CHECK_COMPILE_FLAG([$flag], [AX_APPEND_FLAG([$flag], [$2])], [], [$3], [$4])
+done
+])dnl AX_APPEND_COMPILE_FLAGS
diff --git a/m4/ax_append_flag.m4 b/m4/ax_append_flag.m4
new file mode 100644
index 0000000..08f2e07
--- /dev/null
+++ b/m4/ax_append_flag.m4
@@ -0,0 +1,71 @@
+# ===========================================================================
+#      http://www.gnu.org/software/autoconf-archive/ax_append_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE])
+#
+# DESCRIPTION
+#
+#   FLAG is appended to the FLAGS-VARIABLE shell variable, with a space
+#   added in between.
+#
+#   If FLAGS-VARIABLE is not specified, the current language's flags (e.g.
+#   CFLAGS) is used.  FLAGS-VARIABLE is not changed if it already contains
+#   FLAG.  If FLAGS-VARIABLE is unset in the shell, it is set to exactly
+#   FLAG.
+#
+#   NOTE: Implementation based on AX_CFLAGS_GCC_OPTION.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Guido U. Draheim <guidod gmx de>
+#   Copyright (c) 2011 Maarten Bosmans <mkbosmans gmail com>
+#
+#   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/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 6
+
+AC_DEFUN([AX_APPEND_FLAG],
+[dnl
+AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF
+AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])
+AS_VAR_SET_IF(FLAGS,[
+  AS_CASE([" AS_VAR_GET(FLAGS) "],
+    [*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])],
+    [
+     AS_VAR_APPEND(FLAGS,[" $1"])
+     AC_RUN_LOG([: FLAGS="$FLAGS"])
+    ])
+  ],
+  [
+  AS_VAR_SET(FLAGS,[$1])
+  AC_RUN_LOG([: FLAGS="$FLAGS"])
+  ])
+AS_VAR_POPDEF([FLAGS])dnl
+])dnl AX_APPEND_FLAG
diff --git a/m4/ax_append_link_flags.m4 b/m4/ax_append_link_flags.m4
new file mode 100644
index 0000000..fd70fc7
--- /dev/null
+++ b/m4/ax_append_link_flags.m4
@@ -0,0 +1,65 @@
+# ===========================================================================
+#   http://www.gnu.org/software/autoconf-archive/ax_append_link_flags.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_APPEND_LINK_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+#   For every FLAG1, FLAG2 it is checked whether the linker works with the
+#   flag.  If it does, the flag is added FLAGS-VARIABLE
+#
+#   If FLAGS-VARIABLE is not specified, the linker's flags (LDFLAGS) is
+#   used. During the check the flag is always added to the linker's flags.
+#
+#   If EXTRA-FLAGS is defined, it is added to the linker's default flags
+#   when the check is done.  The check is thus made with the flags: "LDFLAGS
+#   EXTRA-FLAGS FLAG".  This can for example be used to force the linker to
+#   issue an error when a bad flag is given.
+#
+#   INPUT gives an alternative input source to AC_COMPILE_IFELSE.
+#
+#   NOTE: This macro depends on the AX_APPEND_FLAG and AX_CHECK_LINK_FLAG.
+#   Please keep this macro in sync with AX_APPEND_COMPILE_FLAGS.
+#
+# LICENSE
+#
+#   Copyright (c) 2011 Maarten Bosmans <mkbosmans gmail com>
+#
+#   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/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 5
+
+AC_DEFUN([AX_APPEND_LINK_FLAGS],
+[AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
+AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
+for flag in $1; do
+  AX_CHECK_LINK_FLAG([$flag], [AX_APPEND_FLAG([$flag], [m4_default([$2], [LDFLAGS])])], [], [$3], [$4])
+done
+])dnl AX_APPEND_LINK_FLAGS
diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4
new file mode 100644
index 0000000..ca36397
--- /dev/null
+++ b/m4/ax_check_compile_flag.m4
@@ -0,0 +1,74 @@
+# ===========================================================================
+#   http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+#   Check whether the given FLAG works with the current language's compiler
+#   or gives an error.  (Warnings, however, are ignored)
+#
+#   ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+#   success/failure.
+#
+#   If EXTRA-FLAGS is defined, it is added to the current language's default
+#   flags (e.g. CFLAGS) when the check is done.  The check is thus made with
+#   the flags: "CFLAGS EXTRA-FLAGS FLAG".  This can for example be used to
+#   force the compiler to issue an error when a bad flag is given.
+#
+#   INPUT gives an alternative input source to AC_COMPILE_IFELSE.
+#
+#   NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+#   macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Guido U. Draheim <guidod gmx de>
+#   Copyright (c) 2011 Maarten Bosmans <mkbosmans gmail com>
+#
+#   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/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 4
+
+AC_DEFUN([AX_CHECK_COMPILE_FLAG],
+[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
+AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
+  ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
+  _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
+  AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
+    [AS_VAR_SET(CACHEVAR,[yes])],
+    [AS_VAR_SET(CACHEVAR,[no])])
+  _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
+AS_VAR_IF(CACHEVAR,yes,
+  [m4_default([$2], :)],
+  [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_COMPILE_FLAGS
diff --git a/m4/ax_check_enable_debug.m4 b/m4/ax_check_enable_debug.m4
new file mode 100644
index 0000000..f99d75f
--- /dev/null
+++ b/m4/ax_check_enable_debug.m4
@@ -0,0 +1,124 @@
+# ===========================================================================
+#   http://www.gnu.org/software/autoconf-archive/ax_check_enable_debug.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CHECK_ENABLE_DEBUG([enable by default=yes/info/profile/no], [ENABLE DEBUG VARIABLES ...], [DISABLE 
DEBUG VARIABLES NDEBUG ...], [IS-RELEASE])
+#
+# DESCRIPTION
+#
+#   Check for the presence of an --enable-debug option to configure, with
+#   the specified default value used when the option is not present.  Return
+#   the value in the variable $ax_enable_debug.
+#
+#   Specifying 'yes' adds '-g -O0' to the compilation flags for all
+#   languages. Specifying 'info' adds '-g' to the compilation flags.
+#   Specifying 'profile' adds '-g -pg' to the compilation flags and '-pg' to
+#   the linking flags. Otherwise, nothing is added.
+#
+#   Define the variables listed in the second argument if debug is enabled,
+#   defaulting to no variables.  Defines the variables listed in the third
+#   argument if debug is disabled, defaulting to NDEBUG.  All lists of
+#   variables should be space-separated.
+#
+#   If debug is not enabled, ensure AC_PROG_* will not add debugging flags.
+#   Should be invoked prior to any AC_PROG_* compiler checks.
+#
+#   IS-RELEASE can be used to change the default to 'no' when making a
+#   release.  Set IS-RELEASE to 'yes' or 'no' as appropriate. By default, it
+#   uses the value of $ax_is_release, so if you are using the AX_IS_RELEASE
+#   macro, there is no need to pass this parameter.
+#
+#     AX_IS_RELEASE([git-directory])
+#     AX_CHECK_ENABLE_DEBUG()
+#
+# LICENSE
+#
+#   Copyright (c) 2011 Rhys Ulerich <rhys ulerich gmail com>
+#   Copyright (c) 2014, 2015 Philip Withnall <philip tecnocode co uk>
+#
+#   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.
+
+#serial 5
+
+AC_DEFUN([AX_CHECK_ENABLE_DEBUG],[
+    AC_BEFORE([$0],[AC_PROG_CC])dnl
+    AC_BEFORE([$0],[AC_PROG_CXX])dnl
+    AC_BEFORE([$0],[AC_PROG_F77])dnl
+    AC_BEFORE([$0],[AC_PROG_FC])dnl
+
+    AC_MSG_CHECKING(whether to enable debugging)
+
+    ax_enable_debug_default=m4_tolower(m4_normalize(ifelse([$1],,[no],[$1])))
+    ax_enable_debug_is_release=m4_tolower(m4_normalize(ifelse([$4],,
+                                                              [$ax_is_release],
+                                                              [$4])))
+
+    # If this is a release, override the default.
+    AS_IF([test "$ax_enable_debug_is_release" = "yes"],
+      [ax_enable_debug_default="no"])
+
+    m4_define(ax_enable_debug_vars,[m4_normalize(ifelse([$2],,,[$2]))])
+    m4_define(ax_disable_debug_vars,[m4_normalize(ifelse([$3],,[NDEBUG],[$3]))])
+
+    AC_ARG_ENABLE(debug,
+       [AS_HELP_STRING([--enable-debug=]@<:@yes/info/profile/no@:>@,[compile with debugging])],
+       [],enable_debug=$ax_enable_debug_default)
+
+    # empty mean debug yes
+    AS_IF([test "x$enable_debug" = "x"],
+      [enable_debug="yes"])
+
+    # case of debug
+    AS_CASE([$enable_debug],
+      [yes],[
+       AC_MSG_RESULT(yes)
+       CFLAGS="${CFLAGS} -g -O0"
+       CXXFLAGS="${CXXFLAGS} -g -O0"
+       FFLAGS="${FFLAGS} -g -O0"
+       FCFLAGS="${FCFLAGS} -g -O0"
+       OBJCFLAGS="${OBJCFLAGS} -g -O0"
+      ],
+      [info],[
+       AC_MSG_RESULT(info)
+       CFLAGS="${CFLAGS} -g"
+       CXXFLAGS="${CXXFLAGS} -g"
+       FFLAGS="${FFLAGS} -g"
+       FCFLAGS="${FCFLAGS} -g"
+       OBJCFLAGS="${OBJCFLAGS} -g"
+      ],
+      [profile],[
+       AC_MSG_RESULT(profile)
+       CFLAGS="${CFLAGS} -g -pg"
+       CXXFLAGS="${CXXFLAGS} -g -pg"
+       FFLAGS="${FFLAGS} -g -pg"
+       FCFLAGS="${FCFLAGS} -g -pg"
+       OBJCFLAGS="${OBJCFLAGS} -g -pg"
+       LDFLAGS="${LDFLAGS} -pg"
+      ],
+      [
+       AC_MSG_RESULT(no)
+       dnl Ensure AC_PROG_CC/CXX/F77/FC/OBJC will not enable debug flags
+       dnl by setting any unset environment flag variables
+       AS_IF([test "x${CFLAGS+set}" != "xset"],
+         [CFLAGS=""])
+       AS_IF([test "x${CXXFLAGS+set}" != "xset"],
+         [CXXFLAGS=""])
+       AS_IF([test "x${FFLAGS+set}" != "xset"],
+         [FFLAGS=""])
+       AS_IF([test "x${FCFLAGS+set}" != "xset"],
+         [FCFLAGS=""])
+       AS_IF([test "x${OBJCFLAGS+set}" != "xset"],
+         [OBJCFLAGS=""])
+      ])
+
+    dnl Define various variables if debugging is disabled.
+    dnl assert.h is a NOP if NDEBUG is defined, so define it by default.
+    AS_IF([test "x$enable_debug" = "xyes"],
+      [m4_map_args_w(ax_enable_debug_vars, [AC_DEFINE(], [,,[Define if debugging is enabled])])],
+      [m4_map_args_w(ax_disable_debug_vars, [AC_DEFINE(], [,,[Define if debugging is disabled])])])
+    ax_enable_debug=$enable_debug
+])
diff --git a/m4/ax_check_link_flag.m4 b/m4/ax_check_link_flag.m4
new file mode 100644
index 0000000..eb01a6c
--- /dev/null
+++ b/m4/ax_check_link_flag.m4
@@ -0,0 +1,74 @@
+# ===========================================================================
+#    http://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+#   Check whether the given FLAG works with the linker or gives an error.
+#   (Warnings, however, are ignored)
+#
+#   ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+#   success/failure.
+#
+#   If EXTRA-FLAGS is defined, it is added to the linker's default flags
+#   when the check is done.  The check is thus made with the flags: "LDFLAGS
+#   EXTRA-FLAGS FLAG".  This can for example be used to force the linker to
+#   issue an error when a bad flag is given.
+#
+#   INPUT gives an alternative input source to AC_LINK_IFELSE.
+#
+#   NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+#   macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Guido U. Draheim <guidod gmx de>
+#   Copyright (c) 2011 Maarten Bosmans <mkbosmans gmail com>
+#
+#   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/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 4
+
+AC_DEFUN([AX_CHECK_LINK_FLAG],
+[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl
+AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [
+  ax_check_save_flags=$LDFLAGS
+  LDFLAGS="$LDFLAGS $4 $1"
+  AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
+    [AS_VAR_SET(CACHEVAR,[yes])],
+    [AS_VAR_SET(CACHEVAR,[no])])
+  LDFLAGS=$ax_check_save_flags])
+AS_VAR_IF(CACHEVAR,yes,
+  [m4_default([$2], :)],
+  [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_LINK_FLAGS
diff --git a/m4/ax_compiler_flags.m4 b/m4/ax_compiler_flags.m4
new file mode 100644
index 0000000..6cfe398
--- /dev/null
+++ b/m4/ax_compiler_flags.m4
@@ -0,0 +1,158 @@
+# ===========================================================================
+#     http://www.gnu.org/software/autoconf-archive/ax_compiler_flags.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_COMPILER_FLAGS([CFLAGS-VARIABLE], [LDFLAGS-VARIABLE], [IS-RELEASE], [EXTRA-BASE-CFLAGS], 
[EXTRA-YES-CFLAGS], [UNUSED], [UNUSED], [UNUSED], [EXTRA-BASE-LDFLAGS], [EXTRA-YES-LDFLAGS], [UNUSED], 
[UNUSED], [UNUSED])
+#
+# DESCRIPTION
+#
+#   Check for the presence of an --enable-compile-warnings option to
+#   configure, defaulting to "error" in normal operation, or "yes" if
+#   IS-RELEASE is equal to "yes".  Return the value in the variable
+#   $ax_enable_compile_warnings.
+#
+#   Depending on the value of --enable-compile-warnings, different compiler
+#   warnings are checked to see if they work with the current compiler and,
+#   if so, are appended to CFLAGS-VARIABLE and LDFLAGS-VARIABLE.  This
+#   allows a consistent set of baseline compiler warnings to be used across
+#   a code base, irrespective of any warnings enabled locally by individual
+#   developers.  By standardising the warnings used by all developers of a
+#   project, the project can commit to a zero-warnings policy, using -Werror
+#   to prevent compilation if new warnings are introduced.  This makes
+#   catching bugs which are flagged by warnings a lot easier.
+#
+#   By providing a consistent --enable-compile-warnings argument across all
+#   projects using this macro, continuous integration systems can easily be
+#   configured the same for all projects.  Automated systems or build
+#   systems aimed at beginners may want to pass the --disable-Werror
+#   argument to unconditionally prevent warnings being fatal.
+#
+#   --enable-compile-warnings can take the values:
+#
+#    * no:      Base compiler warnings only; not even -Wall.
+#    * yes:     The above, plus a broad range of useful warnings.
+#    * error:   The above, plus -Werror so that all warnings are fatal.
+#               Use --disable-Werror to override this and disable fatal
+#               warnings.
+#
+#   The set of base and enabled flags can be augmented using the
+#   EXTRA-*-CFLAGS and EXTRA-*-LDFLAGS variables, which are tested and
+#   appended to the output variable if --enable-compile-warnings is not
+#   "no". Flags should not be disabled using these arguments, as the entire
+#   point of AX_COMPILER_FLAGS is to enforce a consistent set of useful
+#   compiler warnings on code, using warnings which have been chosen for low
+#   false positive rates.  If a compiler emits false positives for a
+#   warning, a #pragma should be used in the code to disable the warning
+#   locally. See:
+#
+#     https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/Diagnostic-Pragmas.html#Diagnostic-Pragmas
+#
+#   The EXTRA-* variables should only be used to supply extra warning flags,
+#   and not general purpose compiler flags, as they are controlled by
+#   configure options such as --disable-Werror.
+#
+#   IS-RELEASE can be used to disable -Werror when making a release, which
+#   is useful for those hairy moments when you just want to get the release
+#   done as quickly as possible.  Set it to "yes" to disable -Werror. By
+#   default, it uses the value of $ax_is_release, so if you are using the
+#   AX_IS_RELEASE macro, there is no need to pass this parameter. For
+#   example:
+#
+#     AX_IS_RELEASE([git-directory])
+#     AX_COMPILER_FLAGS()
+#
+#   CFLAGS-VARIABLE defaults to WARN_CFLAGS, and LDFLAGS-VARIABLE defaults
+#   to WARN_LDFLAGS.  Both variables are AC_SUBST-ed by this macro, but must
+#   be manually added to the CFLAGS and LDFLAGS variables for each target in
+#   the code base.
+#
+#   If C++ language support is enabled with AC_PROG_CXX, which must occur
+#   before this macro in configure.ac, warning flags for the C++ compiler
+#   are AC_SUBST-ed as WARN_CXXFLAGS, and must be manually added to the
+#   CXXFLAGS variables for each target in the code base.  EXTRA-*-CFLAGS can
+#   be used to augment the base and enabled flags.
+#
+#   Warning flags for g-ir-scanner (from GObject Introspection) are
+#   AC_SUBST-ed as WARN_SCANNERFLAGS.  This variable must be manually added
+#   to the SCANNERFLAGS variable for each GIR target in the code base.  If
+#   extra g-ir-scanner flags need to be enabled, the AX_COMPILER_FLAGS_GIR
+#   macro must be invoked manually.
+#
+#   AX_COMPILER_FLAGS may add support for other tools in future, in addition
+#   to the compiler and linker.  No extra EXTRA-* variables will be added
+#   for those tools, and all extra support will still use the single
+#   --enable-compile-warnings configure option.  For finer grained control
+#   over the flags for individual tools, use AX_COMPILER_FLAGS_CFLAGS,
+#   AX_COMPILER_FLAGS_LDFLAGS and AX_COMPILER_FLAGS_* for new tools.
+#
+#   The UNUSED variables date from a previous version of this macro, and are
+#   automatically appended to the preceding non-UNUSED variable. They should
+#   be left empty in new uses of the macro.
+#
+# LICENSE
+#
+#   Copyright (c) 2014, 2015 Philip Withnall <philip tecnocode co uk>
+#   Copyright (c) 2015 David King <amigadave amigadave com>
+#
+#   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 13
+
+# _AX_COMPILER_FLAGS_LANG([LANGNAME])
+m4_defun([_AX_COMPILER_FLAGS_LANG],
+[m4_ifdef([_AX_COMPILER_FLAGS_LANG_]$1[_enabled], [],
+          [m4_define([_AX_COMPILER_FLAGS_LANG_]$1[_enabled], [])dnl
+           AX_REQUIRE_DEFINED([AX_COMPILER_FLAGS_]$1[FLAGS])])dnl
+])
+
+AC_DEFUN([AX_COMPILER_FLAGS],[
+    # C support is enabled by default.
+    _AX_COMPILER_FLAGS_LANG([C])
+    # Only enable C++ support if AC_PROG_CXX is called. The redefinition of
+    # AC_PROG_CXX is so that a fatal error is emitted if this macro is called
+    # before AC_PROG_CXX, which would otherwise cause no C++ warnings to be
+    # checked.
+    AC_PROVIDE_IFELSE([AC_PROG_CXX],
+                      [_AX_COMPILER_FLAGS_LANG([CXX])],
+                      [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[_AX_COMPILER_FLAGS_LANG([CXX])])])
+    AX_REQUIRE_DEFINED([AX_COMPILER_FLAGS_LDFLAGS])
+
+    # Default value for IS-RELEASE is $ax_is_release
+    ax_compiler_flags_is_release=m4_tolower(m4_normalize(ifelse([$3],,
+                                                                [$ax_is_release],
+                                                                [$3])))
+
+    AC_ARG_ENABLE([compile-warnings],
+                  AS_HELP_STRING([--enable-compile-warnings=@<:@no/yes/error@:>@],
+                                 [Enable compiler warnings and errors]),,
+                  [AS_IF([test "$ax_compiler_flags_is_release" = "yes"],
+                         [enable_compile_warnings="yes"],
+                         [enable_compile_warnings="error"])])
+    AC_ARG_ENABLE([Werror],
+                  AS_HELP_STRING([--disable-Werror],
+                                 [Unconditionally make all compiler warnings non-fatal]),,
+                  [enable_Werror=maybe])
+
+    # Return the user's chosen warning level
+    AS_IF([test "$enable_Werror" = "no" -a \
+                "$enable_compile_warnings" = "error"],[
+        enable_compile_warnings="yes"
+    ])
+
+    ax_enable_compile_warnings=$enable_compile_warnings
+
+    AX_COMPILER_FLAGS_CFLAGS([$1],[$ax_compiler_flags_is_release],
+                             [$4],[$5 $6 $7 $8])
+    m4_ifdef([_AX_COMPILER_FLAGS_LANG_CXX_enabled],
+             [AX_COMPILER_FLAGS_CXXFLAGS([WARN_CXXFLAGS],
+                                         [$ax_compiler_flags_is_release],
+                                         [$4],[$5 $6 $7 $8])])
+    AX_COMPILER_FLAGS_LDFLAGS([$2],[$ax_compiler_flags_is_release],
+                              [$9],[$10 $11 $12 $13])
+    AX_COMPILER_FLAGS_GIR([WARN_SCANNERFLAGS],[$ax_compiler_flags_is_release])
+])dnl AX_COMPILER_FLAGS
diff --git a/m4/ax_compiler_flags_cflags.m4 b/m4/ax_compiler_flags_cflags.m4
new file mode 100644
index 0000000..f470f8f
--- /dev/null
+++ b/m4/ax_compiler_flags_cflags.m4
@@ -0,0 +1,133 @@
+# ============================================================================
+#  http://www.gnu.org/software/autoconf-archive/ax_compiler_flags_cflags.html
+# ============================================================================
+#
+# SYNOPSIS
+#
+#   AX_COMPILER_FLAGS_CFLAGS([VARIABLE], [IS-RELEASE], [EXTRA-BASE-FLAGS], [EXTRA-YES-FLAGS])
+#
+# DESCRIPTION
+#
+#   Add warning flags for the C compiler to VARIABLE, which defaults to
+#   WARN_CFLAGS.  VARIABLE is AC_SUBST-ed by this macro, but must be
+#   manually added to the CFLAGS variable for each target in the code base.
+#
+#   This macro depends on the environment set up by AX_COMPILER_FLAGS.
+#   Specifically, it uses the value of $ax_enable_compile_warnings to decide
+#   which flags to enable.
+#
+# LICENSE
+#
+#   Copyright (c) 2014, 2015 Philip Withnall <philip tecnocode co uk>
+#
+#   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 11
+
+AC_DEFUN([AX_COMPILER_FLAGS_CFLAGS],[
+    AC_REQUIRE([AC_PROG_SED])
+    AX_REQUIRE_DEFINED([AX_APPEND_COMPILE_FLAGS])
+    AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
+    AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG])
+
+    # Variable names
+    m4_define(ax_warn_cflags_variable,
+              [m4_normalize(ifelse([$1],,[WARN_CFLAGS],[$1]))])
+
+    AC_LANG_PUSH([C])
+
+    # Always pass -Werror=unknown-warning-option to get Clang to fail on bad
+    # flags, otherwise they are always appended to the warn_cflags variable, and
+    # Clang warns on them for every compilation unit.
+    # If this is passed to GCC, it will explode, so the flag must be enabled
+    # conditionally.
+    AX_CHECK_COMPILE_FLAG([-Werror=unknown-warning-option],[
+        ax_compiler_flags_test="-Werror=unknown-warning-option"
+    ],[
+        ax_compiler_flags_test=""
+    ])
+
+    # Base flags
+    AX_APPEND_COMPILE_FLAGS([ dnl
+        -fno-strict-aliasing dnl
+        $3 dnl
+    ],ax_warn_cflags_variable,[$ax_compiler_flags_test])
+
+    AS_IF([test "$ax_enable_compile_warnings" != "no"],[
+        # "yes" flags
+        AX_APPEND_COMPILE_FLAGS([ dnl
+            -Wall dnl
+            -Wextra dnl
+            -Wundef dnl
+            -Wnested-externs dnl
+            -Wwrite-strings dnl
+            -Wpointer-arith dnl
+            -Wmissing-declarations dnl
+            -Wmissing-prototypes dnl
+            -Wstrict-prototypes dnl
+            -Wredundant-decls dnl
+            -Wno-unused-parameter dnl
+            -Wno-missing-field-initializers dnl
+            -Wdeclaration-after-statement dnl
+            -Wformat=2 dnl
+            -Wold-style-definition dnl
+            -Wcast-align dnl
+            -Wformat-nonliteral dnl
+            -Wformat-security dnl
+            -Wsign-compare dnl
+            -Wstrict-aliasing dnl
+            -Wshadow dnl
+            -Winline dnl
+            -Wpacked dnl
+            -Wmissing-format-attribute dnl
+            -Wmissing-noreturn dnl
+            -Winit-self dnl
+            -Wredundant-decls dnl
+            -Wmissing-include-dirs dnl
+            -Wunused-but-set-variable dnl
+            -Warray-bounds dnl
+            -Wimplicit-function-declaration dnl
+            -Wreturn-type dnl
+            -Wswitch-enum dnl
+            -Wswitch-default dnl
+            $4 dnl
+            $5 dnl
+            $6 dnl
+            $7 dnl
+        ],ax_warn_cflags_variable,[$ax_compiler_flags_test])
+    ])
+    AS_IF([test "$ax_enable_compile_warnings" = "error"],[
+        # "error" flags; -Werror has to be appended unconditionally because
+        # it's not possible to test for
+        #
+        # suggest-attribute=format is disabled because it gives too many false
+        # positives
+        AX_APPEND_FLAG([-Werror],ax_warn_cflags_variable)
+
+        AX_APPEND_COMPILE_FLAGS([ dnl
+            -Wno-suggest-attribute=format dnl
+        ],ax_warn_cflags_variable,[$ax_compiler_flags_test])
+    ])
+
+    # In the flags below, when disabling specific flags, always add *both*
+    # -Wno-foo and -Wno-error=foo. This fixes the situation where (for example)
+    # we enable -Werror, disable a flag, and a build bot passes CFLAGS=-Wall,
+    # which effectively turns that flag back on again as an error.
+    for flag in $ax_warn_cflags_variable; do
+        AS_CASE([$flag],
+                [-Wno-*=*],[],
+                [-Wno-*],[
+                    AX_APPEND_COMPILE_FLAGS([-Wno-error=$(AS_ECHO([$flag]) | $SED 's/^-Wno-//')],
+                                            ax_warn_cflags_variable,
+                                            [$ax_compiler_flags_test])
+                ])
+    done
+
+    AC_LANG_POP([C])
+
+    # Substitute the variables
+    AC_SUBST(ax_warn_cflags_variable)
+])dnl AX_COMPILER_FLAGS
diff --git a/m4/ax_compiler_flags_cxxflags.m4 b/m4/ax_compiler_flags_cxxflags.m4
new file mode 100644
index 0000000..2d875e8
--- /dev/null
+++ b/m4/ax_compiler_flags_cxxflags.m4
@@ -0,0 +1,129 @@
+# ==============================================================================
+#  http://www.gnu.org/software/autoconf-archive/ax_compiler_flags_cxxflags.html
+# ==============================================================================
+#
+# SYNOPSIS
+#
+#   AX_COMPILER_FLAGS_CXXFLAGS([VARIABLE], [IS-RELEASE], [EXTRA-BASE-FLAGS], [EXTRA-YES-FLAGS])
+#
+# DESCRIPTION
+#
+#   Add warning flags for the C++ compiler to VARIABLE, which defaults to
+#   WARN_CXXFLAGS.  VARIABLE is AC_SUBST-ed by this macro, but must be
+#   manually added to the CXXFLAGS variable for each target in the code
+#   base.
+#
+#   This macro depends on the environment set up by AX_COMPILER_FLAGS.
+#   Specifically, it uses the value of $ax_enable_compile_warnings to decide
+#   which flags to enable.
+#
+# LICENSE
+#
+#   Copyright (c) 2015 David King <amigadave amigadave com>
+#
+#   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 7
+
+AC_DEFUN([AX_COMPILER_FLAGS_CXXFLAGS],[
+    AC_REQUIRE([AC_PROG_SED])
+    AX_REQUIRE_DEFINED([AX_APPEND_COMPILE_FLAGS])
+    AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
+    AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG])
+
+    # Variable names
+    m4_define(ax_warn_cxxflags_variable,
+              [m4_normalize(ifelse([$1],,[WARN_CXXFLAGS],[$1]))])
+
+    AC_LANG_PUSH([C++])
+
+    # Always pass -Werror=unknown-warning-option to get Clang to fail on bad
+    # flags, otherwise they are always appended to the warn_cxxflags variable,
+    # and Clang warns on them for every compilation unit.
+    # If this is passed to GCC, it will explode, so the flag must be enabled
+    # conditionally.
+    AX_CHECK_COMPILE_FLAG([-Werror=unknown-warning-option],[
+        ax_compiler_flags_test="-Werror=unknown-warning-option"
+    ],[
+        ax_compiler_flags_test=""
+    ])
+
+    # Base flags
+    AX_APPEND_COMPILE_FLAGS([ dnl
+        -fno-strict-aliasing dnl
+        $3 dnl
+    ],ax_warn_cxxflags_variable,[$ax_compiler_flags_test])
+
+    AS_IF([test "$ax_enable_compile_warnings" != "no"],[
+        # "yes" flags
+        AX_APPEND_COMPILE_FLAGS([ dnl
+            -Wall dnl
+            -Wextra dnl
+            -Wundef dnl
+            -Wwrite-strings dnl
+            -Wpointer-arith dnl
+            -Wmissing-declarations dnl
+            -Wredundant-decls dnl
+            -Wno-unused-parameter dnl
+            -Wno-missing-field-initializers dnl
+            -Wformat=2 dnl
+            -Wcast-align dnl
+            -Wformat-nonliteral dnl
+            -Wformat-security dnl
+            -Wsign-compare dnl
+            -Wstrict-aliasing dnl
+            -Wshadow dnl
+            -Winline dnl
+            -Wpacked dnl
+            -Wmissing-format-attribute dnl
+            -Wmissing-noreturn dnl
+            -Winit-self dnl
+            -Wredundant-decls dnl
+            -Wmissing-include-dirs dnl
+            -Wunused-but-set-variable dnl
+            -Warray-bounds dnl
+            -Wreturn-type dnl
+            -Wno-overloaded-virtual dnl
+            -Wswitch-enum dnl
+            -Wswitch-default dnl
+            $4 dnl
+            $5 dnl
+            $6 dnl
+            $7 dnl
+        ],ax_warn_cxxflags_variable,[$ax_compiler_flags_test])
+    ])
+    AS_IF([test "$ax_enable_compile_warnings" = "error"],[
+        # "error" flags; -Werror has to be appended unconditionally because
+        # it's not possible to test for
+        #
+        # suggest-attribute=format is disabled because it gives too many false
+        # positives
+        AX_APPEND_FLAG([-Werror],ax_warn_cxxflags_variable)
+
+        AX_APPEND_COMPILE_FLAGS([ dnl
+            -Wno-suggest-attribute=format dnl
+        ],ax_warn_cxxflags_variable,[$ax_compiler_flags_test])
+    ])
+
+    # In the flags below, when disabling specific flags, always add *both*
+    # -Wno-foo and -Wno-error=foo. This fixes the situation where (for example)
+    # we enable -Werror, disable a flag, and a build bot passes CXXFLAGS=-Wall,
+    # which effectively turns that flag back on again as an error.
+    for flag in $ax_warn_cxxflags_variable; do
+        AS_CASE([$flag],
+                [-Wno-*=*],[],
+                [-Wno-*],[
+                    AX_APPEND_COMPILE_FLAGS([-Wno-error=$(AS_ECHO([$flag]) | $SED 's/^-Wno-//')],
+                                            ax_warn_cxxflags_variable,
+                                            [$ax_compiler_flags_test])
+                ])
+    done
+
+    AC_LANG_POP([C++])
+
+    # Substitute the variables
+    AC_SUBST(ax_warn_cxxflags_variable)
+])dnl AX_COMPILER_FLAGS_CXXFLAGS
diff --git a/m4/ax_compiler_flags_gir.m4 b/m4/ax_compiler_flags_gir.m4
new file mode 100644
index 0000000..180f50d
--- /dev/null
+++ b/m4/ax_compiler_flags_gir.m4
@@ -0,0 +1,60 @@
+# ===========================================================================
+#   http://www.gnu.org/software/autoconf-archive/ax_compiler_flags_gir.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_COMPILER_FLAGS_GIR([VARIABLE], [IS-RELEASE], [EXTRA-BASE-FLAGS], [EXTRA-YES-FLAGS])
+#
+# DESCRIPTION
+#
+#   Add warning flags for the g-ir-scanner (from GObject Introspection) to
+#   VARIABLE, which defaults to WARN_SCANNERFLAGS.  VARIABLE is AC_SUBST-ed
+#   by this macro, but must be manually added to the SCANNERFLAGS variable
+#   for each GIR target in the code base.
+#
+#   This macro depends on the environment set up by AX_COMPILER_FLAGS.
+#   Specifically, it uses the value of $ax_enable_compile_warnings to decide
+#   which flags to enable.
+#
+# LICENSE
+#
+#   Copyright (c) 2015 Philip Withnall <philip tecnocode co uk>
+#
+#   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 4
+
+AC_DEFUN([AX_COMPILER_FLAGS_GIR],[
+    AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
+
+    # Variable names
+    m4_define(ax_warn_scannerflags_variable,
+              [m4_normalize(ifelse([$1],,[WARN_SCANNERFLAGS],[$1]))])
+
+    # Base flags
+    AX_APPEND_FLAG([$3],ax_warn_scannerflags_variable)
+
+    AS_IF([test "$ax_enable_compile_warnings" != "no"],[
+        # "yes" flags
+        AX_APPEND_FLAG([ dnl
+            --warn-all dnl
+            $4 dnl
+            $5 dnl
+            $6 dnl
+            $7 dnl
+        ],ax_warn_scannerflags_variable)
+    ])
+    AS_IF([test "$ax_enable_compile_warnings" = "error"],[
+        # "error" flags
+        AX_APPEND_FLAG([ dnl
+            --warn-error dnl
+        ],ax_warn_scannerflags_variable)
+    ])
+
+    # Substitute the variables
+    AC_SUBST(ax_warn_scannerflags_variable)
+])dnl AX_COMPILER_FLAGS
diff --git a/m4/ax_compiler_flags_ldflags.m4 b/m4/ax_compiler_flags_ldflags.m4
new file mode 100644
index 0000000..228471e
--- /dev/null
+++ b/m4/ax_compiler_flags_ldflags.m4
@@ -0,0 +1,75 @@
+# =============================================================================
+#  http://www.gnu.org/software/autoconf-archive/ax_compiler_flags_ldflags.html
+# =============================================================================
+#
+# SYNOPSIS
+#
+#   AX_COMPILER_FLAGS_LDFLAGS([VARIABLE], [IS-RELEASE], [EXTRA-BASE-FLAGS], [EXTRA-YES-FLAGS])
+#
+# DESCRIPTION
+#
+#   Add warning flags for the linker to VARIABLE, which defaults to
+#   WARN_LDFLAGS.  VARIABLE is AC_SUBST-ed by this macro, but must be
+#   manually added to the LDFLAGS variable for each target in the code base.
+#
+#   This macro depends on the environment set up by AX_COMPILER_FLAGS.
+#   Specifically, it uses the value of $ax_enable_compile_warnings to decide
+#   which flags to enable.
+#
+# LICENSE
+#
+#   Copyright (c) 2014, 2015 Philip Withnall <philip tecnocode co uk>
+#
+#   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 5
+
+AC_DEFUN([AX_COMPILER_FLAGS_LDFLAGS],[
+    AX_REQUIRE_DEFINED([AX_APPEND_LINK_FLAGS])
+    AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
+    AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG])
+
+    # Variable names
+    m4_define(ax_warn_ldflags_variable,
+              [m4_normalize(ifelse([$1],,[WARN_LDFLAGS],[$1]))])
+
+    # Always pass -Werror=unknown-warning-option to get Clang to fail on bad
+    # flags, otherwise they are always appended to the warn_ldflags variable,
+    # and Clang warns on them for every compilation unit.
+    # If this is passed to GCC, it will explode, so the flag must be enabled
+    # conditionally.
+    AX_CHECK_COMPILE_FLAG([-Werror=unknown-warning-option],[
+        ax_compiler_flags_test="-Werror=unknown-warning-option"
+    ],[
+        ax_compiler_flags_test=""
+    ])
+
+    # Base flags
+    AX_APPEND_LINK_FLAGS([ dnl
+        -Wl,--no-as-needed dnl
+        $3 dnl
+    ],ax_warn_ldflags_variable,[$ax_compiler_flags_test])
+
+    AS_IF([test "$ax_enable_compile_warnings" != "no"],[
+        # "yes" flags
+        AX_APPEND_LINK_FLAGS([$4 $5 $6 $7],
+                                ax_warn_ldflags_variable,
+                                [$ax_compiler_flags_test])
+    ])
+    AS_IF([test "$ax_enable_compile_warnings" = "error"],[
+        # "error" flags; -Werror has to be appended unconditionally because
+        # it's not possible to test for
+        #
+        # suggest-attribute=format is disabled because it gives too many false
+        # positives
+        AX_APPEND_LINK_FLAGS([ dnl
+            -Wl,--fatal-warnings dnl
+        ],ax_warn_ldflags_variable,[$ax_compiler_flags_test])
+    ])
+
+    # Substitute the variables
+    AC_SUBST(ax_warn_ldflags_variable)
+])dnl AX_COMPILER_FLAGS
diff --git a/m4/ax_compiler_vendor.m4 b/m4/ax_compiler_vendor.m4
new file mode 100644
index 0000000..39ca3c0
--- /dev/null
+++ b/m4/ax_compiler_vendor.m4
@@ -0,0 +1,87 @@
+# ===========================================================================
+#    http://www.gnu.org/software/autoconf-archive/ax_compiler_vendor.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_COMPILER_VENDOR
+#
+# DESCRIPTION
+#
+#   Determine the vendor of the C/C++ compiler, e.g., gnu, intel, ibm, sun,
+#   hp, borland, comeau, dec, cray, kai, lcc, metrowerks, sgi, microsoft,
+#   watcom, etc. The vendor is returned in the cache variable
+#   $ax_cv_c_compiler_vendor for C and $ax_cv_cxx_compiler_vendor for C++.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Steven G. Johnson <stevenj alum mit edu>
+#   Copyright (c) 2008 Matteo Frigo
+#
+#   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/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 15
+
+AC_DEFUN([AX_COMPILER_VENDOR],
+[AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor,
+  dnl Please add if possible support to ax_compiler_version.m4
+  [# note: don't check for gcc first since some other compilers define __GNUC__
+  vendors="intel:     __ICC,__ECC,__INTEL_COMPILER
+           ibm:       __xlc__,__xlC__,__IBMC__,__IBMCPP__
+           pathscale: __PATHCC__,__PATHSCALE__
+           clang:     __clang__
+           cray:      _CRAYC
+           fujitsu:   __FUJITSU
+           gnu:       __GNUC__
+           sun:       __SUNPRO_C,__SUNPRO_CC
+           hp:        __HP_cc,__HP_aCC
+           dec:       __DECC,__DECCXX,__DECC_VER,__DECCXX_VER
+           borland:   __BORLANDC__,__CODEGEARC__,__TURBOC__
+           comeau:    __COMO__
+           kai:       __KCC
+           lcc:       __LCC__
+           sgi:       __sgi,sgi
+           microsoft: _MSC_VER
+           metrowerks: __MWERKS__
+           watcom:    __WATCOMC__
+           portland:  __PGI
+          tcc:       __TINYC__
+           unknown:   UNKNOWN"
+  for ventest in $vendors; do
+    case $ventest in
+      *:) vendor=$ventest; continue ;;
+      *)  vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")" ;;
+    esac
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[
+      #if !($vencpp)
+        thisisanerror;
+      #endif
+    ])], [break])
+  done
+  ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=`echo $vendor | cut -d: -f1`
+ ])
+])
diff --git a/m4/ax_cxx_compile_stdcxx_0x.m4 b/m4/ax_cxx_compile_stdcxx_0x.m4
new file mode 100644
index 0000000..52c3984
--- /dev/null
+++ b/m4/ax_cxx_compile_stdcxx_0x.m4
@@ -0,0 +1,111 @@
+# ============================================================================
+#  http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_0x.html
+# ============================================================================
+#
+# SYNOPSIS
+#
+#   AX_CXX_COMPILE_STDCXX_0X
+#
+# DESCRIPTION
+#
+#   Check for baseline language coverage in the compiler for the C++0x
+#   standard.
+#
+#   This macro is deprecated and has been superseded by the
+#   AX_CXX_COMPILE_STDCXX_11 macro which should be used instead.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Benjamin Kosnik <bkoz redhat com>
+#
+#   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 10
+
+AU_ALIAS([AC_CXX_COMPILE_STDCXX_0X], [AX_CXX_COMPILE_STDCXX_0X])
+AC_DEFUN([AX_CXX_COMPILE_STDCXX_0X], [
+  AC_OBSOLETE([$0], [; use AX_CXX_COMPILE_STDCXX_11 instead])
+  AC_CACHE_CHECK(if g++ supports C++0x features without additional flags,
+  ax_cv_cxx_compile_cxx0x_native,
+  [AC_LANG_SAVE
+  AC_LANG_CPLUSPLUS
+  AC_TRY_COMPILE([
+  template <typename T>
+    struct check
+    {
+      static_assert(sizeof(int) <= sizeof(T), "not big enough");
+    };
+
+    typedef check<check<bool>> right_angle_brackets;
+
+    int a;
+    decltype(a) b;
+
+    typedef check<int> check_type;
+    check_type c;
+    check_type&& cr = static_cast<check_type&&>(c);],,
+  ax_cv_cxx_compile_cxx0x_native=yes, ax_cv_cxx_compile_cxx0x_native=no)
+  AC_LANG_RESTORE
+  ])
+
+  AC_CACHE_CHECK(if g++ supports C++0x features with -std=c++0x,
+  ax_cv_cxx_compile_cxx0x_cxx,
+  [AC_LANG_SAVE
+  AC_LANG_CPLUSPLUS
+  ac_save_CXX="$CXX"
+  CXX="$CXX -std=c++0x"
+  AC_TRY_COMPILE([
+  template <typename T>
+    struct check
+    {
+      static_assert(sizeof(int) <= sizeof(T), "not big enough");
+    };
+
+    typedef check<check<bool>> right_angle_brackets;
+
+    int a;
+    decltype(a) b;
+
+    typedef check<int> check_type;
+    check_type c;
+    check_type&& cr = static_cast<check_type&&>(c);],,
+  ax_cv_cxx_compile_cxx0x_cxx=yes, ax_cv_cxx_compile_cxx0x_cxx=no)
+  CXX="$ac_save_CXX"
+  AC_LANG_RESTORE
+  ])
+
+  AC_CACHE_CHECK(if g++ supports C++0x features with -std=gnu++0x,
+  ax_cv_cxx_compile_cxx0x_gxx,
+  [AC_LANG_SAVE
+  AC_LANG_CPLUSPLUS
+  ac_save_CXX="$CXX"
+  CXX="$CXX -std=gnu++0x"
+  AC_TRY_COMPILE([
+  template <typename T>
+    struct check
+    {
+      static_assert(sizeof(int) <= sizeof(T), "not big enough");
+    };
+
+    typedef check<check<bool>> right_angle_brackets;
+
+    int a;
+    decltype(a) b;
+
+    typedef check<int> check_type;
+    check_type c;
+    check_type&& cr = static_cast<check_type&&>(c);],,
+  ax_cv_cxx_compile_cxx0x_gxx=yes, ax_cv_cxx_compile_cxx0x_gxx=no)
+  CXX="$ac_save_CXX"
+  AC_LANG_RESTORE
+  ])
+
+  if test "$ax_cv_cxx_compile_cxx0x_native" = yes ||
+     test "$ax_cv_cxx_compile_cxx0x_cxx" = yes ||
+     test "$ax_cv_cxx_compile_cxx0x_gxx" = yes; then
+    AC_DEFINE(HAVE_STDCXX_0X,,[Define if g++ supports C++0x features. ])
+  fi
+])
diff --git a/m4/ax_cxx_compile_stdcxx_11.m4 b/m4/ax_cxx_compile_stdcxx_11.m4
new file mode 100644
index 0000000..516da37
--- /dev/null
+++ b/m4/ax_cxx_compile_stdcxx_11.m4
@@ -0,0 +1,172 @@
+# ============================================================================
+#  http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html
+# ============================================================================
+#
+# SYNOPSIS
+#
+#   AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional])
+#
+# DESCRIPTION
+#
+#   Check for baseline language coverage in the compiler for the C++11
+#   standard; if necessary, add switches to CXXFLAGS to enable support.
+#
+#   The first argument, if specified, indicates whether you insist on an
+#   extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
+#   -std=c++11).  If neither is specified, you get whatever works, with
+#   preference for an extended mode.
+#
+#   The second argument, if specified 'mandatory' or if left unspecified,
+#   indicates that baseline C++11 support is required and that the macro
+#   should error out if no mode with that support is found.  If specified
+#   'optional', then configuration proceeds regardless, after defining
+#   HAVE_CXX11 if and only if a supporting mode is found.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Benjamin Kosnik <bkoz redhat com>
+#   Copyright (c) 2012 Zack Weinberg <zackw panix com>
+#   Copyright (c) 2013 Roy Stogner <roystgnr ices utexas edu>
+#   Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov google com>
+#   Copyright (c) 2015 Paul Norman <penorman mac com>
+#
+#   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 13
+
+m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [[
+  template <typename T>
+    struct check
+    {
+      static_assert(sizeof(int) <= sizeof(T), "not big enough");
+    };
+
+    struct Base {
+    virtual void f() {}
+    };
+    struct Child : public Base {
+    virtual void f() override {}
+    };
+
+    typedef check<check<bool>> right_angle_brackets;
+
+    int a;
+    decltype(a) b;
+
+    typedef check<int> check_type;
+    check_type c;
+    check_type&& cr = static_cast<check_type&&>(c);
+
+    auto d = a;
+    auto l = [](){};
+    // Prevent Clang error: unused variable 'l' [-Werror,-Wunused-variable]
+    struct use_l { use_l() { l(); } };
+
+    // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
+    // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function because of this
+    namespace test_template_alias_sfinae {
+        struct foo {};
+
+        template<typename T>
+        using member = typename T::member_type;
+
+        template<typename T>
+        void func(...) {}
+
+        template<typename T>
+        void func(member<T>*) {}
+
+        void test();
+
+        void test() {
+            func<foo>(0);
+        }
+    }
+
+    // Check for C++11 attribute support
+    void noret [[noreturn]] () { throw 0; }
+]])
+
+AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl
+  m4_if([$1], [], [],
+        [$1], [ext], [],
+        [$1], [noext], [],
+        [m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl
+  m4_if([$2], [], [ax_cxx_compile_cxx11_required=true],
+        [$2], [mandatory], [ax_cxx_compile_cxx11_required=true],
+        [$2], [optional], [ax_cxx_compile_cxx11_required=false],
+        [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])])
+  AC_LANG_PUSH([C++])dnl
+  ac_success=no
+  AC_CACHE_CHECK(whether $CXX supports C++11 features by default,
+  ax_cv_cxx_compile_cxx11,
+  [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
+    [ax_cv_cxx_compile_cxx11=yes],
+    [ax_cv_cxx_compile_cxx11=no])])
+  if test x$ax_cv_cxx_compile_cxx11 = xyes; then
+    ac_success=yes
+  fi
+
+  m4_if([$1], [noext], [], [dnl
+  if test x$ac_success = xno; then
+    for switch in -std=gnu++11 -std=gnu++0x; do
+      cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
+      AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
+                     $cachevar,
+        [ac_save_CXXFLAGS="$CXXFLAGS"
+         CXXFLAGS="$CXXFLAGS $switch"
+         AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
+          [eval $cachevar=yes],
+          [eval $cachevar=no])
+         CXXFLAGS="$ac_save_CXXFLAGS"])
+      if eval test x\$$cachevar = xyes; then
+        CXXFLAGS="$CXXFLAGS $switch"
+        ac_success=yes
+        break
+      fi
+    done
+  fi])
+
+  m4_if([$1], [ext], [], [dnl
+  if test x$ac_success = xno; then
+    dnl HP's aCC needs +std=c++11 according to:
+    dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
+    dnl Cray's crayCC needs "-h std=c++11"
+    for switch in -std=c++11 -std=c++0x +std=c++11 "-h std=c++11"; do
+      cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
+      AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
+                     $cachevar,
+        [ac_save_CXXFLAGS="$CXXFLAGS"
+         CXXFLAGS="$CXXFLAGS $switch"
+         AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
+          [eval $cachevar=yes],
+          [eval $cachevar=no])
+         CXXFLAGS="$ac_save_CXXFLAGS"])
+      if eval test x\$$cachevar = xyes; then
+        CXXFLAGS="$CXXFLAGS $switch"
+        ac_success=yes
+        break
+      fi
+    done
+  fi])
+  AC_LANG_POP([C++])
+  if test x$ax_cxx_compile_cxx11_required = xtrue; then
+    if test x$ac_success = xno; then
+      AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.])
+    fi
+  else
+    if test x$ac_success = xno; then
+      HAVE_CXX11=0
+      AC_MSG_NOTICE([No compiler with C++11 support was found])
+    else
+      HAVE_CXX11=1
+      AC_DEFINE(HAVE_CXX11,1,
+                [define if the compiler supports basic C++11 syntax])
+    fi
+
+    AC_SUBST(HAVE_CXX11)
+  fi
+])
diff --git a/m4/ax_generate_changelog.m4 b/m4/ax_generate_changelog.m4
new file mode 100644
index 0000000..d9d5cd1
--- /dev/null
+++ b/m4/ax_generate_changelog.m4
@@ -0,0 +1,99 @@
+# ===========================================================================
+#   http://www.gnu.org/software/autoconf-archive/ax_generate_changelog.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_GENERATE_CHANGELOG()
+#
+# DESCRIPTION
+#
+#   Builds a rule for generating a ChangeLog file from version control
+#   system commit messages.  Currently, the only supported VCS is git, but
+#   support for others could be added in future.
+#
+#   Defines GENERATE_CHANGELOG_RULES which should be substituted in your
+#   Makefile.
+#
+#   Usage example:
+#
+#   configure.ac:
+#
+#     AX_GENERATE_CHANGELOG
+#
+#   Makefile.am:
+#
+#     @GENERATE_CHANGELOG_RULES@
+#     CHANGELOG_START = 0.2.3^
+#     dist-hook: dist-ChangeLog
+#
+#   ChangeLog (stub committed to VCS):
+#
+#     The ChangeLog is auto-generated when releasing.
+#     If you are seeing this, use 'git log' for a detailed list of changes.
+#
+#   This results in a "dist-ChangeLog" rule being added to the Makefile.
+#   When run, "dist-ChangeLog" will generate a ChangeLog in the
+#   $(top_distdir), using $(CHANGELOG_GIT_FLAGS) to format the output from
+#   "git log" being run in $(CHANGELOG_GIT_DIR).
+#
+#   Unless Automake is initialised with the 'foreign' option, a dummy
+#   ChangeLog file must be committed to VCS in $(top_srcdir), containing the
+#   text above (for example).  It will be substituted by the automatically
+#   generated ChangeLog during "make dist".
+#
+# LICENSE
+#
+#   Copyright (c) 2015 David King <amigadave amigadave com>
+#   Copyright (c) 2015 Philip Withnall <philip withnall collabora co uk>
+#
+#   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 1
+
+AC_DEFUN([AX_GENERATE_CHANGELOG],[
+       # Find git, defaulting to the 'missing' script so the user gets a nice
+       # message if git is missing, rather than a plain 'command not found'.
+       AC_PATH_PROG([GIT],[git],[${am_missing_run}git])
+       AC_SUBST([GIT])
+
+       # Build the ChangeLog rules.
+       m4_pattern_allow([AM_V_GEN])
+GENERATE_CHANGELOG_RULES='
+# Generate ChangeLog
+#
+# Optional:
+#  - CHANGELOG_START: git commit ID or tag name to output changelogs from
+#    (exclusive). (Default: include all commits)
+#  - CHANGELOG_GIT_FLAGS: General flags to pass to git-log when generating the
+#    ChangeLog. (Default: various)
+#  - CHANGELOG_GIT_DIR: .git directory to use. (Default: $(top_srcdir)/.git)
+
+# git-specific
+CHANGELOG_GIT_FLAGS ?= --stat -M -C --name-status --no-color
+CHANGELOG_GIT_DIR ?= $(top_srcdir)/.git
+
+ifeq ($(CHANGELOG_START),)
+CHANGELOG_GIT_RANGE =
+else
+CHANGELOG_GIT_RANGE = $(CHANGELOG_START)..
+endif
+
+# Generate a ChangeLog in $(top_distdir)
+dist-ChangeLog:
+       $(AM_V_GEN)if $(GIT) \
+               --git-dir=$(CHANGELOG_GIT_DIR) --work-tree=$(top_srcdir) log \
+               $(CHANGELOG_GIT_FLAGS) $(CHANGELOG_GIT_RANGE) \
+               | fmt --split-only >.ChangeLog.tmp; \
+       then mv -f .ChangeLog.tmp "$(top_distdir)/ChangeLog"; \
+       else rm -f .ChangeLog.tmp; exit 1; fi
+
+.PHONY: dist-ChangeLog
+'
+
+       AC_SUBST([GENERATE_CHANGELOG_RULES])
+       m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([GENERATE_CHANGELOG_RULES])])
+])
diff --git a/m4/ax_is_release.m4 b/m4/ax_is_release.m4
new file mode 100644
index 0000000..9ec6746
--- /dev/null
+++ b/m4/ax_is_release.m4
@@ -0,0 +1,69 @@
+# ===========================================================================
+#       http://www.gnu.org/software/autoconf-archive/ax_is_release.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_IS_RELEASE(POLICY)
+#
+# DESCRIPTION
+#
+#   Determine whether the code is being configured as a release, or from
+#   git. Set the ax_is_release variable to 'yes' or 'no'.
+#
+#   If building a release version, it is recommended that the configure
+#   script disable compiler errors and debug features, by conditionalising
+#   them on the ax_is_release variable.  If building from git, these
+#   features should be enabled.
+#
+#   The POLICY parameter specifies how ax_is_release is determined. It can
+#   take the following values:
+#
+#    * git-directory:  ax_is_release will be 'no' if a '.git' directory exists
+#    * minor-version:  ax_is_release will be 'no' if the minor version number
+#                      in $PACKAGE_VERSION is odd; this assumes
+#                      $PACKAGE_VERSION follows the 'major.minor.micro' scheme
+#    * micro-version:  ax_is_release will be 'no' if the micro version number
+#                      in $PACKAGE_VERSION is odd; this assumes
+#                      $PACKAGE_VERSION follows the 'major.minor.micro' scheme
+#    * always:         ax_is_release will always be 'yes'
+#    * never:          ax_is_release will always be 'no'
+#
+#   Other policies may be added in future.
+#
+# LICENSE
+#
+#   Copyright (c) 2015 Philip Withnall <philip tecnocode co uk>
+#
+#   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.
+
+#serial 3
+
+AC_DEFUN([AX_IS_RELEASE],[
+    AC_BEFORE([AC_INIT],[$0])
+
+    m4_case([$1],
+      [git-directory],[
+        # $is_release = (.git directory does not exist)
+        AS_IF([test -d .git],[ax_is_release=no],[ax_is_release=yes])
+      ],
+      [minor-version],[
+        # $is_release = ($minor_version is even)
+        minor_version=`echo "$PACKAGE_VERSION" | sed 's/[[^.]][[^.]]*.\([[^.]][[^.]]*\).*/\1/'`
+        AS_IF([test "$(( $minor_version % 2 ))" -ne 0],
+              [ax_is_release=no],[ax_is_release=yes])
+      ],
+      [micro-version],[
+        # $is_release = ($micro_version is even)
+        micro_version=`echo "$PACKAGE_VERSION" | sed 's/[[^.]]*\.[[^.]]*\.\([[^.]]*\).*/\1/'`
+        AS_IF([test "$(( $micro_version % 2 ))" -ne 0],
+              [ax_is_release=no],[ax_is_release=yes])
+      ],
+      [always],[ax_is_release=yes],
+      [never],[ax_is_release=no],
+      [
+        AC_MSG_ERROR([Invalid policy. Valid policies: git-directory, minor-version.])
+      ])
+])
diff --git a/m4/ax_require_defined.m4 b/m4/ax_require_defined.m4
new file mode 100644
index 0000000..cae1111
--- /dev/null
+++ b/m4/ax_require_defined.m4
@@ -0,0 +1,37 @@
+# ===========================================================================
+#    http://www.gnu.org/software/autoconf-archive/ax_require_defined.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_REQUIRE_DEFINED(MACRO)
+#
+# DESCRIPTION
+#
+#   AX_REQUIRE_DEFINED is a simple helper for making sure other macros have
+#   been defined and thus are available for use.  This avoids random issues
+#   where a macro isn't expanded.  Instead the configure script emits a
+#   non-fatal:
+#
+#     ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found
+#
+#   It's like AC_REQUIRE except it doesn't expand the required macro.
+#
+#   Here's an example:
+#
+#     AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
+#
+# LICENSE
+#
+#   Copyright (c) 2014 Mike Frysinger <vapier gentoo 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 1
+
+AC_DEFUN([AX_REQUIRE_DEFINED], [dnl
+  m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])])
+])dnl AX_REQUIRE_DEFINED
diff --git a/m4/codeset.m4 b/m4/codeset.m4
new file mode 100644
index 0000000..d7de8d6
--- /dev/null
+++ b/m4/codeset.m4
@@ -0,0 +1,23 @@
+# codeset.m4 serial 5 (gettext-0.18.2)
+dnl Copyright (C) 2000-2002, 2006, 2008-2014 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_DEFUN([AM_LANGINFO_CODESET],
+[
+  AC_CACHE_CHECK([for nl_langinfo and CODESET], [am_cv_langinfo_codeset],
+    [AC_LINK_IFELSE(
+       [AC_LANG_PROGRAM(
+          [[#include <langinfo.h>]],
+          [[char* cs = nl_langinfo(CODESET); return !cs;]])],
+       [am_cv_langinfo_codeset=yes],
+       [am_cv_langinfo_codeset=no])
+    ])
+  if test $am_cv_langinfo_codeset = yes; then
+    AC_DEFINE([HAVE_LANGINFO_CODESET], [1],
+      [Define if you have <langinfo.h> and nl_langinfo(CODESET).])
+  fi
+])
diff --git a/m4/extern-inline.m4 b/m4/extern-inline.m4
new file mode 100644
index 0000000..7280065
--- /dev/null
+++ b/m4/extern-inline.m4
@@ -0,0 +1,101 @@
+dnl 'extern inline' a la ISO C99.
+
+dnl Copyright 2012-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_EXTERN_INLINE],
+[
+  AH_VERBATIM([extern_inline],
+[/* Please see the Gnulib manual for how to use these macros.
+
+   Suppress extern inline with HP-UX cc, as it appears to be broken; see
+   <http://lists.gnu.org/archive/html/bug-texinfo/2013-02/msg00030.html>.
+
+   Suppress extern inline with Sun C in standards-conformance mode, as it
+   mishandles inline functions that call each other.  E.g., for 'inline void f
+   (void) { } inline void g (void) { f (); }', c99 incorrectly complains
+   'reference to static identifier "f" in extern inline function'.
+   This bug was observed with Sun C 5.12 SunOS_i386 2011/11/16.
+
+   Suppress extern inline (with or without __attribute__ ((__gnu_inline__)))
+   on configurations that mistakenly use 'static inline' to implement
+   functions or macros in standard C headers like <ctype.h>.  For example,
+   if isdigit is mistakenly implemented via a static inline function,
+   a program containing an extern inline function that calls isdigit
+   may not work since the C standard prohibits extern inline functions
+   from calling static functions.  This bug is known to occur on:
+
+     OS X 10.8 and earlier; see:
+     http://lists.gnu.org/archive/html/bug-gnulib/2012-12/msg00023.html
+
+     DragonFly; see
+     http://muscles.dragonflybsd.org/bulk/bleeding-edge-potential/latest-per-pkg/ah-tty-0.3.12.log
+
+     FreeBSD; see:
+     http://lists.gnu.org/archive/html/bug-gnulib/2014-07/msg00104.html
+
+   OS X 10.9 has a macro __header_inline indicating the bug is fixed for C and
+   for clang but remains for g++; see <http://trac.macports.org/ticket/41033>.
+   Assume DragonFly and FreeBSD will be similar.  */
+#if (((defined __APPLE__ && defined __MACH__) \
+      || defined __DragonFly__ || defined __FreeBSD__) \
+     && (defined __header_inline \
+         ? (defined __cplusplus && defined __GNUC_STDC_INLINE__ \
+            && ! defined __clang__) \
+         : ((! defined _DONT_USE_CTYPE_INLINE_ \
+             && (defined __GNUC__ || defined __cplusplus)) \
+            || (defined _FORTIFY_SOURCE && 0 < _FORTIFY_SOURCE \
+                && defined __GNUC__ && ! defined __cplusplus))))
+# define _GL_EXTERN_INLINE_STDHEADER_BUG
+#endif
+#if ((__GNUC__ \
+      ? defined __GNUC_STDC_INLINE__ && __GNUC_STDC_INLINE__ \
+      : (199901L <= __STDC_VERSION__ \
+         && !defined __HP_cc \
+         && !(defined __SUNPRO_C && __STDC__))) \
+     && !defined _GL_EXTERN_INLINE_STDHEADER_BUG)
+# define _GL_INLINE inline
+# define _GL_EXTERN_INLINE extern inline
+# define _GL_EXTERN_INLINE_IN_USE
+#elif (2 < __GNUC__ + (7 <= __GNUC_MINOR__) && !defined __STRICT_ANSI__ \
+       && !defined _GL_EXTERN_INLINE_STDHEADER_BUG)
+# if defined __GNUC_GNU_INLINE__ && __GNUC_GNU_INLINE__
+   /* __gnu_inline__ suppresses a GCC 4.2 diagnostic.  */
+#  define _GL_INLINE extern inline __attribute__ ((__gnu_inline__))
+# else
+#  define _GL_INLINE extern inline
+# endif
+# define _GL_EXTERN_INLINE extern
+# define _GL_EXTERN_INLINE_IN_USE
+#else
+# define _GL_INLINE static _GL_UNUSED
+# define _GL_EXTERN_INLINE static _GL_UNUSED
+#endif
+
+/* In GCC 4.6 (inclusive) to 5.1 (exclusive),
+   suppress bogus "no previous prototype for 'FOO'"
+   and "no previous declaration for 'FOO'" diagnostics,
+   when FOO is an inline function in the header; see
+   <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54113> and
+   <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63877>.  */
+#if __GNUC__ == 4 && 6 <= __GNUC_MINOR__
+# if defined __GNUC_STDC_INLINE__ && __GNUC_STDC_INLINE__
+#  define _GL_INLINE_HEADER_CONST_PRAGMA
+# else
+#  define _GL_INLINE_HEADER_CONST_PRAGMA \
+     _Pragma ("GCC diagnostic ignored \"-Wsuggest-attribute=const\"")
+# endif
+# define _GL_INLINE_HEADER_BEGIN \
+    _Pragma ("GCC diagnostic push") \
+    _Pragma ("GCC diagnostic ignored \"-Wmissing-prototypes\"") \
+    _Pragma ("GCC diagnostic ignored \"-Wmissing-declarations\"") \
+    _GL_INLINE_HEADER_CONST_PRAGMA
+# define _GL_INLINE_HEADER_END \
+    _Pragma ("GCC diagnostic pop")
+#else
+# define _GL_INLINE_HEADER_BEGIN
+# define _GL_INLINE_HEADER_END
+#endif])
+])
diff --git a/m4/fcntl-o.m4 b/m4/fcntl-o.m4
new file mode 100644
index 0000000..891a62f
--- /dev/null
+++ b/m4/fcntl-o.m4
@@ -0,0 +1,134 @@
+# fcntl-o.m4 serial 4
+dnl Copyright (C) 2006, 2009-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl Written by Paul Eggert.
+
+# Test whether the flags O_NOATIME and O_NOFOLLOW actually work.
+# Define HAVE_WORKING_O_NOATIME to 1 if O_NOATIME works, or to 0 otherwise.
+# Define HAVE_WORKING_O_NOFOLLOW to 1 if O_NOFOLLOW works, or to 0 otherwise.
+AC_DEFUN([gl_FCNTL_O_FLAGS],
+[
+  dnl Persuade glibc <fcntl.h> to define O_NOATIME and O_NOFOLLOW.
+  dnl AC_USE_SYSTEM_EXTENSIONS was introduced in autoconf 2.60 and obsoletes
+  dnl AC_GNU_SOURCE.
+  m4_ifdef([AC_USE_SYSTEM_EXTENSIONS],
+    [AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])],
+    [AC_REQUIRE([AC_GNU_SOURCE])])
+
+  AC_CHECK_HEADERS_ONCE([unistd.h])
+  AC_CHECK_FUNCS_ONCE([symlink])
+  AC_CACHE_CHECK([for working fcntl.h], [gl_cv_header_working_fcntl_h],
+    [AC_RUN_IFELSE(
+       [AC_LANG_PROGRAM(
+          [[#include <sys/types.h>
+           #include <sys/stat.h>
+           #if HAVE_UNISTD_H
+           # include <unistd.h>
+           #else /* on Windows with MSVC */
+           # include <io.h>
+           # include <stdlib.h>
+           # defined sleep(n) _sleep ((n) * 1000)
+           #endif
+           #include <fcntl.h>
+           #ifndef O_NOATIME
+            #define O_NOATIME 0
+           #endif
+           #ifndef O_NOFOLLOW
+            #define O_NOFOLLOW 0
+           #endif
+           static int const constants[] =
+            {
+              O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC, O_APPEND,
+              O_NONBLOCK, O_SYNC, O_ACCMODE, O_RDONLY, O_RDWR, O_WRONLY
+            };
+          ]],
+          [[
+            int result = !constants;
+            #if HAVE_SYMLINK
+            {
+              static char const sym[] = "conftest.sym";
+              if (symlink ("/dev/null", sym) != 0)
+                result |= 2;
+              else
+                {
+                  int fd = open (sym, O_WRONLY | O_NOFOLLOW | O_CREAT, 0);
+                  if (fd >= 0)
+                    {
+                      close (fd);
+                      result |= 4;
+                    }
+                }
+              if (unlink (sym) != 0 || symlink (".", sym) != 0)
+                result |= 2;
+              else
+                {
+                  int fd = open (sym, O_RDONLY | O_NOFOLLOW);
+                  if (fd >= 0)
+                    {
+                      close (fd);
+                      result |= 4;
+                    }
+                }
+              unlink (sym);
+            }
+            #endif
+            {
+              static char const file[] = "confdefs.h";
+              int fd = open (file, O_RDONLY | O_NOATIME);
+              if (fd < 0)
+                result |= 8;
+              else
+                {
+                  struct stat st0;
+                  if (fstat (fd, &st0) != 0)
+                    result |= 16;
+                  else
+                    {
+                      char c;
+                      sleep (1);
+                      if (read (fd, &c, 1) != 1)
+                        result |= 24;
+                      else
+                        {
+                          if (close (fd) != 0)
+                            result |= 32;
+                          else
+                            {
+                              struct stat st1;
+                              if (stat (file, &st1) != 0)
+                                result |= 40;
+                              else
+                                if (st0.st_atime != st1.st_atime)
+                                  result |= 64;
+                            }
+                        }
+                    }
+                }
+            }
+            return result;]])],
+       [gl_cv_header_working_fcntl_h=yes],
+       [case $? in #(
+        4) gl_cv_header_working_fcntl_h='no (bad O_NOFOLLOW)';; #(
+        64) gl_cv_header_working_fcntl_h='no (bad O_NOATIME)';; #(
+        68) gl_cv_header_working_fcntl_h='no (bad O_NOATIME, O_NOFOLLOW)';; #(
+         *) gl_cv_header_working_fcntl_h='no';;
+        esac],
+       [gl_cv_header_working_fcntl_h=cross-compiling])])
+
+  case $gl_cv_header_working_fcntl_h in #(
+  *O_NOATIME* | no | cross-compiling) ac_val=0;; #(
+  *) ac_val=1;;
+  esac
+  AC_DEFINE_UNQUOTED([HAVE_WORKING_O_NOATIME], [$ac_val],
+    [Define to 1 if O_NOATIME works.])
+
+  case $gl_cv_header_working_fcntl_h in #(
+  *O_NOFOLLOW* | no | cross-compiling) ac_val=0;; #(
+  *) ac_val=1;;
+  esac
+  AC_DEFINE_UNQUOTED([HAVE_WORKING_O_NOFOLLOW], [$ac_val],
+    [Define to 1 if O_NOFOLLOW works.])
+])
diff --git a/m4/gettext.m4 b/m4/gettext.m4
new file mode 100644
index 0000000..da31efe
--- /dev/null
+++ b/m4/gettext.m4
@@ -0,0 +1,405 @@
+# gettext.m4 serial 67 (gettext-0.19.6)
+dnl Copyright (C) 1995-2014 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+dnl
+dnl This file can be used in projects which are not available under
+dnl the GNU General Public License or the GNU Library General Public
+dnl License but which still want to provide support for the GNU gettext
+dnl functionality.
+dnl Please note that the actual code of the GNU gettext library is covered
+dnl by the GNU Library General Public License, and the rest of the GNU
+dnl gettext package is covered by the GNU General Public License.
+dnl They are *not* in the public domain.
+
+dnl Authors:
+dnl   Ulrich Drepper <drepper cygnus com>, 1995-2000.
+dnl   Bruno Haible <haible clisp cons org>, 2000-2006, 2008-2010.
+
+dnl Macro to add for using GNU gettext.
+
+dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]).
+dnl INTLSYMBOL can be one of 'external', 'no-libtool', 'use-libtool'. The
+dnl    default (if it is not specified or empty) is 'no-libtool'.
+dnl    INTLSYMBOL should be 'external' for packages with no intl directory,
+dnl    and 'no-libtool' or 'use-libtool' for packages with an intl directory.
+dnl    If INTLSYMBOL is 'use-libtool', then a libtool library
+dnl    $(top_builddir)/intl/libintl.la will be created (shared and/or static,
+dnl    depending on --{enable,disable}-{shared,static} and on the presence of
+dnl    AM-DISABLE-SHARED). If INTLSYMBOL is 'no-libtool', a static library
+dnl    $(top_builddir)/intl/libintl.a will be created.
+dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext
+dnl    implementations (in libc or libintl) without the ngettext() function
+dnl    will be ignored.  If NEEDSYMBOL is specified and is
+dnl    'need-formatstring-macros', then GNU gettext implementations that don't
+dnl    support the ISO C 99 <inttypes.h> formatstring macros will be ignored.
+dnl INTLDIR is used to find the intl libraries.  If empty,
+dnl    the value '$(top_builddir)/intl/' is used.
+dnl
+dnl The result of the configuration is one of three cases:
+dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled
+dnl    and used.
+dnl    Catalog format: GNU --> install in $(datadir)
+dnl    Catalog extension: .mo after installation, .gmo in source tree
+dnl 2) GNU gettext has been found in the system's C library.
+dnl    Catalog format: GNU --> install in $(datadir)
+dnl    Catalog extension: .mo after installation, .gmo in source tree
+dnl 3) No internationalization, always use English msgid.
+dnl    Catalog format: none
+dnl    Catalog extension: none
+dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur.
+dnl The use of .gmo is historical (it was needed to avoid overwriting the
+dnl GNU format catalogs when building on a platform with an X/Open gettext),
+dnl but we keep it in order not to force irrelevant filename changes on the
+dnl maintainers.
+dnl
+AC_DEFUN([AM_GNU_GETTEXT],
+[
+  dnl Argument checking.
+  ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], ,
+    [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT
+])])])])])
+  ifelse(ifelse([$1], [], [old])[]ifelse([$1], [no-libtool], [old]), [old],
+    [AC_DIAGNOSE([obsolete], [Use of AM_GNU_GETTEXT without [external] argument is deprecated.])])
+  ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], ,
+    [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT
+])])])])
+  define([gt_included_intl],
+    ifelse([$1], [external],
+      ifdef([AM_GNU_GETTEXT_][INTL_SUBDIR], [yes], [no]),
+      [yes]))
+  define([gt_libtool_suffix_prefix], ifelse([$1], [use-libtool], [l], []))
+  gt_NEEDS_INIT
+  AM_GNU_GETTEXT_NEED([$2])
+
+  AC_REQUIRE([AM_PO_SUBDIRS])dnl
+  ifelse(gt_included_intl, yes, [
+    AC_REQUIRE([AM_INTL_SUBDIR])dnl
+  ])
+
+  dnl Prerequisites of AC_LIB_LINKFLAGS_BODY.
+  AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+  AC_REQUIRE([AC_LIB_RPATH])
+
+  dnl Sometimes libintl requires libiconv, so first search for libiconv.
+  dnl Ideally we would do this search only after the
+  dnl      if test "$USE_NLS" = "yes"; then
+  dnl        if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then
+  dnl tests. But if configure.in invokes AM_ICONV after AM_GNU_GETTEXT
+  dnl the configure script would need to contain the same shell code
+  dnl again, outside any 'if'. There are two solutions:
+  dnl - Invoke AM_ICONV_LINKFLAGS_BODY here, outside any 'if'.
+  dnl - Control the expansions in more detail using AC_PROVIDE_IFELSE.
+  dnl Since AC_PROVIDE_IFELSE is only in autoconf >= 2.52 and not
+  dnl documented, we avoid it.
+  ifelse(gt_included_intl, yes, , [
+    AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY])
+  ])
+
+  dnl Sometimes, on Mac OS X, libintl requires linking with CoreFoundation.
+  gt_INTL_MACOSX
+
+  dnl Set USE_NLS.
+  AC_REQUIRE([AM_NLS])
+
+  ifelse(gt_included_intl, yes, [
+    BUILD_INCLUDED_LIBINTL=no
+    USE_INCLUDED_LIBINTL=no
+  ])
+  LIBINTL=
+  LTLIBINTL=
+  POSUB=
+
+  dnl Add a version number to the cache macros.
+  case " $gt_needs " in
+    *" need-formatstring-macros "*) gt_api_version=3 ;;
+    *" need-ngettext "*) gt_api_version=2 ;;
+    *) gt_api_version=1 ;;
+  esac
+  gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc"
+  gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl"
+
+  dnl If we use NLS figure out what method
+  if test "$USE_NLS" = "yes"; then
+    gt_use_preinstalled_gnugettext=no
+    ifelse(gt_included_intl, yes, [
+      AC_MSG_CHECKING([whether included gettext is requested])
+      AC_ARG_WITH([included-gettext],
+        [  --with-included-gettext use the GNU gettext library included here],
+        nls_cv_force_use_gnu_gettext=$withval,
+        nls_cv_force_use_gnu_gettext=no)
+      AC_MSG_RESULT([$nls_cv_force_use_gnu_gettext])
+
+      nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext"
+      if test "$nls_cv_force_use_gnu_gettext" != "yes"; then
+    ])
+        dnl User does not insist on using GNU NLS library.  Figure out what
+        dnl to use.  If GNU gettext is available we use this.  Else we have
+        dnl to fall back to GNU NLS library.
+
+        if test $gt_api_version -ge 3; then
+          gt_revision_test_code='
+#ifndef __GNU_GETTEXT_SUPPORTED_REVISION
+#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1)
+#endif
+changequote(,)dnl
+typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1];
+changequote([,])dnl
+'
+        else
+          gt_revision_test_code=
+        fi
+        if test $gt_api_version -ge 2; then
+          gt_expression_test_code=' + * ngettext ("", "", 0)'
+        else
+          gt_expression_test_code=
+        fi
+
+        AC_CACHE_CHECK([for GNU gettext in libc], [$gt_func_gnugettext_libc],
+         [AC_LINK_IFELSE(
+            [AC_LANG_PROGRAM(
+               [[
+#include <libintl.h>
+$gt_revision_test_code
+extern int _nl_msg_cat_cntr;
+extern int *_nl_domain_bindings;
+               ]],
+               [[
+bindtextdomain ("", "");
+return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings
+               ]])],
+            [eval "$gt_func_gnugettext_libc=yes"],
+            [eval "$gt_func_gnugettext_libc=no"])])
+
+        if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then
+          dnl Sometimes libintl requires libiconv, so first search for libiconv.
+          ifelse(gt_included_intl, yes, , [
+            AM_ICONV_LINK
+          ])
+          dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL
+          dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv])
+          dnl because that would add "-liconv" to LIBINTL and LTLIBINTL
+          dnl even if libiconv doesn't exist.
+          AC_LIB_LINKFLAGS_BODY([intl])
+          AC_CACHE_CHECK([for GNU gettext in libintl],
+            [$gt_func_gnugettext_libintl],
+           [gt_save_CPPFLAGS="$CPPFLAGS"
+            CPPFLAGS="$CPPFLAGS $INCINTL"
+            gt_save_LIBS="$LIBS"
+            LIBS="$LIBS $LIBINTL"
+            dnl Now see whether libintl exists and does not depend on libiconv.
+            AC_LINK_IFELSE(
+              [AC_LANG_PROGRAM(
+                 [[
+#include <libintl.h>
+$gt_revision_test_code
+extern int _nl_msg_cat_cntr;
+extern
+#ifdef __cplusplus
+"C"
+#endif
+const char *_nl_expand_alias (const char *);
+                 ]],
+                 [[
+bindtextdomain ("", "");
+return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("")
+                 ]])],
+              [eval "$gt_func_gnugettext_libintl=yes"],
+              [eval "$gt_func_gnugettext_libintl=no"])
+            dnl Now see whether libintl exists and depends on libiconv.
+            if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n 
"$LIBICONV"; then
+              LIBS="$LIBS $LIBICONV"
+              AC_LINK_IFELSE(
+                [AC_LANG_PROGRAM(
+                   [[
+#include <libintl.h>
+$gt_revision_test_code
+extern int _nl_msg_cat_cntr;
+extern
+#ifdef __cplusplus
+"C"
+#endif
+const char *_nl_expand_alias (const char *);
+                   ]],
+                   [[
+bindtextdomain ("", "");
+return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("")
+                   ]])],
+                [LIBINTL="$LIBINTL $LIBICONV"
+                 LTLIBINTL="$LTLIBINTL $LTLIBICONV"
+                 eval "$gt_func_gnugettext_libintl=yes"
+                ])
+            fi
+            CPPFLAGS="$gt_save_CPPFLAGS"
+            LIBS="$gt_save_LIBS"])
+        fi
+
+        dnl If an already present or preinstalled GNU gettext() is found,
+        dnl use it.  But if this macro is used in GNU gettext, and GNU
+        dnl gettext is already preinstalled in libintl, we update this
+        dnl libintl.  (Cf. the install rule in intl/Makefile.in.)
+        if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \
+           || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \
+                && test "$PACKAGE" != gettext-runtime \
+                && test "$PACKAGE" != gettext-tools; }; then
+          gt_use_preinstalled_gnugettext=yes
+        else
+          dnl Reset the values set by searching for libintl.
+          LIBINTL=
+          LTLIBINTL=
+          INCINTL=
+        fi
+
+    ifelse(gt_included_intl, yes, [
+        if test "$gt_use_preinstalled_gnugettext" != "yes"; then
+          dnl GNU gettext is not found in the C library.
+          dnl Fall back on included GNU gettext library.
+          nls_cv_use_gnu_gettext=yes
+        fi
+      fi
+
+      if test "$nls_cv_use_gnu_gettext" = "yes"; then
+        dnl Mark actions used to generate GNU NLS library.
+        BUILD_INCLUDED_LIBINTL=yes
+        USE_INCLUDED_LIBINTL=yes
+        LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV 
$LIBTHREAD"
+        LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a 
$LTLIBICONV $LTLIBTHREAD"
+        LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'`
+      fi
+
+      CATOBJEXT=
+      if test "$gt_use_preinstalled_gnugettext" = "yes" \
+         || test "$nls_cv_use_gnu_gettext" = "yes"; then
+        dnl Mark actions to use GNU gettext tools.
+        CATOBJEXT=.gmo
+      fi
+    ])
+
+    if test -n "$INTL_MACOSX_LIBS"; then
+      if test "$gt_use_preinstalled_gnugettext" = "yes" \
+         || test "$nls_cv_use_gnu_gettext" = "yes"; then
+        dnl Some extra flags are needed during linking.
+        LIBINTL="$LIBINTL $INTL_MACOSX_LIBS"
+        LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS"
+      fi
+    fi
+
+    if test "$gt_use_preinstalled_gnugettext" = "yes" \
+       || test "$nls_cv_use_gnu_gettext" = "yes"; then
+      AC_DEFINE([ENABLE_NLS], [1],
+        [Define to 1 if translation of program messages to the user's native language
+   is requested.])
+    else
+      USE_NLS=no
+    fi
+  fi
+
+  AC_MSG_CHECKING([whether to use NLS])
+  AC_MSG_RESULT([$USE_NLS])
+  if test "$USE_NLS" = "yes"; then
+    AC_MSG_CHECKING([where the gettext function comes from])
+    if test "$gt_use_preinstalled_gnugettext" = "yes"; then
+      if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then
+        gt_source="external libintl"
+      else
+        gt_source="libc"
+      fi
+    else
+      gt_source="included intl directory"
+    fi
+    AC_MSG_RESULT([$gt_source])
+  fi
+
+  if test "$USE_NLS" = "yes"; then
+
+    if test "$gt_use_preinstalled_gnugettext" = "yes"; then
+      if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then
+        AC_MSG_CHECKING([how to link with libintl])
+        AC_MSG_RESULT([$LIBINTL])
+        AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL])
+      fi
+
+      dnl For backward compatibility. Some packages may be using this.
+      AC_DEFINE([HAVE_GETTEXT], [1],
+       [Define if the GNU gettext() function is already present or preinstalled.])
+      AC_DEFINE([HAVE_DCGETTEXT], [1],
+       [Define if the GNU dcgettext() function is already present or preinstalled.])
+    fi
+
+    dnl We need to process the po/ directory.
+    POSUB=po
+  fi
+
+  ifelse(gt_included_intl, yes, [
+    dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL
+    dnl to 'yes' because some of the testsuite requires it.
+    if test "$PACKAGE" = gettext-runtime || test "$PACKAGE" = gettext-tools; then
+      BUILD_INCLUDED_LIBINTL=yes
+    fi
+
+    dnl Make all variables we use known to autoconf.
+    AC_SUBST([BUILD_INCLUDED_LIBINTL])
+    AC_SUBST([USE_INCLUDED_LIBINTL])
+    AC_SUBST([CATOBJEXT])
+
+    dnl For backward compatibility. Some configure.ins may be using this.
+    nls_cv_header_intl=
+    nls_cv_header_libgt=
+
+    dnl For backward compatibility. Some Makefiles may be using this.
+    DATADIRNAME=share
+    AC_SUBST([DATADIRNAME])
+
+    dnl For backward compatibility. Some Makefiles may be using this.
+    INSTOBJEXT=.mo
+    AC_SUBST([INSTOBJEXT])
+
+    dnl For backward compatibility. Some Makefiles may be using this.
+    GENCAT=gencat
+    AC_SUBST([GENCAT])
+
+    dnl For backward compatibility. Some Makefiles may be using this.
+    INTLOBJS=
+    if test "$USE_INCLUDED_LIBINTL" = yes; then
+      INTLOBJS="\$(GETTOBJS)"
+    fi
+    AC_SUBST([INTLOBJS])
+
+    dnl Enable libtool support if the surrounding package wishes it.
+    INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix
+    AC_SUBST([INTL_LIBTOOL_SUFFIX_PREFIX])
+  ])
+
+  dnl For backward compatibility. Some Makefiles may be using this.
+  INTLLIBS="$LIBINTL"
+  AC_SUBST([INTLLIBS])
+
+  dnl Make all documented variables known to autoconf.
+  AC_SUBST([LIBINTL])
+  AC_SUBST([LTLIBINTL])
+  AC_SUBST([POSUB])
+])
+
+
+dnl gt_NEEDS_INIT ensures that the gt_needs variable is initialized.
+m4_define([gt_NEEDS_INIT],
+[
+  m4_divert_text([DEFAULTS], [gt_needs=])
+  m4_define([gt_NEEDS_INIT], [])
+])
+
+
+dnl Usage: AM_GNU_GETTEXT_NEED([NEEDSYMBOL])
+AC_DEFUN([AM_GNU_GETTEXT_NEED],
+[
+  m4_divert_text([INIT_PREPARE], [gt_needs="$gt_needs $1"])
+])
+
+
+dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version])
+AC_DEFUN([AM_GNU_GETTEXT_VERSION], [])
+
+
+dnl Usage: AM_GNU_GETTEXT_REQUIRE_VERSION([gettext-version])
+AC_DEFUN([AM_GNU_GETTEXT_REQUIRE_VERSION], [])
diff --git a/m4/glib-gettext.m4 b/m4/glib-gettext.m4
new file mode 100644
index 0000000..155b1d8
--- /dev/null
+++ b/m4/glib-gettext.m4
@@ -0,0 +1,436 @@
+# Copyright (C) 1995-2002 Free Software Foundation, Inc.
+# Copyright (C) 2001-2003,2004 Red Hat, Inc.
+#
+# This file is free software, distributed under the terms of the GNU
+# General Public License.  As a special exception to the GNU General
+# Public License, this file may be distributed as part of a program
+# that contains a configuration script generated by Autoconf, under
+# the same distribution terms as the rest of that program.
+#
+# This file can be copied and used freely without restrictions.  It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+#
+# Macro to add for using GNU gettext.
+# Ulrich Drepper <drepper cygnus com>, 1995, 1996
+#
+# Modified to never use included libintl. 
+# Owen Taylor <otaylor redhat com>, 12/15/1998
+#
+# Major rework to remove unused code
+# Owen Taylor <otaylor redhat com>, 12/11/2002
+#
+# Added better handling of ALL_LINGUAS from GNU gettext version 
+# written by Bruno Haible, Owen Taylor <otaylor.redhat.com> 5/30/3002
+#
+# Modified to require ngettext
+# Matthias Clasen <mclasen redhat com> 08/06/2004
+#
+# We need this here as well, since someone might use autoconf-2.5x
+# to configure GLib then an older version to configure a package
+# using AM_GLIB_GNU_GETTEXT
+AC_PREREQ(2.53)
+
+dnl
+dnl We go to great lengths to make sure that aclocal won't 
+dnl try to pull in the installed version of these macros
+dnl when running aclocal in the glib directory.
+dnl
+m4_copy([AC_DEFUN],[glib_DEFUN])
+m4_copy([AC_REQUIRE],[glib_REQUIRE])
+dnl
+dnl At the end, if we're not within glib, we'll define the public
+dnl definitions in terms of our private definitions.
+dnl
+
+# GLIB_LC_MESSAGES
+#--------------------
+glib_DEFUN([GLIB_LC_MESSAGES],
+  [AC_CHECK_HEADERS([locale.h])
+    if test $ac_cv_header_locale_h = yes; then
+    AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES,
+      [AC_TRY_LINK([#include <locale.h>], [return LC_MESSAGES],
+       am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)])
+    if test $am_cv_val_LC_MESSAGES = yes; then
+      AC_DEFINE(HAVE_LC_MESSAGES, 1,
+        [Define if your <locale.h> file defines LC_MESSAGES.])
+    fi
+  fi])
+
+# GLIB_PATH_PROG_WITH_TEST
+#----------------------------
+dnl GLIB_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR,
+dnl   TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]])
+glib_DEFUN([GLIB_PATH_PROG_WITH_TEST],
+[# Extract the first word of "$2", so it can be a program name with args.
+set dummy $2; ac_word=[$]2
+AC_MSG_CHECKING([for $ac_word])
+AC_CACHE_VAL(ac_cv_path_$1,
+[case "[$]$1" in
+  /*)
+  ac_cv_path_$1="[$]$1" # Let the user override the test with a path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in ifelse([$5], , $PATH, [$5]); do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if [$3]; then
+       ac_cv_path_$1="$ac_dir/$ac_word"
+       break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+dnl If no 4th arg is given, leave the cache variable unset,
+dnl so AC_PATH_PROGS will keep looking.
+ifelse([$4], , , [  test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4"
+])dnl
+  ;;
+esac])dnl
+$1="$ac_cv_path_$1"
+if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then
+  AC_MSG_RESULT([$]$1)
+else
+  AC_MSG_RESULT(no)
+fi
+AC_SUBST($1)dnl
+])
+
+# GLIB_WITH_NLS
+#-----------------
+glib_DEFUN([GLIB_WITH_NLS],
+  dnl NLS is obligatory
+  [USE_NLS=yes
+    AC_SUBST(USE_NLS)
+
+    gt_cv_have_gettext=no
+
+    CATOBJEXT=NONE
+    XGETTEXT=:
+    INTLLIBS=
+
+    AC_CHECK_HEADER(libintl.h,
+     [gt_cv_func_dgettext_libintl="no"
+      libintl_extra_libs=""
+
+      #
+      # First check in libc
+      #
+      AC_CACHE_CHECK([for ngettext in libc], gt_cv_func_ngettext_libc,
+        [AC_TRY_LINK([
+#include <libintl.h>
+],
+         [return !ngettext ("","", 1)],
+         gt_cv_func_ngettext_libc=yes,
+          gt_cv_func_ngettext_libc=no)
+        ])
+  
+      if test "$gt_cv_func_ngettext_libc" = "yes" ; then
+             AC_CACHE_CHECK([for dgettext in libc], gt_cv_func_dgettext_libc,
+               [AC_TRY_LINK([
+#include <libintl.h>
+],
+                 [return !dgettext ("","")],
+                 gt_cv_func_dgettext_libc=yes,
+                 gt_cv_func_dgettext_libc=no)
+               ])
+      fi
+  
+      if test "$gt_cv_func_ngettext_libc" = "yes" ; then
+        AC_CHECK_FUNCS(bind_textdomain_codeset)
+      fi
+
+      #
+      # If we don't have everything we want, check in libintl
+      #
+      if test "$gt_cv_func_dgettext_libc" != "yes" \
+        || test "$gt_cv_func_ngettext_libc" != "yes" \
+         || test "$ac_cv_func_bind_textdomain_codeset" != "yes" ; then
+        
+        AC_CHECK_LIB(intl, bindtextdomain,
+           [AC_CHECK_LIB(intl, ngettext,
+                   [AC_CHECK_LIB(intl, dgettext,
+                                 gt_cv_func_dgettext_libintl=yes)])])
+
+       if test "$gt_cv_func_dgettext_libintl" != "yes" ; then
+         AC_MSG_CHECKING([if -liconv is needed to use gettext])
+         AC_MSG_RESULT([])
+         AC_CHECK_LIB(intl, ngettext,
+               [AC_CHECK_LIB(intl, dcgettext,
+                      [gt_cv_func_dgettext_libintl=yes
+                       libintl_extra_libs=-liconv],
+                       :,-liconv)],
+               :,-liconv)
+        fi
+
+        #
+        # If we found libintl, then check in it for bind_textdomain_codeset();
+        # we'll prefer libc if neither have bind_textdomain_codeset(),
+        # and both have dgettext and ngettext
+        #
+        if test "$gt_cv_func_dgettext_libintl" = "yes" ; then
+          glib_save_LIBS="$LIBS"
+          LIBS="$LIBS -lintl $libintl_extra_libs"
+          unset ac_cv_func_bind_textdomain_codeset
+          AC_CHECK_FUNCS(bind_textdomain_codeset)
+          LIBS="$glib_save_LIBS"
+
+          if test "$ac_cv_func_bind_textdomain_codeset" = "yes" ; then
+            gt_cv_func_dgettext_libc=no
+          else
+            if test "$gt_cv_func_dgettext_libc" = "yes" \
+               && test "$gt_cv_func_ngettext_libc" = "yes"; then
+              gt_cv_func_dgettext_libintl=no
+            fi
+          fi
+        fi
+      fi
+
+      if test "$gt_cv_func_dgettext_libc" = "yes" \
+       || test "$gt_cv_func_dgettext_libintl" = "yes"; then
+        gt_cv_have_gettext=yes
+      fi
+  
+      if test "$gt_cv_func_dgettext_libintl" = "yes"; then
+        INTLLIBS="-lintl $libintl_extra_libs"
+      fi
+  
+      if test "$gt_cv_have_gettext" = "yes"; then
+       AC_DEFINE(HAVE_GETTEXT,1,
+         [Define if the GNU gettext() function is already present or preinstalled.])
+       GLIB_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
+         [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl
+       if test "$MSGFMT" != "no"; then
+          glib_save_LIBS="$LIBS"
+          LIBS="$LIBS $INTLLIBS"
+         AC_CHECK_FUNCS(dcgettext)
+         MSGFMT_OPTS=
+         AC_MSG_CHECKING([if msgfmt accepts -c])
+         GLIB_RUN_PROG([$MSGFMT -c -o /dev/null],[
+msgid ""
+msgstr ""
+"Content-Type: text/plain; charset=UTF-8\n"
+"Project-Id-Version: test 1.0\n"
+"PO-Revision-Date: 2007-02-15 12:01+0100\n"
+"Last-Translator: test <foo bar xx>\n"
+"Language-Team: C <LL li org>\n"
+"MIME-Version: 1.0\n"
+"Content-Transfer-Encoding: 8bit\n"
+], [MSGFMT_OPTS=-c; AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])])
+         AC_SUBST(MSGFMT_OPTS)
+         AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
+         GLIB_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+           [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
+         AC_TRY_LINK(, [extern int _nl_msg_cat_cntr;
+                        return _nl_msg_cat_cntr],
+           [CATOBJEXT=.gmo 
+             DATADIRNAME=share],
+           [case $host in
+           *-*-solaris*)
+           dnl On Solaris, if bind_textdomain_codeset is in libc,
+           dnl GNU format message catalog is always supported,
+            dnl since both are added to the libc all together.
+           dnl Hence, we'd like to go with DATADIRNAME=share and
+           dnl and CATOBJEXT=.gmo in this case.
+            AC_CHECK_FUNC(bind_textdomain_codeset,
+             [CATOBJEXT=.gmo 
+               DATADIRNAME=share],
+             [CATOBJEXT=.mo
+               DATADIRNAME=lib])
+           ;;
+           *-*-openbsd*)
+           CATOBJEXT=.mo
+            DATADIRNAME=share
+           ;;
+           *)
+           CATOBJEXT=.mo
+            DATADIRNAME=lib
+           ;;
+           esac])
+          LIBS="$glib_save_LIBS"
+         INSTOBJEXT=.mo
+       else
+         gt_cv_have_gettext=no
+       fi
+      fi
+    ])
+
+    if test "$gt_cv_have_gettext" = "yes" ; then
+      AC_DEFINE(ENABLE_NLS, 1,
+        [always defined to indicate that i18n is enabled])
+    fi
+
+    dnl Test whether we really found GNU xgettext.
+    if test "$XGETTEXT" != ":"; then
+      dnl If it is not GNU xgettext we define it as : so that the
+      dnl Makefiles still can work.
+      if $XGETTEXT --omit-header /dev/null 2> /dev/null; then
+        : ;
+      else
+        AC_MSG_RESULT(
+         [found xgettext program is not GNU xgettext; ignore it])
+        XGETTEXT=":"
+      fi
+    fi
+
+    # We need to process the po/ directory.
+    POSUB=po
+
+    AC_OUTPUT_COMMANDS(
+      [case "$CONFIG_FILES" in *po/Makefile.in*)
+        sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile
+      esac])
+
+    dnl These rules are solely for the distribution goal.  While doing this
+    dnl we only have to keep exactly one list of the available catalogs
+    dnl in configure.ac.
+    for lang in $ALL_LINGUAS; do
+      GMOFILES="$GMOFILES $lang.gmo"
+      POFILES="$POFILES $lang.po"
+    done
+
+    dnl Make all variables we use known to autoconf.
+    AC_SUBST(CATALOGS)
+    AC_SUBST(CATOBJEXT)
+    AC_SUBST(DATADIRNAME)
+    AC_SUBST(GMOFILES)
+    AC_SUBST(INSTOBJEXT)
+    AC_SUBST(INTLLIBS)
+    AC_SUBST(PO_IN_DATADIR_TRUE)
+    AC_SUBST(PO_IN_DATADIR_FALSE)
+    AC_SUBST(POFILES)
+    AC_SUBST(POSUB)
+  ])
+
+# AM_GLIB_GNU_GETTEXT
+# -------------------
+# Do checks necessary for use of gettext. If a suitable implementation 
+# of gettext is found in either in libintl or in the C library,
+# it will set INTLLIBS to the libraries needed for use of gettext
+# and AC_DEFINE() HAVE_GETTEXT and ENABLE_NLS. (The shell variable
+# gt_cv_have_gettext will be set to "yes".) It will also call AC_SUBST()
+# on various variables needed by the Makefile.in.in installed by 
+# glib-gettextize.
+dnl
+AU_DEFUN([GLIB_GNU_GETTEXT],
+  [AC_REQUIRE([AC_PROG_CC])dnl
+   
+   GLIB_LC_MESSAGES
+   GLIB_WITH_NLS
+
+   if test "$gt_cv_have_gettext" = "yes"; then
+     if test "x$ALL_LINGUAS" = "x"; then
+       LINGUAS=
+     else
+       AC_MSG_CHECKING(for catalogs to be installed)
+       NEW_LINGUAS=
+       for presentlang in $ALL_LINGUAS; do
+         useit=no
+         if test "%UNSET%" != "${LINGUAS-%UNSET%}"; then
+           desiredlanguages="$LINGUAS"
+         else
+           desiredlanguages="$ALL_LINGUAS"
+         fi
+         for desiredlang in $desiredlanguages; do
+          # Use the presentlang catalog if desiredlang is
+           #   a. equal to presentlang, or
+           #   b. a variant of presentlang (because in this case,
+           #      presentlang can be used as a fallback for messages
+           #      which are not translated in the desiredlang catalog).
+           case "$desiredlang" in
+             "$presentlang"*) useit=yes;;
+           esac
+         done
+         if test $useit = yes; then
+           NEW_LINGUAS="$NEW_LINGUAS $presentlang"
+         fi
+       done
+       LINGUAS=$NEW_LINGUAS
+       AC_MSG_RESULT($LINGUAS)
+     fi
+
+     dnl Construct list of names of catalog files to be constructed.
+     if test -n "$LINGUAS"; then
+       for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done
+     fi
+   fi
+
+   dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly
+   dnl find the mkinstalldirs script in another subdir but ($top_srcdir).
+   dnl Try to locate is.
+   MKINSTALLDIRS=
+   if test -n "$ac_aux_dir"; then
+     MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs"
+   fi
+   if test -z "$MKINSTALLDIRS"; then
+     MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs"
+   fi
+   AC_SUBST(MKINSTALLDIRS)
+
+   dnl Generate list of files to be processed by xgettext which will
+   dnl be included in po/Makefile.
+   test -d po || mkdir po
+   if test "x$srcdir" != "x."; then
+     if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then
+       posrcprefix="$srcdir/"
+     else
+       posrcprefix="../$srcdir/"
+     fi
+   else
+     posrcprefix="../"
+   fi
+   rm -f po/POTFILES
+   sed -e "/^#/d" -e "/^\$/d" -e "s,.*,        $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \
+       < $srcdir/po/POTFILES.in > po/POTFILES
+  ],
+  [[$0: This macro is deprecated. You should use upstream gettext instead.]])
+
+# AM_GLIB_DEFINE_LOCALEDIR(VARIABLE)
+# -------------------------------
+# Define VARIABLE to the location where catalog files will
+# be installed by po/Makefile.
+glib_DEFUN([GLIB_DEFINE_LOCALEDIR],
+[glib_REQUIRE([GLIB_GNU_GETTEXT])dnl
+glib_save_prefix="$prefix"
+glib_save_exec_prefix="$exec_prefix"
+glib_save_datarootdir="$datarootdir"
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+test "x$exec_prefix" = xNONE && exec_prefix=$prefix
+datarootdir=`eval echo "${datarootdir}"`
+if test "x$CATOBJEXT" = "x.mo" ; then
+  localedir=`eval echo "${libdir}/locale"`
+else
+  localedir=`eval echo "${datadir}/locale"`
+fi
+prefix="$glib_save_prefix"
+exec_prefix="$glib_save_exec_prefix"
+datarootdir="$glib_save_datarootdir"
+AC_DEFINE_UNQUOTED($1, "$localedir",
+  [Define the location where the catalogs will be installed])
+])
+
+dnl
+dnl Now the definitions that aclocal will find
+dnl
+ifdef(glib_configure_ac,[],[
+AC_DEFUN([AM_GLIB_GNU_GETTEXT],[GLIB_GNU_GETTEXT($@)])
+AC_DEFUN([AM_GLIB_DEFINE_LOCALEDIR],[GLIB_DEFINE_LOCALEDIR($@)])
+])dnl
+
+# GLIB_RUN_PROG(PROGRAM, TEST-FILE, [ACTION-IF-PASS], [ACTION-IF-FAIL])
+# 
+# Create a temporary file with TEST-FILE as its contents and pass the
+# file name to PROGRAM.  Perform ACTION-IF-PASS if PROGRAM exits with
+# 0 and perform ACTION-IF-FAIL for any other exit status.
+AC_DEFUN([GLIB_RUN_PROG],
+[cat >conftest.foo <<_ACEOF
+$2
+_ACEOF
+if AC_RUN_LOG([$1 conftest.foo]); then
+  m4_ifval([$3], [$3], [:])
+m4_ifvaln([$4], [else $4])dnl
+echo "$as_me: failed input was:" >&AS_MESSAGE_LOG_FD
+sed 's/^/| /' conftest.foo >&AS_MESSAGE_LOG_FD
+fi])
+
diff --git a/m4/glibc2.m4 b/m4/glibc2.m4
new file mode 100644
index 0000000..216c863
--- /dev/null
+++ b/m4/glibc2.m4
@@ -0,0 +1,31 @@
+# glibc2.m4 serial 3
+dnl Copyright (C) 2000-2002, 2004, 2008, 2010-2015 Free Software Foundation,
+dnl Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+# Test for the GNU C Library, version 2.0 or newer.
+# From Bruno Haible.
+
+AC_DEFUN([gt_GLIBC2],
+  [
+    AC_CACHE_CHECK([whether we are using the GNU C Library 2 or newer],
+      [ac_cv_gnu_library_2],
+      [AC_EGREP_CPP([Lucky GNU user],
+        [
+#include <features.h>
+#ifdef __GNU_LIBRARY__
+ #if (__GLIBC__ >= 2) && !defined __UCLIBC__
+  Lucky GNU user
+ #endif
+#endif
+        ],
+        [ac_cv_gnu_library_2=yes],
+        [ac_cv_gnu_library_2=no])
+      ]
+    )
+    AC_SUBST([GLIBC2])
+    GLIBC2="$ac_cv_gnu_library_2"
+  ]
+)
diff --git a/m4/glibc21.m4 b/m4/glibc21.m4
new file mode 100644
index 0000000..3a971c5
--- /dev/null
+++ b/m4/glibc21.m4
@@ -0,0 +1,34 @@
+# glibc21.m4 serial 5
+dnl Copyright (C) 2000-2002, 2004, 2008, 2010-2015 Free Software Foundation,
+dnl Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+# Test for the GNU C Library, version 2.1 or newer, or uClibc.
+# From Bruno Haible.
+
+AC_DEFUN([gl_GLIBC21],
+  [
+    AC_CACHE_CHECK([whether we are using the GNU C Library >= 2.1 or uClibc],
+      [ac_cv_gnu_library_2_1],
+      [AC_EGREP_CPP([Lucky],
+        [
+#include <features.h>
+#ifdef __GNU_LIBRARY__
+ #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2)
+  Lucky GNU user
+ #endif
+#endif
+#ifdef __UCLIBC__
+ Lucky user
+#endif
+        ],
+        [ac_cv_gnu_library_2_1=yes],
+        [ac_cv_gnu_library_2_1=no])
+      ]
+    )
+    AC_SUBST([GLIBC21])
+    GLIBC21="$ac_cv_gnu_library_2_1"
+  ]
+)
diff --git a/m4/gsettings.m4 b/m4/gsettings.m4
new file mode 100644
index 0000000..35ee5aa
--- /dev/null
+++ b/m4/gsettings.m4
@@ -0,0 +1,83 @@
+dnl GLIB_GSETTINGS
+dnl Defines GSETTINGS_SCHEMAS_INSTALL which controls whether
+dnl the schema should be compiled
+dnl
+
+AC_DEFUN([GLIB_GSETTINGS],
+[
+  m4_pattern_allow([AM_V_GEN])
+  AC_ARG_ENABLE(schemas-compile,
+                AS_HELP_STRING([--disable-schemas-compile],
+                               [Disable regeneration of gschemas.compiled on install]),
+                [case ${enableval} in
+                  yes) GSETTINGS_DISABLE_SCHEMAS_COMPILE=""  ;;
+                  no)  GSETTINGS_DISABLE_SCHEMAS_COMPILE="1" ;;
+                  *) AC_MSG_ERROR([bad value ${enableval} for --enable-schemas-compile]) ;;
+                 esac])
+  AC_SUBST([GSETTINGS_DISABLE_SCHEMAS_COMPILE])
+  PKG_PROG_PKG_CONFIG([0.16])
+  AC_SUBST(gsettingsschemadir, [${datadir}/glib-2.0/schemas])
+  if test x$cross_compiling != xyes; then
+    GLIB_COMPILE_SCHEMAS=`$PKG_CONFIG --variable glib_compile_schemas gio-2.0`
+  else
+    AC_PATH_PROG(GLIB_COMPILE_SCHEMAS, glib-compile-schemas)
+  fi
+  AC_SUBST(GLIB_COMPILE_SCHEMAS)
+  if test "x$GLIB_COMPILE_SCHEMAS" = "x"; then
+    ifelse([$2],,[AC_MSG_ERROR([glib-compile-schemas not found.])],[$2])
+  else
+    ifelse([$1],,[:],[$1])
+  fi
+
+  GSETTINGS_RULES='
+.PHONY : uninstall-gsettings-schemas install-gsettings-schemas clean-gsettings-schemas
+
+mostlyclean-am: clean-gsettings-schemas
+
+gsettings__enum_file = $(addsuffix .enums.xml,$(gsettings_ENUM_NAMESPACE))
+
+%.gschema.valid: %.gschema.xml $(gsettings__enum_file)
+       $(AM_V_GEN) $(GLIB_COMPILE_SCHEMAS) --strict --dry-run $(addprefix 
--schema-file=,$(gsettings__enum_file)) --schema-file=$< && mkdir -p [$](@D) && touch [$]@
+
+all-am: $(gsettings_SCHEMAS:.xml=.valid)
+uninstall-am: uninstall-gsettings-schemas
+install-data-am: install-gsettings-schemas
+
+.SECONDARY: $(gsettings_SCHEMAS)
+
+install-gsettings-schemas: $(gsettings_SCHEMAS) $(gsettings__enum_file)
+       @$(NORMAL_INSTALL)
+       if test -n "$^"; then \
+               test -z "$(gsettingsschemadir)" || $(MKDIR_P) "$(DESTDIR)$(gsettingsschemadir)"; \
+               $(INSTALL_DATA) $^ "$(DESTDIR)$(gsettingsschemadir)"; \
+               test -n "$(GSETTINGS_DISABLE_SCHEMAS_COMPILE)$(DESTDIR)" || $(GLIB_COMPILE_SCHEMAS) 
$(gsettingsschemadir); \
+       fi
+
+uninstall-gsettings-schemas:
+       @$(NORMAL_UNINSTALL)
+       @list='\''$(gsettings_SCHEMAS) $(gsettings__enum_file)'\''; test -n "$(gsettingsschemadir)" || list=; 
\
+       files=`for p in $$list; do echo $$p; done | sed -e '\''s|^.*/||'\''`; \
+       test -n "$$files" || exit 0; \
+       echo " ( cd '\''$(DESTDIR)$(gsettingsschemadir)'\'' && rm -f" $$files ")"; \
+       cd "$(DESTDIR)$(gsettingsschemadir)" && rm -f $$files
+       test -n "$(GSETTINGS_DISABLE_SCHEMAS_COMPILE)$(DESTDIR)" || $(GLIB_COMPILE_SCHEMAS) 
$(gsettingsschemadir)
+
+clean-gsettings-schemas:
+       rm -f $(gsettings_SCHEMAS:.xml=.valid) $(gsettings__enum_file)
+
+ifdef gsettings_ENUM_NAMESPACE
+$(gsettings__enum_file): $(gsettings_ENUM_FILES)
+       $(AM_V_GEN) glib-mkenums --comments '\''<!-- @comment@ -->'\'' --fhead "<schemalist>" --vhead "  
<@type@ id='\''$(gsettings_ENUM_NAMESPACE)  EnumName@'\''>" --vprod "    <value nick='\''@valuenick@'\'' 
value='\''@valuenum@'\''/>" --vtail "  </@type@>" --ftail "</schemalist>" [$]^ > [$]  tmp && mv [$]  tmp [$]@
+endif
+'
+  _GSETTINGS_SUBST(GSETTINGS_RULES)
+])
+
+dnl _GSETTINGS_SUBST(VARIABLE)
+dnl Abstract macro to do either _AM_SUBST_NOTMAKE or AC_SUBST
+AC_DEFUN([_GSETTINGS_SUBST],
+[
+AC_SUBST([$1])
+m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([$1])])
+]
+)
diff --git a/m4/iconv.m4 b/m4/iconv.m4
new file mode 100644
index 0000000..4e37363
--- /dev/null
+++ b/m4/iconv.m4
@@ -0,0 +1,271 @@
+# iconv.m4 serial 19 (gettext-0.18.2)
+dnl Copyright (C) 2000-2002, 2007-2014 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_DEFUN([AM_ICONV_LINKFLAGS_BODY],
+[
+  dnl Prerequisites of AC_LIB_LINKFLAGS_BODY.
+  AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+  AC_REQUIRE([AC_LIB_RPATH])
+
+  dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
+  dnl accordingly.
+  AC_LIB_LINKFLAGS_BODY([iconv])
+])
+
+AC_DEFUN([AM_ICONV_LINK],
+[
+  dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and
+  dnl those with the standalone portable GNU libiconv installed).
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+
+  dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
+  dnl accordingly.
+  AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY])
+
+  dnl Add $INCICONV to CPPFLAGS before performing the following checks,
+  dnl because if the user has installed libiconv and not disabled its use
+  dnl via --without-libiconv-prefix, he wants to use it. The first
+  dnl AC_LINK_IFELSE will then fail, the second AC_LINK_IFELSE will succeed.
+  am_save_CPPFLAGS="$CPPFLAGS"
+  AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV])
+
+  AC_CACHE_CHECK([for iconv], [am_cv_func_iconv], [
+    am_cv_func_iconv="no, consider installing GNU libiconv"
+    am_cv_lib_iconv=no
+    AC_LINK_IFELSE(
+      [AC_LANG_PROGRAM(
+         [[
+#include <stdlib.h>
+#include <iconv.h>
+         ]],
+         [[iconv_t cd = iconv_open("","");
+           iconv(cd,NULL,NULL,NULL,NULL);
+           iconv_close(cd);]])],
+      [am_cv_func_iconv=yes])
+    if test "$am_cv_func_iconv" != yes; then
+      am_save_LIBS="$LIBS"
+      LIBS="$LIBS $LIBICONV"
+      AC_LINK_IFELSE(
+        [AC_LANG_PROGRAM(
+           [[
+#include <stdlib.h>
+#include <iconv.h>
+           ]],
+           [[iconv_t cd = iconv_open("","");
+             iconv(cd,NULL,NULL,NULL,NULL);
+             iconv_close(cd);]])],
+        [am_cv_lib_iconv=yes]
+        [am_cv_func_iconv=yes])
+      LIBS="$am_save_LIBS"
+    fi
+  ])
+  if test "$am_cv_func_iconv" = yes; then
+    AC_CACHE_CHECK([for working iconv], [am_cv_func_iconv_works], [
+      dnl This tests against bugs in AIX 5.1, AIX 6.1..7.1, HP-UX 11.11,
+      dnl Solaris 10.
+      am_save_LIBS="$LIBS"
+      if test $am_cv_lib_iconv = yes; then
+        LIBS="$LIBS $LIBICONV"
+      fi
+      am_cv_func_iconv_works=no
+      for ac_iconv_const in '' 'const'; do
+        AC_RUN_IFELSE(
+          [AC_LANG_PROGRAM(
+             [[
+#include <iconv.h>
+#include <string.h>
+
+#ifndef ICONV_CONST
+# define ICONV_CONST $ac_iconv_const
+#endif
+             ]],
+             [[int result = 0;
+  /* Test against AIX 5.1 bug: Failures are not distinguishable from successful
+     returns.  */
+  {
+    iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8");
+    if (cd_utf8_to_88591 != (iconv_t)(-1))
+      {
+        static ICONV_CONST char input[] = "\342\202\254"; /* EURO SIGN */
+        char buf[10];
+        ICONV_CONST char *inptr = input;
+        size_t inbytesleft = strlen (input);
+        char *outptr = buf;
+        size_t outbytesleft = sizeof (buf);
+        size_t res = iconv (cd_utf8_to_88591,
+                            &inptr, &inbytesleft,
+                            &outptr, &outbytesleft);
+        if (res == 0)
+          result |= 1;
+        iconv_close (cd_utf8_to_88591);
+      }
+  }
+  /* Test against Solaris 10 bug: Failures are not distinguishable from
+     successful returns.  */
+  {
+    iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646");
+    if (cd_ascii_to_88591 != (iconv_t)(-1))
+      {
+        static ICONV_CONST char input[] = "\263";
+        char buf[10];
+        ICONV_CONST char *inptr = input;
+        size_t inbytesleft = strlen (input);
+        char *outptr = buf;
+        size_t outbytesleft = sizeof (buf);
+        size_t res = iconv (cd_ascii_to_88591,
+                            &inptr, &inbytesleft,
+                            &outptr, &outbytesleft);
+        if (res == 0)
+          result |= 2;
+        iconv_close (cd_ascii_to_88591);
+      }
+  }
+  /* Test against AIX 6.1..7.1 bug: Buffer overrun.  */
+  {
+    iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1");
+    if (cd_88591_to_utf8 != (iconv_t)(-1))
+      {
+        static ICONV_CONST char input[] = "\304";
+        static char buf[2] = { (char)0xDE, (char)0xAD };
+        ICONV_CONST char *inptr = input;
+        size_t inbytesleft = 1;
+        char *outptr = buf;
+        size_t outbytesleft = 1;
+        size_t res = iconv (cd_88591_to_utf8,
+                            &inptr, &inbytesleft,
+                            &outptr, &outbytesleft);
+        if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD)
+          result |= 4;
+        iconv_close (cd_88591_to_utf8);
+      }
+  }
+#if 0 /* This bug could be worked around by the caller.  */
+  /* Test against HP-UX 11.11 bug: Positive return value instead of 0.  */
+  {
+    iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591");
+    if (cd_88591_to_utf8 != (iconv_t)(-1))
+      {
+        static ICONV_CONST char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
+        char buf[50];
+        ICONV_CONST char *inptr = input;
+        size_t inbytesleft = strlen (input);
+        char *outptr = buf;
+        size_t outbytesleft = sizeof (buf);
+        size_t res = iconv (cd_88591_to_utf8,
+                            &inptr, &inbytesleft,
+                            &outptr, &outbytesleft);
+        if ((int)res > 0)
+          result |= 8;
+        iconv_close (cd_88591_to_utf8);
+      }
+  }
+#endif
+  /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
+     provided.  */
+  if (/* Try standardized names.  */
+      iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1)
+      /* Try IRIX, OSF/1 names.  */
+      && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1)
+      /* Try AIX names.  */
+      && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1)
+      /* Try HP-UX names.  */
+      && iconv_open ("utf8", "eucJP") == (iconv_t)(-1))
+    result |= 16;
+  return result;
+]])],
+          [am_cv_func_iconv_works=yes], ,
+          [case "$host_os" in
+             aix* | hpux*) am_cv_func_iconv_works="guessing no" ;;
+             *)            am_cv_func_iconv_works="guessing yes" ;;
+           esac])
+        test "$am_cv_func_iconv_works" = no || break
+      done
+      LIBS="$am_save_LIBS"
+    ])
+    case "$am_cv_func_iconv_works" in
+      *no) am_func_iconv=no am_cv_lib_iconv=no ;;
+      *)   am_func_iconv=yes ;;
+    esac
+  else
+    am_func_iconv=no am_cv_lib_iconv=no
+  fi
+  if test "$am_func_iconv" = yes; then
+    AC_DEFINE([HAVE_ICONV], [1],
+      [Define if you have the iconv() function and it works.])
+  fi
+  if test "$am_cv_lib_iconv" = yes; then
+    AC_MSG_CHECKING([how to link with libiconv])
+    AC_MSG_RESULT([$LIBICONV])
+  else
+    dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV
+    dnl either.
+    CPPFLAGS="$am_save_CPPFLAGS"
+    LIBICONV=
+    LTLIBICONV=
+  fi
+  AC_SUBST([LIBICONV])
+  AC_SUBST([LTLIBICONV])
+])
+
+dnl Define AM_ICONV using AC_DEFUN_ONCE for Autoconf >= 2.64, in order to
+dnl avoid warnings like
+dnl "warning: AC_REQUIRE: `AM_ICONV' was expanded before it was required".
+dnl This is tricky because of the way 'aclocal' is implemented:
+dnl - It requires defining an auxiliary macro whose name ends in AC_DEFUN.
+dnl   Otherwise aclocal's initial scan pass would miss the macro definition.
+dnl - It requires a line break inside the AC_DEFUN_ONCE and AC_DEFUN expansions.
+dnl   Otherwise aclocal would emit many "Use of uninitialized value $1"
+dnl   warnings.
+m4_define([gl_iconv_AC_DEFUN],
+  m4_version_prereq([2.64],
+    [[AC_DEFUN_ONCE(
+        [$1], [$2])]],
+    [m4_ifdef([gl_00GNULIB],
+       [[AC_DEFUN_ONCE(
+           [$1], [$2])]],
+       [[AC_DEFUN(
+           [$1], [$2])]])]))
+gl_iconv_AC_DEFUN([AM_ICONV],
+[
+  AM_ICONV_LINK
+  if test "$am_cv_func_iconv" = yes; then
+    AC_MSG_CHECKING([for iconv declaration])
+    AC_CACHE_VAL([am_cv_proto_iconv], [
+      AC_COMPILE_IFELSE(
+        [AC_LANG_PROGRAM(
+           [[
+#include <stdlib.h>
+#include <iconv.h>
+extern
+#ifdef __cplusplus
+"C"
+#endif
+#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus)
+size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+#else
+size_t iconv();
+#endif
+           ]],
+           [[]])],
+        [am_cv_proto_iconv_arg1=""],
+        [am_cv_proto_iconv_arg1="const"])
+      am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t 
*inbytesleft, char * *outbuf, size_t *outbytesleft);"])
+    am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
+    AC_MSG_RESULT([
+         $am_cv_proto_iconv])
+    AC_DEFINE_UNQUOTED([ICONV_CONST], [$am_cv_proto_iconv_arg1],
+      [Define as const if the declaration of iconv() needs const.])
+    dnl Also substitute ICONV_CONST in the gnulib generated <iconv.h>.
+    m4_ifdef([gl_ICONV_H_DEFAULTS],
+      [AC_REQUIRE([gl_ICONV_H_DEFAULTS])
+       if test -n "$am_cv_proto_iconv_arg1"; then
+         ICONV_CONST="const"
+       fi
+      ])
+  fi
+])
diff --git a/m4/intdiv0.m4 b/m4/intdiv0.m4
new file mode 100644
index 0000000..44f9863
--- /dev/null
+++ b/m4/intdiv0.m4
@@ -0,0 +1,87 @@
+# intdiv0.m4 serial 6 (gettext-0.18.2)
+dnl Copyright (C) 2002, 2007-2008, 2010-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_DEFUN([gt_INTDIV0],
+[
+  AC_REQUIRE([AC_PROG_CC])dnl
+  AC_REQUIRE([AC_CANONICAL_HOST])dnl
+
+  AC_CACHE_CHECK([whether integer division by zero raises SIGFPE],
+    gt_cv_int_divbyzero_sigfpe,
+    [
+      gt_cv_int_divbyzero_sigfpe=
+changequote(,)dnl
+      case "$host_os" in
+        macos* | darwin[6-9]* | darwin[1-9][0-9]*)
+          # On Mac OS X 10.2 or newer, just assume the same as when cross-
+          # compiling. If we were to perform the real test, 1 Crash Report
+          # dialog window would pop up.
+          case "$host_cpu" in
+            i[34567]86 | x86_64)
+              gt_cv_int_divbyzero_sigfpe="guessing yes" ;;
+          esac
+          ;;
+      esac
+changequote([,])dnl
+      if test -z "$gt_cv_int_divbyzero_sigfpe"; then
+        AC_RUN_IFELSE(
+          [AC_LANG_SOURCE([[
+#include <stdlib.h>
+#include <signal.h>
+
+static void
+sigfpe_handler (int sig)
+{
+  /* Exit with code 0 if SIGFPE, with code 1 if any other signal.  */
+  exit (sig != SIGFPE);
+}
+
+int x = 1;
+int y = 0;
+int z;
+int nan;
+
+int main ()
+{
+  signal (SIGFPE, sigfpe_handler);
+/* IRIX and AIX (when "xlc -qcheck" is used) yield signal SIGTRAP.  */
+#if (defined (__sgi) || defined (_AIX)) && defined (SIGTRAP)
+  signal (SIGTRAP, sigfpe_handler);
+#endif
+/* Linux/SPARC yields signal SIGILL.  */
+#if defined (__sparc__) && defined (__linux__)
+  signal (SIGILL, sigfpe_handler);
+#endif
+
+  z = x / y;
+  nan = y / y;
+  exit (2);
+}
+]])],
+          [gt_cv_int_divbyzero_sigfpe=yes],
+          [gt_cv_int_divbyzero_sigfpe=no],
+          [
+            # Guess based on the CPU.
+changequote(,)dnl
+            case "$host_cpu" in
+              alpha* | i[34567]86 | x86_64 | m68k | s390*)
+                gt_cv_int_divbyzero_sigfpe="guessing yes";;
+              *)
+                gt_cv_int_divbyzero_sigfpe="guessing no";;
+            esac
+changequote([,])dnl
+          ])
+      fi
+    ])
+  case "$gt_cv_int_divbyzero_sigfpe" in
+    *yes) value=1;;
+    *) value=0;;
+  esac
+  AC_DEFINE_UNQUOTED([INTDIV0_RAISES_SIGFPE], [$value],
+    [Define if integer division by zero raises signal SIGFPE.])
+])
diff --git a/m4/intl.m4 b/m4/intl.m4
new file mode 100644
index 0000000..70d9a9e
--- /dev/null
+++ b/m4/intl.m4
@@ -0,0 +1,304 @@
+# intl.m4 serial 29 (gettext-0.19)
+dnl Copyright (C) 1995-2014 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+dnl
+dnl This file can can be used in projects which are not available under
+dnl the GNU General Public License or the GNU Library General Public
+dnl License but which still want to provide support for the GNU gettext
+dnl functionality.
+dnl Please note that the actual code of the GNU gettext library is covered
+dnl by the GNU Library General Public License, and the rest of the GNU
+dnl gettext package package is covered by the GNU General Public License.
+dnl They are *not* in the public domain.
+
+dnl Authors:
+dnl   Ulrich Drepper <drepper cygnus com>, 1995-2000.
+dnl   Bruno Haible <haible clisp cons org>, 2000-2009.
+
+AC_PREREQ([2.60])
+
+dnl Checks for all prerequisites of the intl subdirectory,
+dnl except for INTL_LIBTOOL_SUFFIX_PREFIX (and possibly LIBTOOL), INTLOBJS,
+dnl            USE_INCLUDED_LIBINTL, BUILD_INCLUDED_LIBINTL.
+AC_DEFUN([AM_INTL_SUBDIR],
+[
+  AC_REQUIRE([AC_PROG_INSTALL])dnl
+  AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+  AC_REQUIRE([AC_PROG_CC])dnl
+  AC_REQUIRE([AC_CANONICAL_HOST])dnl
+  AC_REQUIRE([gt_GLIBC2])dnl
+  AC_REQUIRE([AC_PROG_RANLIB])dnl
+  AC_REQUIRE([gl_VISIBILITY])dnl
+  AC_REQUIRE([gt_INTL_SUBDIR_CORE])dnl
+  AC_REQUIRE([AC_TYPE_LONG_LONG_INT])dnl
+  AC_REQUIRE([gt_TYPE_WCHAR_T])dnl
+  AC_REQUIRE([gt_TYPE_WINT_T])dnl
+  AC_REQUIRE([gl_AC_HEADER_INTTYPES_H])
+  AC_REQUIRE([gt_TYPE_INTMAX_T])
+  AC_REQUIRE([gt_PRINTF_POSIX])
+  AC_REQUIRE([gl_GLIBC21])dnl
+  AC_REQUIRE([gl_XSIZE])dnl
+  AC_REQUIRE([gl_FCNTL_O_FLAGS])dnl
+  AC_REQUIRE([gt_INTL_MACOSX])dnl
+  AC_REQUIRE([gl_EXTERN_INLINE])dnl
+  AC_REQUIRE([gt_GL_ATTRIBUTE])dnl
+
+  dnl Support for automake's --enable-silent-rules.
+  case "$enable_silent_rules" in
+    yes) INTL_DEFAULT_VERBOSITY=0;;
+    no)  INTL_DEFAULT_VERBOSITY=1;;
+    *)   INTL_DEFAULT_VERBOSITY=1;;
+  esac
+  AC_SUBST([INTL_DEFAULT_VERBOSITY])
+
+  AC_CHECK_TYPE([ptrdiff_t], ,
+    [AC_DEFINE([ptrdiff_t], [long],
+       [Define as the type of the result of subtracting two pointers, if the system doesn't define it.])
+    ])
+  AC_CHECK_HEADERS([features.h stddef.h stdlib.h string.h])
+  AC_CHECK_FUNCS([asprintf fwprintf newlocale putenv setenv setlocale \
+    snprintf strnlen wcslen wcsnlen mbrtowc wcrtomb])
+
+  dnl Use the _snprintf function only if it is declared (because on NetBSD it
+  dnl is defined as a weak alias of snprintf; we prefer to use the latter).
+  AC_CHECK_DECLS([_snprintf, _snwprintf], , , [#include <stdio.h>])
+
+  dnl Use the *_unlocked functions only if they are declared.
+  dnl (because some of them were defined without being declared in Solaris
+  dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built
+  dnl on Solaris 2.5.1 to run on Solaris 2.6).
+  AC_CHECK_DECLS([getc_unlocked], , , [#include <stdio.h>])
+
+  case $gt_cv_func_printf_posix in
+    *yes) HAVE_POSIX_PRINTF=1 ;;
+    *) HAVE_POSIX_PRINTF=0 ;;
+  esac
+  AC_SUBST([HAVE_POSIX_PRINTF])
+  if test "$ac_cv_func_asprintf" = yes; then
+    HAVE_ASPRINTF=1
+  else
+    HAVE_ASPRINTF=0
+  fi
+  AC_SUBST([HAVE_ASPRINTF])
+  if test "$ac_cv_func_snprintf" = yes; then
+    HAVE_SNPRINTF=1
+  else
+    HAVE_SNPRINTF=0
+  fi
+  AC_SUBST([HAVE_SNPRINTF])
+  if test "$ac_cv_func_newlocale" = yes; then
+    HAVE_NEWLOCALE=1
+  else
+    HAVE_NEWLOCALE=0
+  fi
+  AC_SUBST([HAVE_NEWLOCALE])
+  if test "$ac_cv_func_wprintf" = yes; then
+    HAVE_WPRINTF=1
+  else
+    HAVE_WPRINTF=0
+  fi
+  AC_SUBST([HAVE_WPRINTF])
+
+  AM_LANGINFO_CODESET
+  gt_LC_MESSAGES
+
+  dnl Compilation on mingw and Cygwin needs special Makefile rules, because
+  dnl 1. when we install a shared library, we must arrange to export
+  dnl    auxiliary pointer variables for every exported variable,
+  dnl 2. when we install a shared library and a static library simultaneously,
+  dnl    the include file specifies __declspec(dllimport) and therefore we
+  dnl    must arrange to define the auxiliary pointer variables for the
+  dnl    exported variables _also_ in the static library.
+  if test "$enable_shared" = yes; then
+    case "$host_os" in
+      mingw* | cygwin*) is_woe32dll=yes ;;
+      *) is_woe32dll=no ;;
+    esac
+  else
+    is_woe32dll=no
+  fi
+  WOE32DLL=$is_woe32dll
+  AC_SUBST([WOE32DLL])
+
+  dnl On mingw and Cygwin, we can activate special Makefile rules which add
+  dnl version information to the shared libraries and executables.
+  case "$host_os" in
+    mingw* | cygwin*) is_woe32=yes ;;
+    *) is_woe32=no ;;
+  esac
+  WOE32=$is_woe32
+  AC_SUBST([WOE32])
+  if test $WOE32 = yes; then
+    dnl Check for a program that compiles Windows resource files.
+    AC_CHECK_TOOL([WINDRES], [windres])
+  fi
+
+  dnl Determine whether when creating a library, "-lc" should be passed to
+  dnl libtool or not. On many platforms, it is required for the libtool option
+  dnl -no-undefined to work. On HP-UX, however, the -lc - stored by libtool
+  dnl in the *.la files - makes it impossible to create multithreaded programs,
+  dnl because libtool also reorders the -lc to come before the -pthread, and
+  dnl this disables pthread_create() <http://docs.hp.com/en/1896/pthreads.html>.
+  case "$host_os" in
+    hpux*) LTLIBC="" ;;
+    *)     LTLIBC="-lc" ;;
+  esac
+  AC_SUBST([LTLIBC])
+
+  dnl Rename some macros and functions used for locking.
+  AH_BOTTOM([
+#define __libc_lock_t                   gl_lock_t
+#define __libc_lock_define              gl_lock_define
+#define __libc_lock_define_initialized  gl_lock_define_initialized
+#define __libc_lock_init                gl_lock_init
+#define __libc_lock_lock                gl_lock_lock
+#define __libc_lock_unlock              gl_lock_unlock
+#define __libc_lock_recursive_t                   gl_recursive_lock_t
+#define __libc_lock_define_recursive              gl_recursive_lock_define
+#define __libc_lock_define_initialized_recursive  gl_recursive_lock_define_initialized
+#define __libc_lock_init_recursive                gl_recursive_lock_init
+#define __libc_lock_lock_recursive                gl_recursive_lock_lock
+#define __libc_lock_unlock_recursive              gl_recursive_lock_unlock
+#define glthread_in_use  libintl_thread_in_use
+#define glthread_lock_init_func     libintl_lock_init_func
+#define glthread_lock_lock_func     libintl_lock_lock_func
+#define glthread_lock_unlock_func   libintl_lock_unlock_func
+#define glthread_lock_destroy_func  libintl_lock_destroy_func
+#define glthread_rwlock_init_multithreaded     libintl_rwlock_init_multithreaded
+#define glthread_rwlock_init_func              libintl_rwlock_init_func
+#define glthread_rwlock_rdlock_multithreaded   libintl_rwlock_rdlock_multithreaded
+#define glthread_rwlock_rdlock_func            libintl_rwlock_rdlock_func
+#define glthread_rwlock_wrlock_multithreaded   libintl_rwlock_wrlock_multithreaded
+#define glthread_rwlock_wrlock_func            libintl_rwlock_wrlock_func
+#define glthread_rwlock_unlock_multithreaded   libintl_rwlock_unlock_multithreaded
+#define glthread_rwlock_unlock_func            libintl_rwlock_unlock_func
+#define glthread_rwlock_destroy_multithreaded  libintl_rwlock_destroy_multithreaded
+#define glthread_rwlock_destroy_func           libintl_rwlock_destroy_func
+#define glthread_recursive_lock_init_multithreaded     libintl_recursive_lock_init_multithreaded
+#define glthread_recursive_lock_init_func              libintl_recursive_lock_init_func
+#define glthread_recursive_lock_lock_multithreaded     libintl_recursive_lock_lock_multithreaded
+#define glthread_recursive_lock_lock_func              libintl_recursive_lock_lock_func
+#define glthread_recursive_lock_unlock_multithreaded   libintl_recursive_lock_unlock_multithreaded
+#define glthread_recursive_lock_unlock_func            libintl_recursive_lock_unlock_func
+#define glthread_recursive_lock_destroy_multithreaded  libintl_recursive_lock_destroy_multithreaded
+#define glthread_recursive_lock_destroy_func           libintl_recursive_lock_destroy_func
+#define glthread_once_func            libintl_once_func
+#define glthread_once_singlethreaded  libintl_once_singlethreaded
+#define glthread_once_multithreaded   libintl_once_multithreaded
+])
+])
+
+
+dnl Checks for the core files of the intl subdirectory:
+dnl   dcigettext.c
+dnl   eval-plural.h
+dnl   explodename.c
+dnl   finddomain.c
+dnl   gettextP.h
+dnl   gmo.h
+dnl   hash-string.h hash-string.c
+dnl   l10nflist.c
+dnl   libgnuintl.h.in (except the *printf stuff)
+dnl   loadinfo.h
+dnl   loadmsgcat.c
+dnl   localealias.c
+dnl   log.c
+dnl   plural-exp.h plural-exp.c
+dnl   plural.y
+dnl Used by libglocale.
+AC_DEFUN([gt_INTL_SUBDIR_CORE],
+[
+  AC_REQUIRE([AC_C_INLINE])dnl
+  AC_REQUIRE([AC_TYPE_SIZE_T])dnl
+  AC_REQUIRE([gl_AC_HEADER_STDINT_H])
+  AC_REQUIRE([AC_FUNC_ALLOCA])dnl
+  AC_REQUIRE([AC_FUNC_MMAP])dnl
+  AC_REQUIRE([gt_INTDIV0])dnl
+  AC_REQUIRE([gl_AC_TYPE_UINTMAX_T])dnl
+  AC_REQUIRE([gt_INTTYPES_PRI])dnl
+  AC_REQUIRE([gl_LOCK])dnl
+
+  AC_LINK_IFELSE(
+    [AC_LANG_PROGRAM(
+       [[int foo (int a) { a = __builtin_expect (a, 10); return a == 10 ? 0 : 1; }]],
+       [[]])],
+    [AC_DEFINE([HAVE_BUILTIN_EXPECT], [1],
+       [Define to 1 if the compiler understands __builtin_expect.])])
+
+  AC_CHECK_HEADERS([argz.h inttypes.h limits.h unistd.h sys/param.h])
+  AC_CHECK_FUNCS([getcwd getegid geteuid getgid getuid mempcpy munmap \
+    stpcpy strcasecmp strdup strtoul tsearch uselocale argz_count \
+    argz_stringify argz_next __fsetlocking])
+
+  dnl Solaris 12 provides getlocalename_l, while Illumos doesn't have
+  dnl it nor the equivalent.
+  if test $ac_cv_func_uselocale = yes; then
+    AC_CHECK_FUNCS([getlocalename_l])
+  fi
+
+  dnl Use the *_unlocked functions only if they are declared.
+  dnl (because some of them were defined without being declared in Solaris
+  dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built
+  dnl on Solaris 2.5.1 to run on Solaris 2.6).
+  AC_CHECK_DECLS([feof_unlocked, fgets_unlocked], , , [#include <stdio.h>])
+
+  AM_ICONV
+
+  dnl intl/plural.c is generated from intl/plural.y. It requires bison,
+  dnl because plural.y uses bison specific features. It requires at least
+  dnl bison-2.7 for %define api.pure.
+  dnl bison is only needed for the maintainer (who touches plural.y). But in
+  dnl order to avoid separate Makefiles or --enable-maintainer-mode, we put
+  dnl the rule in general Makefile. Now, some people carelessly touch the
+  dnl files or have a broken "make" program, hence the plural.c rule will
+  dnl sometimes fire. To avoid an error, defines BISON to ":" if it is not
+  dnl present or too old.
+  AC_CHECK_PROGS([INTLBISON], [bison])
+  if test -z "$INTLBISON"; then
+    ac_verc_fail=yes
+  else
+    dnl Found it, now check the version.
+    AC_MSG_CHECKING([version of bison])
+changequote(<<,>>)dnl
+    ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'`
+    case $ac_prog_version in
+      '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
+      2.[7-9]* | [3-9].*)
+changequote([,])dnl
+         ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
+      *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
+    esac
+    AC_MSG_RESULT([$ac_prog_version])
+  fi
+  if test $ac_verc_fail = yes; then
+    INTLBISON=:
+  fi
+])
+
+dnl Copies _GL_UNUSED and _GL_ATTRIBUTE_PURE definitions from
+dnl gnulib-common.m4 as a fallback, if the project isn't using Gnulib.
+AC_DEFUN([gt_GL_ATTRIBUTE], [
+  m4_ifndef([gl_[]COMMON],
+    AH_VERBATIM([gt_gl_attribute],
+[/* Define as a marker that can be attached to declarations that might not
+    be used.  This helps to reduce warnings, such as from
+    GCC -Wunused-parameter.  */
+#ifndef _GL_UNUSED
+# if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+#  define _GL_UNUSED __attribute__ ((__unused__))
+# else
+#  define _GL_UNUSED
+# endif
+#endif
+
+/* The __pure__ attribute was added in gcc 2.96.  */
+#ifndef _GL_ATTRIBUTE_PURE
+# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
+#  define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
+# else
+#  define _GL_ATTRIBUTE_PURE /* empty */
+# endif
+#endif
+]))])
diff --git a/m4/intldir.m4 b/m4/intldir.m4
new file mode 100644
index 0000000..73b672a
--- /dev/null
+++ b/m4/intldir.m4
@@ -0,0 +1,19 @@
+# intldir.m4 serial 2 (gettext-0.18)
+dnl Copyright (C) 2006, 2009-2014 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+dnl
+dnl This file can can be used in projects which are not available under
+dnl the GNU General Public License or the GNU Library General Public
+dnl License but which still want to provide support for the GNU gettext
+dnl functionality.
+dnl Please note that the actual code of the GNU gettext library is covered
+dnl by the GNU Library General Public License, and the rest of the GNU
+dnl gettext package package is covered by the GNU General Public License.
+dnl They are *not* in the public domain.
+
+AC_PREREQ([2.52])
+
+dnl Tells the AM_GNU_GETTEXT macro to consider an intl/ directory.
+AC_DEFUN([AM_GNU_GETTEXT_INTL_SUBDIR], [])
diff --git a/m4/intlmacosx.m4 b/m4/intlmacosx.m4
new file mode 100644
index 0000000..bba7b3d
--- /dev/null
+++ b/m4/intlmacosx.m4
@@ -0,0 +1,56 @@
+# intlmacosx.m4 serial 5 (gettext-0.18.2)
+dnl Copyright (C) 2004-2014 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+dnl
+dnl This file can be used in projects which are not available under
+dnl the GNU General Public License or the GNU Library General Public
+dnl License but which still want to provide support for the GNU gettext
+dnl functionality.
+dnl Please note that the actual code of the GNU gettext library is covered
+dnl by the GNU Library General Public License, and the rest of the GNU
+dnl gettext package is covered by the GNU General Public License.
+dnl They are *not* in the public domain.
+
+dnl Checks for special options needed on Mac OS X.
+dnl Defines INTL_MACOSX_LIBS.
+AC_DEFUN([gt_INTL_MACOSX],
+[
+  dnl Check for API introduced in Mac OS X 10.2.
+  AC_CACHE_CHECK([for CFPreferencesCopyAppValue],
+    [gt_cv_func_CFPreferencesCopyAppValue],
+    [gt_save_LIBS="$LIBS"
+     LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation"
+     AC_LINK_IFELSE(
+       [AC_LANG_PROGRAM(
+          [[#include <CoreFoundation/CFPreferences.h>]],
+          [[CFPreferencesCopyAppValue(NULL, NULL)]])],
+       [gt_cv_func_CFPreferencesCopyAppValue=yes],
+       [gt_cv_func_CFPreferencesCopyAppValue=no])
+     LIBS="$gt_save_LIBS"])
+  if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then
+    AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], [1],
+      [Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in the CoreFoundation 
framework.])
+  fi
+  dnl Check for API introduced in Mac OS X 10.3.
+  AC_CACHE_CHECK([for CFLocaleCopyCurrent], [gt_cv_func_CFLocaleCopyCurrent],
+    [gt_save_LIBS="$LIBS"
+     LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation"
+     AC_LINK_IFELSE(
+       [AC_LANG_PROGRAM(
+          [[#include <CoreFoundation/CFLocale.h>]],
+          [[CFLocaleCopyCurrent();]])],
+       [gt_cv_func_CFLocaleCopyCurrent=yes],
+       [gt_cv_func_CFLocaleCopyCurrent=no])
+     LIBS="$gt_save_LIBS"])
+  if test $gt_cv_func_CFLocaleCopyCurrent = yes; then
+    AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], [1],
+      [Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the CoreFoundation framework.])
+  fi
+  INTL_MACOSX_LIBS=
+  if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then
+    INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation"
+  fi
+  AC_SUBST([INTL_MACOSX_LIBS])
+])
diff --git a/m4/intltool.m4 b/m4/intltool.m4
new file mode 100644
index 0000000..c25b7b1
--- /dev/null
+++ b/m4/intltool.m4
@@ -0,0 +1,212 @@
+## intltool.m4 - Configure intltool for the target system. -*-Shell-script-*-
+## Copyright (C) 2001 Eazel, Inc.
+## Author: Maciej Stachowiak <mjs noisehavoc org>
+##         Kenneth Christiansen <kenneth gnu org>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+##
+## As a special exception to the GNU General Public License, if you
+## distribute this file as part of a program that contains a
+## configuration script generated by Autoconf, you may include it under
+## the same distribution terms that you use for the rest of that program.
+
+dnl IT_PROG_INTLTOOL([MINIMUM-VERSION], [no-xml])
+# serial 42 IT_PROG_INTLTOOL
+AC_DEFUN([IT_PROG_INTLTOOL], [
+AC_PREREQ([2.50])dnl
+AC_REQUIRE([AM_NLS])dnl
+
+case "$am__api_version" in
+    1.[01234])
+       AC_MSG_ERROR([Automake 1.5 or newer is required to use intltool])
+    ;;
+    *)
+    ;;
+esac
+
+INTLTOOL_REQUIRED_VERSION_AS_INT=`echo $1 | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'`
+INTLTOOL_APPLIED_VERSION=`intltool-update --version | head -1 | cut -d" " -f3`
+INTLTOOL_APPLIED_VERSION_AS_INT=`echo $INTLTOOL_APPLIED_VERSION | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + 
$ 3; }'`
+if test -n "$1"; then
+    AC_MSG_CHECKING([for intltool >= $1])
+    AC_MSG_RESULT([$INTLTOOL_APPLIED_VERSION found])
+    test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge "$INTLTOOL_REQUIRED_VERSION_AS_INT" ||
+       AC_MSG_ERROR([Your intltool is too old.  You need intltool $1 or later.])
+fi
+
+AC_PATH_PROG(INTLTOOL_UPDATE, [intltool-update])
+AC_PATH_PROG(INTLTOOL_MERGE, [intltool-merge])
+AC_PATH_PROG(INTLTOOL_EXTRACT, [intltool-extract])
+if test -z "$INTLTOOL_UPDATE" -o -z "$INTLTOOL_MERGE" -o -z "$INTLTOOL_EXTRACT"; then
+    AC_MSG_ERROR([The intltool scripts were not found. Please install intltool.])
+fi
+
+if test -z "$AM_DEFAULT_VERBOSITY"; then
+  AM_DEFAULT_VERBOSITY=1
+fi
+AC_SUBST([AM_DEFAULT_VERBOSITY])
+
+INTLTOOL_V_MERGE='$(INTLTOOL__v_MERGE_$(V))'
+INTLTOOL__v_MERGE_='$(INTLTOOL__v_MERGE_$(AM_DEFAULT_VERBOSITY))'
+INTLTOOL__v_MERGE_0='@echo "  ITMRG " [$]@;'
+AC_SUBST(INTLTOOL_V_MERGE)
+AC_SUBST(INTLTOOL__v_MERGE_)
+AC_SUBST(INTLTOOL__v_MERGE_0)
+
+INTLTOOL_V_MERGE_OPTIONS='$(intltool__v_merge_options_$(V))'
+intltool__v_merge_options_='$(intltool__v_merge_options_$(AM_DEFAULT_VERBOSITY))'
+intltool__v_merge_options_0='-q'
+AC_SUBST(INTLTOOL_V_MERGE_OPTIONS)
+AC_SUBST(intltool__v_merge_options_)
+AC_SUBST(intltool__v_merge_options_0)
+
+  INTLTOOL_DESKTOP_RULE='%.desktop:   %.desktop.in   $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; 
$(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c 
$(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+INTLTOOL_DIRECTORY_RULE='%.directory: %.directory.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; 
$(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c 
$(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+     INTLTOOL_KEYS_RULE='%.keys:      %.keys.in      $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; 
$(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -k -u -c 
$(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+     INTLTOOL_PROP_RULE='%.prop:      %.prop.in      $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; 
$(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c 
$(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+      INTLTOOL_OAF_RULE='%.oaf:       %.oaf.in       $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; 
$(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -o -p $(top_srcdir)/po $< [$]@'
+     INTLTOOL_PONG_RULE='%.pong:      %.pong.in      $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; 
$(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c 
$(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+   INTLTOOL_SERVER_RULE='%.server:    %.server.in    $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; 
$(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -o -u -c 
$(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+    INTLTOOL_SHEET_RULE='%.sheet:     %.sheet.in     $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; 
$(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c 
$(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+INTLTOOL_SOUNDLIST_RULE='%.soundlist: %.soundlist.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; 
$(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c 
$(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+       INTLTOOL_UI_RULE='%.ui:        %.ui.in        $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; 
$(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c 
$(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+      INTLTOOL_XML_RULE='%.xml:       %.xml.in       $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; 
$(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c 
$(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+if test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge 5000; then
+      INTLTOOL_XML_NOMERGE_RULE='%.xml:       %.xml.in       $(INTLTOOL_MERGE) ; $(INTLTOOL_V_MERGE)LC_ALL=C 
$(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u --no-translations $< [$]@'
+else
+      INTLTOOL_XML_NOMERGE_RULE='%.xml:       %.xml.in       $(INTLTOOL_MERGE) ; 
$(INTLTOOL_V_MERGE)_it_tmp_dir=tmp.intltool.[$][$]RANDOM && mkdir [$][$]_it_tmp_dir && LC_ALL=C 
$(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u [$][$]_it_tmp_dir $< [$]@ && rmdir [$][$]_it_tmp_dir'
+fi
+      INTLTOOL_XAM_RULE='%.xam:       %.xml.in       $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; 
$(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c 
$(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+      INTLTOOL_KBD_RULE='%.kbd:       %.kbd.in       $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; 
$(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -m -c 
$(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+    INTLTOOL_CAVES_RULE='%.caves:     %.caves.in     $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; 
$(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c 
$(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+  INTLTOOL_SCHEMAS_RULE='%.schemas:   %.schemas.in   $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; 
$(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -s -u -c 
$(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+    INTLTOOL_THEME_RULE='%.theme:     %.theme.in     $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; 
$(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c 
$(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+    INTLTOOL_SERVICE_RULE='%.service: %.service.in   $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; 
$(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c 
$(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+   INTLTOOL_POLICY_RULE='%.policy:    %.policy.in    $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; 
$(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c 
$(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+
+_IT_SUBST(INTLTOOL_DESKTOP_RULE)
+_IT_SUBST(INTLTOOL_DIRECTORY_RULE)
+_IT_SUBST(INTLTOOL_KEYS_RULE)
+_IT_SUBST(INTLTOOL_PROP_RULE)
+_IT_SUBST(INTLTOOL_OAF_RULE)
+_IT_SUBST(INTLTOOL_PONG_RULE)
+_IT_SUBST(INTLTOOL_SERVER_RULE)
+_IT_SUBST(INTLTOOL_SHEET_RULE)
+_IT_SUBST(INTLTOOL_SOUNDLIST_RULE)
+_IT_SUBST(INTLTOOL_UI_RULE)
+_IT_SUBST(INTLTOOL_XAM_RULE)
+_IT_SUBST(INTLTOOL_KBD_RULE)
+_IT_SUBST(INTLTOOL_XML_RULE)
+_IT_SUBST(INTLTOOL_XML_NOMERGE_RULE)
+_IT_SUBST(INTLTOOL_CAVES_RULE)
+_IT_SUBST(INTLTOOL_SCHEMAS_RULE)
+_IT_SUBST(INTLTOOL_THEME_RULE)
+_IT_SUBST(INTLTOOL_SERVICE_RULE)
+_IT_SUBST(INTLTOOL_POLICY_RULE)
+
+# Check the gettext tools to make sure they are GNU
+AC_PATH_PROG(XGETTEXT, xgettext)
+AC_PATH_PROG(MSGMERGE, msgmerge)
+AC_PATH_PROG(MSGFMT, msgfmt)
+AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
+if test -z "$XGETTEXT" -o -z "$MSGMERGE" -o -z "$MSGFMT"; then
+    AC_MSG_ERROR([GNU gettext tools not found; required for intltool])
+fi
+xgversion="`$XGETTEXT --version|grep '(GNU ' 2> /dev/null`"
+mmversion="`$MSGMERGE --version|grep '(GNU ' 2> /dev/null`"
+mfversion="`$MSGFMT --version|grep '(GNU ' 2> /dev/null`"
+if test -z "$xgversion" -o -z "$mmversion" -o -z "$mfversion"; then
+    AC_MSG_ERROR([GNU gettext tools not found; required for intltool])
+fi
+
+AC_PATH_PROG(INTLTOOL_PERL, perl)
+if test -z "$INTLTOOL_PERL"; then
+   AC_MSG_ERROR([perl not found])
+fi
+AC_MSG_CHECKING([for perl >= 5.8.1])
+$INTLTOOL_PERL -e "use 5.8.1;" > /dev/null 2>&1
+if test $? -ne 0; then
+   AC_MSG_ERROR([perl 5.8.1 is required for intltool])
+else
+   IT_PERL_VERSION=`$INTLTOOL_PERL -e "printf '%vd', $^V"`
+   AC_MSG_RESULT([$IT_PERL_VERSION])
+fi
+if test "x$2" != "xno-xml"; then
+   AC_MSG_CHECKING([for XML::Parser])
+   if `$INTLTOOL_PERL -e "require XML::Parser" 2>/dev/null`; then
+       AC_MSG_RESULT([ok])
+   else
+       AC_MSG_ERROR([XML::Parser perl module is required for intltool])
+   fi
+fi
+
+# Substitute ALL_LINGUAS so we can use it in po/Makefile
+AC_SUBST(ALL_LINGUAS)
+
+IT_PO_SUBDIR([po])
+
+])
+
+
+# IT_PO_SUBDIR(DIRNAME)
+# ---------------------
+# All po subdirs have to be declared with this macro; the subdir "po" is
+# declared by IT_PROG_INTLTOOL.
+#
+AC_DEFUN([IT_PO_SUBDIR],
+[AC_PREREQ([2.53])dnl We use ac_top_srcdir inside AC_CONFIG_COMMANDS.
+dnl
+dnl The following CONFIG_COMMANDS should be executed at the very end
+dnl of config.status.
+AC_CONFIG_COMMANDS_PRE([
+  AC_CONFIG_COMMANDS([$1/stamp-it], [
+    if [ ! grep "^# INTLTOOL_MAKEFILE$" "$1/Makefile.in" > /dev/null ]; then
+       AC_MSG_ERROR([$1/Makefile.in.in was not created by intltoolize.])
+    fi
+    rm -f "$1/stamp-it" "$1/stamp-it.tmp" "$1/POTFILES" "$1/Makefile.tmp"
+    >"$1/stamp-it.tmp"
+    [sed '/^#/d
+        s/^[[].*] *//
+        /^[    ]*$/d
+       '"s|^|  $ac_top_srcdir/|" \
+      "$srcdir/$1/POTFILES.in" | sed '$!s/$/ \\/' >"$1/POTFILES"
+    ]
+    [sed '/^POTFILES =/,/[^\\]$/ {
+               /^POTFILES =/!d
+               r $1/POTFILES
+         }
+        ' "$1/Makefile.in" >"$1/Makefile"]
+    rm -f "$1/Makefile.tmp"
+    mv "$1/stamp-it.tmp" "$1/stamp-it"
+  ])
+])dnl
+])
+
+# _IT_SUBST(VARIABLE)
+# -------------------
+# Abstract macro to do either _AM_SUBST_NOTMAKE or AC_SUBST
+#
+AC_DEFUN([_IT_SUBST],
+[
+AC_SUBST([$1])
+m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([$1])])
+]
+)
+
+# deprecated macros
+AU_ALIAS([AC_PROG_INTLTOOL], [IT_PROG_INTLTOOL])
+# A hint is needed for aclocal from Automake <= 1.9.4:
+# AC_DEFUN([AC_PROG_INTLTOOL], ...)
+
diff --git a/m4/intmax.m4 b/m4/intmax.m4
new file mode 100644
index 0000000..08b3a38
--- /dev/null
+++ b/m4/intmax.m4
@@ -0,0 +1,36 @@
+# intmax.m4 serial 6 (gettext-0.18.2)
+dnl Copyright (C) 2002-2005, 2008-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+dnl Test whether the system has the 'intmax_t' type, but don't attempt to
+dnl find a replacement if it is lacking.
+
+AC_DEFUN([gt_TYPE_INTMAX_T],
+[
+  AC_REQUIRE([gl_AC_HEADER_INTTYPES_H])
+  AC_REQUIRE([gl_AC_HEADER_STDINT_H])
+  AC_CACHE_CHECK([for intmax_t], [gt_cv_c_intmax_t],
+    [AC_COMPILE_IFELSE(
+       [AC_LANG_PROGRAM(
+          [[
+#include <stddef.h>
+#include <stdlib.h>
+#if HAVE_STDINT_H_WITH_UINTMAX
+#include <stdint.h>
+#endif
+#if HAVE_INTTYPES_H_WITH_UINTMAX
+#include <inttypes.h>
+#endif
+          ]],
+          [[intmax_t x = -1;
+            return !x;]])],
+       [gt_cv_c_intmax_t=yes],
+       [gt_cv_c_intmax_t=no])])
+  if test $gt_cv_c_intmax_t = yes; then
+    AC_DEFINE([HAVE_INTMAX_T], [1],
+      [Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>.])
+  fi
+])
diff --git a/m4/introspection.m4 b/m4/introspection.m4
new file mode 100644
index 0000000..d89c3d9
--- /dev/null
+++ b/m4/introspection.m4
@@ -0,0 +1,96 @@
+dnl -*- mode: autoconf -*-
+dnl Copyright 2009 Johan Dahlin
+dnl
+dnl This file is free software; the author(s) gives unlimited
+dnl permission to copy and/or distribute it, with or without
+dnl modifications, as long as this notice is preserved.
+dnl
+
+# serial 1
+
+m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL],
+[
+    AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first
+    AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first
+    AC_BEFORE([LT_INIT],[$0])dnl setup libtool first
+
+    dnl enable/disable introspection
+    m4_if([$2], [require],
+    [dnl
+        enable_introspection=yes
+    ],[dnl
+        AC_ARG_ENABLE(introspection,
+                  AS_HELP_STRING([--enable-introspection[=@<:@no/auto/yes@:>@]],
+                                 [Enable introspection for this build]),, 
+                                 [enable_introspection=auto])
+    ])dnl
+
+    AC_MSG_CHECKING([for gobject-introspection])
+
+    dnl presence/version checking
+    AS_CASE([$enable_introspection],
+    [no], [dnl
+        found_introspection="no (disabled, use --enable-introspection to enable)"
+    ],dnl
+    [yes],[dnl
+        PKG_CHECK_EXISTS([gobject-introspection-1.0],,
+                         AC_MSG_ERROR([gobject-introspection-1.0 is not installed]))
+        PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1],
+                         found_introspection=yes,
+                         AC_MSG_ERROR([You need to have gobject-introspection >= $1 installed to build 
AC_PACKAGE_NAME]))
+    ],dnl
+    [auto],[dnl
+        PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, found_introspection=no)
+       dnl Canonicalize enable_introspection
+       enable_introspection=$found_introspection
+    ],dnl
+    [dnl       
+        AC_MSG_ERROR([invalid argument passed to --enable-introspection, should be one of 
@<:@no/auto/yes@:>@])
+    ])dnl
+
+    AC_MSG_RESULT([$found_introspection])
+
+    INTROSPECTION_SCANNER=
+    INTROSPECTION_COMPILER=
+    INTROSPECTION_GENERATE=
+    INTROSPECTION_GIRDIR=
+    INTROSPECTION_TYPELIBDIR=
+    if test "x$found_introspection" = "xyes"; then
+       INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0`
+       INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0`
+       INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0`
+       INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0`
+       INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)"
+       INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0`
+       INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0`
+       INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir 
gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection
+    fi
+    AC_SUBST(INTROSPECTION_SCANNER)
+    AC_SUBST(INTROSPECTION_COMPILER)
+    AC_SUBST(INTROSPECTION_GENERATE)
+    AC_SUBST(INTROSPECTION_GIRDIR)
+    AC_SUBST(INTROSPECTION_TYPELIBDIR)
+    AC_SUBST(INTROSPECTION_CFLAGS)
+    AC_SUBST(INTROSPECTION_LIBS)
+    AC_SUBST(INTROSPECTION_MAKEFILE)
+
+    AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$found_introspection" = "xyes")
+])
+
+
+dnl Usage:
+dnl   GOBJECT_INTROSPECTION_CHECK([minimum-g-i-version])
+
+AC_DEFUN([GOBJECT_INTROSPECTION_CHECK],
+[
+  _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1])
+])
+
+dnl Usage:
+dnl   GOBJECT_INTROSPECTION_REQUIRE([minimum-g-i-version])
+
+
+AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE],
+[
+  _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require])
+])
diff --git a/m4/inttypes-pri.m4 b/m4/inttypes-pri.m4
new file mode 100644
index 0000000..0884e71
--- /dev/null
+++ b/m4/inttypes-pri.m4
@@ -0,0 +1,42 @@
+# inttypes-pri.m4 serial 7 (gettext-0.18.2)
+dnl Copyright (C) 1997-2002, 2006, 2008-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_PREREQ([2.53])
+
+# Define PRI_MACROS_BROKEN if <inttypes.h> exists and defines the PRI*
+# macros to non-string values.  This is the case on AIX 4.3.3.
+
+AC_DEFUN([gt_INTTYPES_PRI],
+[
+  AC_CHECK_HEADERS([inttypes.h])
+  if test $ac_cv_header_inttypes_h = yes; then
+    AC_CACHE_CHECK([whether the inttypes.h PRIxNN macros are broken],
+      [gt_cv_inttypes_pri_broken],
+      [
+        AC_COMPILE_IFELSE(
+          [AC_LANG_PROGRAM(
+             [[
+#include <inttypes.h>
+#ifdef PRId32
+char *p = PRId32;
+#endif
+             ]],
+             [[]])],
+          [gt_cv_inttypes_pri_broken=no],
+          [gt_cv_inttypes_pri_broken=yes])
+      ])
+  fi
+  if test "$gt_cv_inttypes_pri_broken" = yes; then
+    AC_DEFINE_UNQUOTED([PRI_MACROS_BROKEN], [1],
+      [Define if <inttypes.h> exists and defines unusable PRI* macros.])
+    PRI_MACROS_BROKEN=1
+  else
+    PRI_MACROS_BROKEN=0
+  fi
+  AC_SUBST([PRI_MACROS_BROKEN])
+])
diff --git a/m4/inttypes_h.m4 b/m4/inttypes_h.m4
new file mode 100644
index 0000000..d0b5f5d
--- /dev/null
+++ b/m4/inttypes_h.m4
@@ -0,0 +1,29 @@
+# inttypes_h.m4 serial 10
+dnl Copyright (C) 1997-2004, 2006, 2008-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Paul Eggert.
+
+# Define HAVE_INTTYPES_H_WITH_UINTMAX if <inttypes.h> exists,
+# doesn't clash with <sys/types.h>, and declares uintmax_t.
+
+AC_DEFUN([gl_AC_HEADER_INTTYPES_H],
+[
+  AC_CACHE_CHECK([for inttypes.h], [gl_cv_header_inttypes_h],
+    [AC_COMPILE_IFELSE(
+       [AC_LANG_PROGRAM(
+          [[
+#include <sys/types.h>
+#include <inttypes.h>
+          ]],
+          [[uintmax_t i = (uintmax_t) -1; return !i;]])],
+       [gl_cv_header_inttypes_h=yes],
+       [gl_cv_header_inttypes_h=no])])
+  if test $gl_cv_header_inttypes_h = yes; then
+    AC_DEFINE_UNQUOTED([HAVE_INTTYPES_H_WITH_UINTMAX], [1],
+      [Define if <inttypes.h> exists, doesn't clash with <sys/types.h>,
+       and declares uintmax_t. ])
+  fi
+])
diff --git a/m4/lcmessage.m4 b/m4/lcmessage.m4
new file mode 100644
index 0000000..7470ec5
--- /dev/null
+++ b/m4/lcmessage.m4
@@ -0,0 +1,35 @@
+# lcmessage.m4 serial 7 (gettext-0.18.2)
+dnl Copyright (C) 1995-2002, 2004-2005, 2008-2014 Free Software Foundation,
+dnl Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+dnl
+dnl This file can can be used in projects which are not available under
+dnl the GNU General Public License or the GNU Library General Public
+dnl License but which still want to provide support for the GNU gettext
+dnl functionality.
+dnl Please note that the actual code of the GNU gettext library is covered
+dnl by the GNU Library General Public License, and the rest of the GNU
+dnl gettext package package is covered by the GNU General Public License.
+dnl They are *not* in the public domain.
+
+dnl Authors:
+dnl   Ulrich Drepper <drepper cygnus com>, 1995.
+
+# Check whether LC_MESSAGES is available in <locale.h>.
+
+AC_DEFUN([gt_LC_MESSAGES],
+[
+  AC_CACHE_CHECK([for LC_MESSAGES], [gt_cv_val_LC_MESSAGES],
+    [AC_LINK_IFELSE(
+       [AC_LANG_PROGRAM(
+          [[#include <locale.h>]],
+          [[return LC_MESSAGES]])],
+       [gt_cv_val_LC_MESSAGES=yes],
+       [gt_cv_val_LC_MESSAGES=no])])
+  if test $gt_cv_val_LC_MESSAGES = yes; then
+    AC_DEFINE([HAVE_LC_MESSAGES], [1],
+      [Define if your <locale.h> file defines LC_MESSAGES.])
+  fi
+])
diff --git a/m4/lib-ld.m4 b/m4/lib-ld.m4
new file mode 100644
index 0000000..91ca911
--- /dev/null
+++ b/m4/lib-ld.m4
@@ -0,0 +1,119 @@
+# lib-ld.m4 serial 6
+dnl Copyright (C) 1996-2003, 2009-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl Subroutines of libtool.m4,
+dnl with replacements s/_*LT_PATH/AC_LIB_PROG/ and s/lt_/acl_/ to avoid
+dnl collision with libtool.m4.
+
+dnl From libtool-2.4. Sets the variable with_gnu_ld to yes or no.
+AC_DEFUN([AC_LIB_PROG_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], [acl_cv_prog_gnu_ld],
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  acl_cv_prog_gnu_ld=yes
+  ;;
+*)
+  acl_cv_prog_gnu_ld=no
+  ;;
+esac])
+with_gnu_ld=$acl_cv_prog_gnu_ld
+])
+
+dnl From libtool-2.4. Sets the variable LD.
+AC_DEFUN([AC_LIB_PROG_LD],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+
+AC_ARG_WITH([gnu-ld],
+    [AS_HELP_STRING([--with-gnu-ld],
+        [assume the C compiler uses GNU ld [default=no]])],
+    [test "$withval" = no || with_gnu_ld=yes],
+    [with_gnu_ld=no])dnl
+
+# Prepare PATH_SEPARATOR.
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which
+  # contains only /bin. Note that ksh looks also at the FPATH variable,
+  # so we have to set that as well for the test.
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \
+    && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \
+           || PATH_SEPARATOR=';'
+       }
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  AC_MSG_CHECKING([for ld used by $CC])
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [[\\/]]* | ?:[[\\/]]*)
+      re_direlt='/[[^/]][[^/]]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`echo "$ac_prog"| sed 's%\\\\%/%g'`
+      while echo "$ac_prog" | grep "$re_direlt" > /dev/null 2>&1; do
+        ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL([acl_cv_path_LD],
+[if test -z "$LD"; then
+  acl_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$acl_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      acl_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$acl_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+        test "$with_gnu_ld" != no && break
+        ;;
+      *)
+        test "$with_gnu_ld" != yes && break
+        ;;
+      esac
+    fi
+  done
+  IFS="$acl_save_ifs"
+else
+  acl_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$acl_cv_path_LD"
+if test -n "$LD"; then
+  AC_MSG_RESULT([$LD])
+else
+  AC_MSG_RESULT([no])
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_LIB_PROG_LD_GNU
+])
diff --git a/m4/lib-link.m4 b/m4/lib-link.m4
new file mode 100644
index 0000000..d8d5d1f
--- /dev/null
+++ b/m4/lib-link.m4
@@ -0,0 +1,777 @@
+# lib-link.m4 serial 26 (gettext-0.18.2)
+dnl Copyright (C) 2001-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_PREREQ([2.54])
+
+dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and
+dnl the libraries corresponding to explicit and implicit dependencies.
+dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and
+dnl augments the CPPFLAGS variable.
+dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
+dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
+AC_DEFUN([AC_LIB_LINKFLAGS],
+[
+  AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+  AC_REQUIRE([AC_LIB_RPATH])
+  pushdef([Name],[m4_translit([$1],[./+-], [____])])
+  pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-],
+                                   [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])])
+  AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [
+    AC_LIB_LINKFLAGS_BODY([$1], [$2])
+    ac_cv_lib[]Name[]_libs="$LIB[]NAME"
+    ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME"
+    ac_cv_lib[]Name[]_cppflags="$INC[]NAME"
+    ac_cv_lib[]Name[]_prefix="$LIB[]NAME[]_PREFIX"
+  ])
+  LIB[]NAME="$ac_cv_lib[]Name[]_libs"
+  LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs"
+  INC[]NAME="$ac_cv_lib[]Name[]_cppflags"
+  LIB[]NAME[]_PREFIX="$ac_cv_lib[]Name[]_prefix"
+  AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
+  AC_SUBST([LIB]NAME)
+  AC_SUBST([LTLIB]NAME)
+  AC_SUBST([LIB]NAME[_PREFIX])
+  dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the
+  dnl results of this search when this library appears as a dependency.
+  HAVE_LIB[]NAME=yes
+  popdef([NAME])
+  popdef([Name])
+])
+
+dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode, [missing-message])
+dnl searches for libname and the libraries corresponding to explicit and
+dnl implicit dependencies, together with the specified include files and
+dnl the ability to compile and link the specified testcode. The missing-message
+dnl defaults to 'no' and may contain additional hints for the user.
+dnl If found, it sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME}
+dnl and LTLIB${NAME} variables and augments the CPPFLAGS variable, and
+dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs
+dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty.
+dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
+dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
+AC_DEFUN([AC_LIB_HAVE_LINKFLAGS],
+[
+  AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+  AC_REQUIRE([AC_LIB_RPATH])
+  pushdef([Name],[m4_translit([$1],[./+-], [____])])
+  pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-],
+                                   [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])])
+
+  dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME
+  dnl accordingly.
+  AC_LIB_LINKFLAGS_BODY([$1], [$2])
+
+  dnl Add $INC[]NAME to CPPFLAGS before performing the following checks,
+  dnl because if the user has installed lib[]Name and not disabled its use
+  dnl via --without-lib[]Name-prefix, he wants to use it.
+  ac_save_CPPFLAGS="$CPPFLAGS"
+  AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
+
+  AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [
+    ac_save_LIBS="$LIBS"
+    dnl If $LIB[]NAME contains some -l options, add it to the end of LIBS,
+    dnl because these -l options might require -L options that are present in
+    dnl LIBS. -l options benefit only from the -L options listed before it.
+    dnl Otherwise, add it to the front of LIBS, because it may be a static
+    dnl library that depends on another static library that is present in LIBS.
+    dnl Static libraries benefit only from the static libraries listed after
+    dnl it.
+    case " $LIB[]NAME" in
+      *" -l"*) LIBS="$LIBS $LIB[]NAME" ;;
+      *)       LIBS="$LIB[]NAME $LIBS" ;;
+    esac
+    AC_LINK_IFELSE(
+      [AC_LANG_PROGRAM([[$3]], [[$4]])],
+      [ac_cv_lib[]Name=yes],
+      [ac_cv_lib[]Name='m4_if([$5], [], [no], [[$5]])'])
+    LIBS="$ac_save_LIBS"
+  ])
+  if test "$ac_cv_lib[]Name" = yes; then
+    HAVE_LIB[]NAME=yes
+    AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the lib][$1 library.])
+    AC_MSG_CHECKING([how to link with lib[]$1])
+    AC_MSG_RESULT([$LIB[]NAME])
+  else
+    HAVE_LIB[]NAME=no
+    dnl If $LIB[]NAME didn't lead to a usable library, we don't need
+    dnl $INC[]NAME either.
+    CPPFLAGS="$ac_save_CPPFLAGS"
+    LIB[]NAME=
+    LTLIB[]NAME=
+    LIB[]NAME[]_PREFIX=
+  fi
+  AC_SUBST([HAVE_LIB]NAME)
+  AC_SUBST([LIB]NAME)
+  AC_SUBST([LTLIB]NAME)
+  AC_SUBST([LIB]NAME[_PREFIX])
+  popdef([NAME])
+  popdef([Name])
+])
+
+dnl Determine the platform dependent parameters needed to use rpath:
+dnl   acl_libext,
+dnl   acl_shlibext,
+dnl   acl_libname_spec,
+dnl   acl_library_names_spec,
+dnl   acl_hardcode_libdir_flag_spec,
+dnl   acl_hardcode_libdir_separator,
+dnl   acl_hardcode_direct,
+dnl   acl_hardcode_minus_L.
+AC_DEFUN([AC_LIB_RPATH],
+[
+  dnl Tell automake >= 1.10 to complain if config.rpath is missing.
+  m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])])
+  AC_REQUIRE([AC_PROG_CC])                dnl we use $CC, $GCC, $LDFLAGS
+  AC_REQUIRE([AC_LIB_PROG_LD])            dnl we use $LD, $with_gnu_ld
+  AC_REQUIRE([AC_CANONICAL_HOST])         dnl we use $host
+  AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir
+  AC_CACHE_CHECK([for shared library run path origin], [acl_cv_rpath], [
+    CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
+    ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
+    . ./conftest.sh
+    rm -f ./conftest.sh
+    acl_cv_rpath=done
+  ])
+  wl="$acl_cv_wl"
+  acl_libext="$acl_cv_libext"
+  acl_shlibext="$acl_cv_shlibext"
+  acl_libname_spec="$acl_cv_libname_spec"
+  acl_library_names_spec="$acl_cv_library_names_spec"
+  acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
+  acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
+  acl_hardcode_direct="$acl_cv_hardcode_direct"
+  acl_hardcode_minus_L="$acl_cv_hardcode_minus_L"
+  dnl Determine whether the user wants rpath handling at all.
+  AC_ARG_ENABLE([rpath],
+    [  --disable-rpath         do not hardcode runtime library paths],
+    :, enable_rpath=yes)
+])
+
+dnl AC_LIB_FROMPACKAGE(name, package)
+dnl declares that libname comes from the given package. The configure file
+dnl will then not have a --with-libname-prefix option but a
+dnl --with-package-prefix option. Several libraries can come from the same
+dnl package. This declaration must occur before an AC_LIB_LINKFLAGS or similar
+dnl macro call that searches for libname.
+AC_DEFUN([AC_LIB_FROMPACKAGE],
+[
+  pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-],
+                                   [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])])
+  define([acl_frompackage_]NAME, [$2])
+  popdef([NAME])
+  pushdef([PACK],[$2])
+  pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-],
+                                     [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])])
+  define([acl_libsinpackage_]PACKUP,
+    m4_ifdef([acl_libsinpackage_]PACKUP, [m4_defn([acl_libsinpackage_]PACKUP)[, ]],)[lib$1])
+  popdef([PACKUP])
+  popdef([PACK])
+])
+
+dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and
+dnl the libraries corresponding to explicit and implicit dependencies.
+dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables.
+dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found
+dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
+AC_DEFUN([AC_LIB_LINKFLAGS_BODY],
+[
+  AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
+  pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-],
+                                   [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])])
+  pushdef([PACK],[m4_ifdef([acl_frompackage_]NAME, [acl_frompackage_]NAME, lib[$1])])
+  pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-],
+                                     [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])])
+  pushdef([PACKLIBS],[m4_ifdef([acl_frompackage_]NAME, [acl_libsinpackage_]PACKUP, lib[$1])])
+  dnl Autoconf >= 2.61 supports dots in --with options.
+  
pushdef([P_A_C_K],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[m4_translit(PACK,[.],[_])],PACK)])
+  dnl By default, look in $includedir and $libdir.
+  use_additional=yes
+  AC_LIB_WITH_FINAL_PREFIX([
+    eval additional_includedir=\"$includedir\"
+    eval additional_libdir=\"$libdir\"
+  ])
+  AC_ARG_WITH(P_A_C_K[-prefix],
+[[  --with-]]P_A_C_K[[-prefix[=DIR]  search for ]PACKLIBS[ in DIR/include and DIR/lib
+  --without-]]P_A_C_K[[-prefix     don't search for ]PACKLIBS[ in includedir and libdir]],
+[
+    if test "X$withval" = "Xno"; then
+      use_additional=no
+    else
+      if test "X$withval" = "X"; then
+        AC_LIB_WITH_FINAL_PREFIX([
+          eval additional_includedir=\"$includedir\"
+          eval additional_libdir=\"$libdir\"
+        ])
+      else
+        additional_includedir="$withval/include"
+        additional_libdir="$withval/$acl_libdirstem"
+        if test "$acl_libdirstem2" != "$acl_libdirstem" \
+           && ! test -d "$withval/$acl_libdirstem"; then
+          additional_libdir="$withval/$acl_libdirstem2"
+        fi
+      fi
+    fi
+])
+  dnl Search the library and its dependencies in $additional_libdir and
+  dnl $LDFLAGS. Using breadth-first-seach.
+  LIB[]NAME=
+  LTLIB[]NAME=
+  INC[]NAME=
+  LIB[]NAME[]_PREFIX=
+  dnl HAVE_LIB${NAME} is an indicator that LIB${NAME}, LTLIB${NAME} have been
+  dnl computed. So it has to be reset here.
+  HAVE_LIB[]NAME=
+  rpathdirs=
+  ltrpathdirs=
+  names_already_handled=
+  names_next_round='$1 $2'
+  while test -n "$names_next_round"; do
+    names_this_round="$names_next_round"
+    names_next_round=
+    for name in $names_this_round; do
+      already_handled=
+      for n in $names_already_handled; do
+        if test "$n" = "$name"; then
+          already_handled=yes
+          break
+        fi
+      done
+      if test -z "$already_handled"; then
+        names_already_handled="$names_already_handled $name"
+        dnl See if it was already located by an earlier AC_LIB_LINKFLAGS
+        dnl or AC_LIB_HAVE_LINKFLAGS call.
+        uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'`
+        eval value=\"\$HAVE_LIB$uppername\"
+        if test -n "$value"; then
+          if test "$value" = yes; then
+            eval value=\"\$LIB$uppername\"
+            test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value"
+            eval value=\"\$LTLIB$uppername\"
+            test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value"
+          else
+            dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined
+            dnl that this library doesn't exist. So just drop it.
+            :
+          fi
+        else
+          dnl Search the library lib$name in $additional_libdir and $LDFLAGS
+          dnl and the already constructed $LIBNAME/$LTLIBNAME.
+          found_dir=
+          found_la=
+          found_so=
+          found_a=
+          eval libname=\"$acl_libname_spec\"    # typically: libname=lib$name
+          if test -n "$acl_shlibext"; then
+            shrext=".$acl_shlibext"             # typically: shrext=.so
+          else
+            shrext=
+          fi
+          if test $use_additional = yes; then
+            dir="$additional_libdir"
+            dnl The same code as in the loop below:
+            dnl First look for a shared library.
+            if test -n "$acl_shlibext"; then
+              if test -f "$dir/$libname$shrext"; then
+                found_dir="$dir"
+                found_so="$dir/$libname$shrext"
+              else
+                if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
+                  ver=`(cd "$dir" && \
+                        for f in "$libname$shrext".*; do echo "$f"; done \
+                        | sed -e "s,^$libname$shrext\\\\.,," \
+                        | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
+                        | sed 1q ) 2>/dev/null`
+                  if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
+                    found_dir="$dir"
+                    found_so="$dir/$libname$shrext.$ver"
+                  fi
+                else
+                  eval library_names=\"$acl_library_names_spec\"
+                  for f in $library_names; do
+                    if test -f "$dir/$f"; then
+                      found_dir="$dir"
+                      found_so="$dir/$f"
+                      break
+                    fi
+                  done
+                fi
+              fi
+            fi
+            dnl Then look for a static library.
+            if test "X$found_dir" = "X"; then
+              if test -f "$dir/$libname.$acl_libext"; then
+                found_dir="$dir"
+                found_a="$dir/$libname.$acl_libext"
+              fi
+            fi
+            if test "X$found_dir" != "X"; then
+              if test -f "$dir/$libname.la"; then
+                found_la="$dir/$libname.la"
+              fi
+            fi
+          fi
+          if test "X$found_dir" = "X"; then
+            for x in $LDFLAGS $LTLIB[]NAME; do
+              AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+              case "$x" in
+                -L*)
+                  dir=`echo "X$x" | sed -e 's/^X-L//'`
+                  dnl First look for a shared library.
+                  if test -n "$acl_shlibext"; then
+                    if test -f "$dir/$libname$shrext"; then
+                      found_dir="$dir"
+                      found_so="$dir/$libname$shrext"
+                    else
+                      if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
+                        ver=`(cd "$dir" && \
+                              for f in "$libname$shrext".*; do echo "$f"; done \
+                              | sed -e "s,^$libname$shrext\\\\.,," \
+                              | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
+                              | sed 1q ) 2>/dev/null`
+                        if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
+                          found_dir="$dir"
+                          found_so="$dir/$libname$shrext.$ver"
+                        fi
+                      else
+                        eval library_names=\"$acl_library_names_spec\"
+                        for f in $library_names; do
+                          if test -f "$dir/$f"; then
+                            found_dir="$dir"
+                            found_so="$dir/$f"
+                            break
+                          fi
+                        done
+                      fi
+                    fi
+                  fi
+                  dnl Then look for a static library.
+                  if test "X$found_dir" = "X"; then
+                    if test -f "$dir/$libname.$acl_libext"; then
+                      found_dir="$dir"
+                      found_a="$dir/$libname.$acl_libext"
+                    fi
+                  fi
+                  if test "X$found_dir" != "X"; then
+                    if test -f "$dir/$libname.la"; then
+                      found_la="$dir/$libname.la"
+                    fi
+                  fi
+                  ;;
+              esac
+              if test "X$found_dir" != "X"; then
+                break
+              fi
+            done
+          fi
+          if test "X$found_dir" != "X"; then
+            dnl Found the library.
+            LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name"
+            if test "X$found_so" != "X"; then
+              dnl Linking with a shared library. We attempt to hardcode its
+              dnl directory into the executable's runpath, unless it's the
+              dnl standard /usr/lib.
+              if test "$enable_rpath" = no \
+                 || test "X$found_dir" = "X/usr/$acl_libdirstem" \
+                 || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then
+                dnl No hardcoding is needed.
+                LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+              else
+                dnl Use an explicit option to hardcode DIR into the resulting
+                dnl binary.
+                dnl Potentially add DIR to ltrpathdirs.
+                dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
+                haveit=
+                for x in $ltrpathdirs; do
+                  if test "X$x" = "X$found_dir"; then
+                    haveit=yes
+                    break
+                  fi
+                done
+                if test -z "$haveit"; then
+                  ltrpathdirs="$ltrpathdirs $found_dir"
+                fi
+                dnl The hardcoding into $LIBNAME is system dependent.
+                if test "$acl_hardcode_direct" = yes; then
+                  dnl Using DIR/libNAME.so during linking hardcodes DIR into the
+                  dnl resulting binary.
+                  LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+                else
+                  if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
+                    dnl Use an explicit option to hardcode DIR into the resulting
+                    dnl binary.
+                    LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+                    dnl Potentially add DIR to rpathdirs.
+                    dnl The rpathdirs will be appended to $LIBNAME at the end.
+                    haveit=
+                    for x in $rpathdirs; do
+                      if test "X$x" = "X$found_dir"; then
+                        haveit=yes
+                        break
+                      fi
+                    done
+                    if test -z "$haveit"; then
+                      rpathdirs="$rpathdirs $found_dir"
+                    fi
+                  else
+                    dnl Rely on "-L$found_dir".
+                    dnl But don't add it if it's already contained in the LDFLAGS
+                    dnl or the already constructed $LIBNAME
+                    haveit=
+                    for x in $LDFLAGS $LIB[]NAME; do
+                      AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+                      if test "X$x" = "X-L$found_dir"; then
+                        haveit=yes
+                        break
+                      fi
+                    done
+                    if test -z "$haveit"; then
+                      LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir"
+                    fi
+                    if test "$acl_hardcode_minus_L" != no; then
+                      dnl FIXME: Not sure whether we should use
+                      dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
+                      dnl here.
+                      LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+                    else
+                      dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH
+                      dnl here, because this doesn't fit in flags passed to the
+                      dnl compiler. So give up. No hardcoding. This affects only
+                      dnl very old systems.
+                      dnl FIXME: Not sure whether we should use
+                      dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
+                      dnl here.
+                      LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
+                    fi
+                  fi
+                fi
+              fi
+            else
+              if test "X$found_a" != "X"; then
+                dnl Linking with a static library.
+                LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a"
+              else
+                dnl We shouldn't come here, but anyway it's good to have a
+                dnl fallback.
+                LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name"
+              fi
+            fi
+            dnl Assume the include files are nearby.
+            additional_includedir=
+            case "$found_dir" in
+              */$acl_libdirstem | */$acl_libdirstem/)
+                basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'`
+                if test "$name" = '$1'; then
+                  LIB[]NAME[]_PREFIX="$basedir"
+                fi
+                additional_includedir="$basedir/include"
+                ;;
+              */$acl_libdirstem2 | */$acl_libdirstem2/)
+                basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'`
+                if test "$name" = '$1'; then
+                  LIB[]NAME[]_PREFIX="$basedir"
+                fi
+                additional_includedir="$basedir/include"
+                ;;
+            esac
+            if test "X$additional_includedir" != "X"; then
+              dnl Potentially add $additional_includedir to $INCNAME.
+              dnl But don't add it
+              dnl   1. if it's the standard /usr/include,
+              dnl   2. if it's /usr/local/include and we are using GCC on Linux,
+              dnl   3. if it's already present in $CPPFLAGS or the already
+              dnl      constructed $INCNAME,
+              dnl   4. if it doesn't exist as a directory.
+              if test "X$additional_includedir" != "X/usr/include"; then
+                haveit=
+                if test "X$additional_includedir" = "X/usr/local/include"; then
+                  if test -n "$GCC"; then
+                    case $host_os in
+                      linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+                    esac
+                  fi
+                fi
+                if test -z "$haveit"; then
+                  for x in $CPPFLAGS $INC[]NAME; do
+                    AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+                    if test "X$x" = "X-I$additional_includedir"; then
+                      haveit=yes
+                      break
+                    fi
+                  done
+                  if test -z "$haveit"; then
+                    if test -d "$additional_includedir"; then
+                      dnl Really add $additional_includedir to $INCNAME.
+                      INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir"
+                    fi
+                  fi
+                fi
+              fi
+            fi
+            dnl Look for dependencies.
+            if test -n "$found_la"; then
+              dnl Read the .la file. It defines the variables
+              dnl dlname, library_names, old_library, dependency_libs, current,
+              dnl age, revision, installed, dlopen, dlpreopen, libdir.
+              save_libdir="$libdir"
+              case "$found_la" in
+                */* | *\\*) . "$found_la" ;;
+                *) . "./$found_la" ;;
+              esac
+              libdir="$save_libdir"
+              dnl We use only dependency_libs.
+              for dep in $dependency_libs; do
+                case "$dep" in
+                  -L*)
+                    additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
+                    dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME.
+                    dnl But don't add it
+                    dnl   1. if it's the standard /usr/lib,
+                    dnl   2. if it's /usr/local/lib and we are using GCC on Linux,
+                    dnl   3. if it's already present in $LDFLAGS or the already
+                    dnl      constructed $LIBNAME,
+                    dnl   4. if it doesn't exist as a directory.
+                    if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \
+                       && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then
+                      haveit=
+                      if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \
+                         || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then
+                        if test -n "$GCC"; then
+                          case $host_os in
+                            linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+                          esac
+                        fi
+                      fi
+                      if test -z "$haveit"; then
+                        haveit=
+                        for x in $LDFLAGS $LIB[]NAME; do
+                          AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+                          if test "X$x" = "X-L$additional_libdir"; then
+                            haveit=yes
+                            break
+                          fi
+                        done
+                        if test -z "$haveit"; then
+                          if test -d "$additional_libdir"; then
+                            dnl Really add $additional_libdir to $LIBNAME.
+                            LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir"
+                          fi
+                        fi
+                        haveit=
+                        for x in $LDFLAGS $LTLIB[]NAME; do
+                          AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+                          if test "X$x" = "X-L$additional_libdir"; then
+                            haveit=yes
+                            break
+                          fi
+                        done
+                        if test -z "$haveit"; then
+                          if test -d "$additional_libdir"; then
+                            dnl Really add $additional_libdir to $LTLIBNAME.
+                            LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir"
+                          fi
+                        fi
+                      fi
+                    fi
+                    ;;
+                  -R*)
+                    dir=`echo "X$dep" | sed -e 's/^X-R//'`
+                    if test "$enable_rpath" != no; then
+                      dnl Potentially add DIR to rpathdirs.
+                      dnl The rpathdirs will be appended to $LIBNAME at the end.
+                      haveit=
+                      for x in $rpathdirs; do
+                        if test "X$x" = "X$dir"; then
+                          haveit=yes
+                          break
+                        fi
+                      done
+                      if test -z "$haveit"; then
+                        rpathdirs="$rpathdirs $dir"
+                      fi
+                      dnl Potentially add DIR to ltrpathdirs.
+                      dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
+                      haveit=
+                      for x in $ltrpathdirs; do
+                        if test "X$x" = "X$dir"; then
+                          haveit=yes
+                          break
+                        fi
+                      done
+                      if test -z "$haveit"; then
+                        ltrpathdirs="$ltrpathdirs $dir"
+                      fi
+                    fi
+                    ;;
+                  -l*)
+                    dnl Handle this in the next round.
+                    names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
+                    ;;
+                  *.la)
+                    dnl Handle this in the next round. Throw away the .la's
+                    dnl directory; it is already contained in a preceding -L
+                    dnl option.
+                    names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 
's,\.la$,,'`
+                    ;;
+                  *)
+                    dnl Most likely an immediate library name.
+                    LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep"
+                    LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep"
+                    ;;
+                esac
+              done
+            fi
+          else
+            dnl Didn't find the library; assume it is in the system directories
+            dnl known to the linker and runtime loader. (All the system
+            dnl directories known to the linker should also be known to the
+            dnl runtime loader, otherwise the system is severely misconfigured.)
+            LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
+            LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name"
+          fi
+        fi
+      fi
+    done
+  done
+  if test "X$rpathdirs" != "X"; then
+    if test -n "$acl_hardcode_libdir_separator"; then
+      dnl Weird platform: only the last -rpath option counts, the user must
+      dnl pass all path elements in one option. We can arrange that for a
+      dnl single library, but not when more than one $LIBNAMEs are used.
+      alldirs=
+      for found_dir in $rpathdirs; do
+        alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir"
+      done
+      dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl.
+      acl_save_libdir="$libdir"
+      libdir="$alldirs"
+      eval flag=\"$acl_hardcode_libdir_flag_spec\"
+      libdir="$acl_save_libdir"
+      LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
+    else
+      dnl The -rpath options are cumulative.
+      for found_dir in $rpathdirs; do
+        acl_save_libdir="$libdir"
+        libdir="$found_dir"
+        eval flag=\"$acl_hardcode_libdir_flag_spec\"
+        libdir="$acl_save_libdir"
+        LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
+      done
+    fi
+  fi
+  if test "X$ltrpathdirs" != "X"; then
+    dnl When using libtool, the option that works for both libraries and
+    dnl executables is -R. The -R options are cumulative.
+    for found_dir in $ltrpathdirs; do
+      LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir"
+    done
+  fi
+  popdef([P_A_C_K])
+  popdef([PACKLIBS])
+  popdef([PACKUP])
+  popdef([PACK])
+  popdef([NAME])
+])
+
+dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR,
+dnl unless already present in VAR.
+dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes
+dnl contains two or three consecutive elements that belong together.
+AC_DEFUN([AC_LIB_APPENDTOVAR],
+[
+  for element in [$2]; do
+    haveit=
+    for x in $[$1]; do
+      AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+      if test "X$x" = "X$element"; then
+        haveit=yes
+        break
+      fi
+    done
+    if test -z "$haveit"; then
+      [$1]="${[$1]}${[$1]:+ }$element"
+    fi
+  done
+])
+
+dnl For those cases where a variable contains several -L and -l options
+dnl referring to unknown libraries and directories, this macro determines the
+dnl necessary additional linker options for the runtime path.
+dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL])
+dnl sets LDADDVAR to linker options needed together with LIBSVALUE.
+dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed,
+dnl otherwise linking without libtool is assumed.
+AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS],
+[
+  AC_REQUIRE([AC_LIB_RPATH])
+  AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
+  $1=
+  if test "$enable_rpath" != no; then
+    if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
+      dnl Use an explicit option to hardcode directories into the resulting
+      dnl binary.
+      rpathdirs=
+      next=
+      for opt in $2; do
+        if test -n "$next"; then
+          dir="$next"
+          dnl No need to hardcode the standard /usr/lib.
+          if test "X$dir" != "X/usr/$acl_libdirstem" \
+             && test "X$dir" != "X/usr/$acl_libdirstem2"; then
+            rpathdirs="$rpathdirs $dir"
+          fi
+          next=
+        else
+          case $opt in
+            -L) next=yes ;;
+            -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'`
+                 dnl No need to hardcode the standard /usr/lib.
+                 if test "X$dir" != "X/usr/$acl_libdirstem" \
+                    && test "X$dir" != "X/usr/$acl_libdirstem2"; then
+                   rpathdirs="$rpathdirs $dir"
+                 fi
+                 next= ;;
+            *) next= ;;
+          esac
+        fi
+      done
+      if test "X$rpathdirs" != "X"; then
+        if test -n ""$3""; then
+          dnl libtool is used for linking. Use -R options.
+          for dir in $rpathdirs; do
+            $1="${$1}${$1:+ }-R$dir"
+          done
+        else
+          dnl The linker is used for linking directly.
+          if test -n "$acl_hardcode_libdir_separator"; then
+            dnl Weird platform: only the last -rpath option counts, the user
+            dnl must pass all path elements in one option.
+            alldirs=
+            for dir in $rpathdirs; do
+              alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir"
+            done
+            acl_save_libdir="$libdir"
+            libdir="$alldirs"
+            eval flag=\"$acl_hardcode_libdir_flag_spec\"
+            libdir="$acl_save_libdir"
+            $1="$flag"
+          else
+            dnl The -rpath options are cumulative.
+            for dir in $rpathdirs; do
+              acl_save_libdir="$libdir"
+              libdir="$dir"
+              eval flag=\"$acl_hardcode_libdir_flag_spec\"
+              libdir="$acl_save_libdir"
+              $1="${$1}${$1:+ }$flag"
+            done
+          fi
+        fi
+      fi
+    fi
+  fi
+  AC_SUBST([$1])
+])
diff --git a/m4/lib-prefix.m4 b/m4/lib-prefix.m4
new file mode 100644
index 0000000..0465f47
--- /dev/null
+++ b/m4/lib-prefix.m4
@@ -0,0 +1,224 @@
+# lib-prefix.m4 serial 7 (gettext-0.18)
+dnl Copyright (C) 2001-2005, 2008-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and
+dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't
+dnl require excessive bracketing.
+ifdef([AC_HELP_STRING],
+[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])],
+[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])])
+
+dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed
+dnl to access previously installed libraries. The basic assumption is that
+dnl a user will want packages to use other packages he previously installed
+dnl with the same --prefix option.
+dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate
+dnl libraries, but is otherwise very convenient.
+AC_DEFUN([AC_LIB_PREFIX],
+[
+  AC_BEFORE([$0], [AC_LIB_LINKFLAGS])
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST])
+  AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
+  AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+  dnl By default, look in $includedir and $libdir.
+  use_additional=yes
+  AC_LIB_WITH_FINAL_PREFIX([
+    eval additional_includedir=\"$includedir\"
+    eval additional_libdir=\"$libdir\"
+  ])
+  AC_LIB_ARG_WITH([lib-prefix],
+[  --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib
+  --without-lib-prefix    don't search for libraries in includedir and libdir],
+[
+    if test "X$withval" = "Xno"; then
+      use_additional=no
+    else
+      if test "X$withval" = "X"; then
+        AC_LIB_WITH_FINAL_PREFIX([
+          eval additional_includedir=\"$includedir\"
+          eval additional_libdir=\"$libdir\"
+        ])
+      else
+        additional_includedir="$withval/include"
+        additional_libdir="$withval/$acl_libdirstem"
+      fi
+    fi
+])
+  if test $use_additional = yes; then
+    dnl Potentially add $additional_includedir to $CPPFLAGS.
+    dnl But don't add it
+    dnl   1. if it's the standard /usr/include,
+    dnl   2. if it's already present in $CPPFLAGS,
+    dnl   3. if it's /usr/local/include and we are using GCC on Linux,
+    dnl   4. if it doesn't exist as a directory.
+    if test "X$additional_includedir" != "X/usr/include"; then
+      haveit=
+      for x in $CPPFLAGS; do
+        AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+        if test "X$x" = "X-I$additional_includedir"; then
+          haveit=yes
+          break
+        fi
+      done
+      if test -z "$haveit"; then
+        if test "X$additional_includedir" = "X/usr/local/include"; then
+          if test -n "$GCC"; then
+            case $host_os in
+              linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+            esac
+          fi
+        fi
+        if test -z "$haveit"; then
+          if test -d "$additional_includedir"; then
+            dnl Really add $additional_includedir to $CPPFLAGS.
+            CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir"
+          fi
+        fi
+      fi
+    fi
+    dnl Potentially add $additional_libdir to $LDFLAGS.
+    dnl But don't add it
+    dnl   1. if it's the standard /usr/lib,
+    dnl   2. if it's already present in $LDFLAGS,
+    dnl   3. if it's /usr/local/lib and we are using GCC on Linux,
+    dnl   4. if it doesn't exist as a directory.
+    if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then
+      haveit=
+      for x in $LDFLAGS; do
+        AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+        if test "X$x" = "X-L$additional_libdir"; then
+          haveit=yes
+          break
+        fi
+      done
+      if test -z "$haveit"; then
+        if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then
+          if test -n "$GCC"; then
+            case $host_os in
+              linux*) haveit=yes;;
+            esac
+          fi
+        fi
+        if test -z "$haveit"; then
+          if test -d "$additional_libdir"; then
+            dnl Really add $additional_libdir to $LDFLAGS.
+            LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir"
+          fi
+        fi
+      fi
+    fi
+  fi
+])
+
+dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix,
+dnl acl_final_exec_prefix, containing the values to which $prefix and
+dnl $exec_prefix will expand at the end of the configure script.
+AC_DEFUN([AC_LIB_PREPARE_PREFIX],
+[
+  dnl Unfortunately, prefix and exec_prefix get only finally determined
+  dnl at the end of configure.
+  if test "X$prefix" = "XNONE"; then
+    acl_final_prefix="$ac_default_prefix"
+  else
+    acl_final_prefix="$prefix"
+  fi
+  if test "X$exec_prefix" = "XNONE"; then
+    acl_final_exec_prefix='${prefix}'
+  else
+    acl_final_exec_prefix="$exec_prefix"
+  fi
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
+  prefix="$acl_save_prefix"
+])
+
+dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the
+dnl variables prefix and exec_prefix bound to the values they will have
+dnl at the end of the configure script.
+AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX],
+[
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  $1
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+])
+
+dnl AC_LIB_PREPARE_MULTILIB creates
+dnl - a variable acl_libdirstem, containing the basename of the libdir, either
+dnl   "lib" or "lib64" or "lib/64",
+dnl - a variable acl_libdirstem2, as a secondary possible value for
+dnl   acl_libdirstem, either the same as acl_libdirstem or "lib/sparcv9" or
+dnl   "lib/amd64".
+AC_DEFUN([AC_LIB_PREPARE_MULTILIB],
+[
+  dnl There is no formal standard regarding lib and lib64.
+  dnl On glibc systems, the current practice is that on a system supporting
+  dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under
+  dnl $prefix/lib64 and 32-bit libraries go under $prefix/lib. We determine
+  dnl the compiler's default mode by looking at the compiler's library search
+  dnl path. If at least one of its elements ends in /lib64 or points to a
+  dnl directory whose absolute pathname ends in /lib64, we assume a 64-bit ABI.
+  dnl Otherwise we use the default, namely "lib".
+  dnl On Solaris systems, the current practice is that on a system supporting
+  dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under
+  dnl $prefix/lib/64 (which is a symlink to either $prefix/lib/sparcv9 or
+  dnl $prefix/lib/amd64) and 32-bit libraries go under $prefix/lib.
+  AC_REQUIRE([AC_CANONICAL_HOST])
+  acl_libdirstem=lib
+  acl_libdirstem2=
+  case "$host_os" in
+    solaris*)
+      dnl See Solaris 10 Software Developer Collection > Solaris 64-bit Developer's Guide > The Development 
Environment
+      dnl <http://docs.sun.com/app/docs/doc/816-5138/dev-env?l=en&a=view>.
+      dnl "Portable Makefiles should refer to any library directories using the 64 symbolic link."
+      dnl But we want to recognize the sparcv9 or amd64 subdirectory also if the
+      dnl symlink is missing, so we set acl_libdirstem2 too.
+      AC_CACHE_CHECK([for 64-bit host], [gl_cv_solaris_64bit],
+        [AC_EGREP_CPP([sixtyfour bits], [
+#ifdef _LP64
+sixtyfour bits
+#endif
+           ], [gl_cv_solaris_64bit=yes], [gl_cv_solaris_64bit=no])
+        ])
+      if test $gl_cv_solaris_64bit = yes; then
+        acl_libdirstem=lib/64
+        case "$host_cpu" in
+          sparc*)        acl_libdirstem2=lib/sparcv9 ;;
+          i*86 | x86_64) acl_libdirstem2=lib/amd64 ;;
+        esac
+      fi
+      ;;
+    *)
+      searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 
's,^=,,'`
+      if test -n "$searchpath"; then
+        acl_save_IFS="${IFS=   }"; IFS=":"
+        for searchdir in $searchpath; do
+          if test -d "$searchdir"; then
+            case "$searchdir" in
+              */lib64/ | */lib64 ) acl_libdirstem=lib64 ;;
+              */../ | */.. )
+                # Better ignore directories of this form. They are misleading.
+                ;;
+              *) searchdir=`cd "$searchdir" && pwd`
+                 case "$searchdir" in
+                   */lib64 ) acl_libdirstem=lib64 ;;
+                 esac ;;
+            esac
+          fi
+        done
+        IFS="$acl_save_IFS"
+      fi
+      ;;
+  esac
+  test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem"
+])
diff --git a/m4/libtool.m4 b/m4/libtool.m4
new file mode 100644
index 0000000..a644432
--- /dev/null
+++ b/m4/libtool.m4
@@ -0,0 +1,8372 @@
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+#
+#   Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+m4_define([_LT_COPYING], [dnl
+# Copyright (C) 2014 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions.  There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of of the License, or
+# (at your option) any later version.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program or library that is built
+# using GNU Libtool, you may include this file under the  same
+# distribution terms that you use for the rest of that program.
+#
+# GNU Libtool 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/>.
+])
+
+# serial 58 LT_INIT
+
+
+# LT_PREREQ(VERSION)
+# ------------------
+# Complain and exit if this libtool version is less that VERSION.
+m4_defun([LT_PREREQ],
+[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
+       [m4_default([$3],
+                  [m4_fatal([Libtool version $1 or higher is required],
+                            63)])],
+       [$2])])
+
+
+# _LT_CHECK_BUILDDIR
+# ------------------
+# Complain if the absolute build directory name contains unusual characters
+m4_defun([_LT_CHECK_BUILDDIR],
+[case `pwd` in
+  *\ * | *\    *)
+    AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
+esac
+])
+
+
+# LT_INIT([OPTIONS])
+# ------------------
+AC_DEFUN([LT_INIT],
+[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK
+AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+AC_BEFORE([$0], [LT_LANG])dnl
+AC_BEFORE([$0], [LT_OUTPUT])dnl
+AC_BEFORE([$0], [LTDL_INIT])dnl
+m4_require([_LT_CHECK_BUILDDIR])dnl
+
+dnl Autoconf doesn't catch unexpanded LT_ macros by default:
+m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
+m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
+dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
+dnl unless we require an AC_DEFUNed macro:
+AC_REQUIRE([LTOPTIONS_VERSION])dnl
+AC_REQUIRE([LTSUGAR_VERSION])dnl
+AC_REQUIRE([LTVERSION_VERSION])dnl
+AC_REQUIRE([LTOBSOLETE_VERSION])dnl
+m4_require([_LT_PROG_LTMAIN])dnl
+
+_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}])
+
+dnl Parse OPTIONS
+_LT_SET_OPTIONS([$0], [$1])
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS=$ltmain
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+_LT_SETUP
+
+# Only expand once:
+m4_define([LT_INIT])
+])# LT_INIT
+
+# Old names:
+AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
+AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
+dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
+
+
+# _LT_PREPARE_CC_BASENAME
+# -----------------------
+m4_defun([_LT_PREPARE_CC_BASENAME], [
+# Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
+func_cc_basename ()
+{
+    for cc_temp in @S|@*""; do
+      case $cc_temp in
+        compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+        distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+        \-*) ;;
+        *) break;;
+      esac
+    done
+    func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+}
+])# _LT_PREPARE_CC_BASENAME
+
+
+# _LT_CC_BASENAME(CC)
+# -------------------
+# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME,
+# but that macro is also expanded into generated libtool script, which
+# arranges for $SED and $ECHO to be set by different means.
+m4_defun([_LT_CC_BASENAME],
+[m4_require([_LT_PREPARE_CC_BASENAME])dnl
+AC_REQUIRE([_LT_DECL_SED])dnl
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
+func_cc_basename $1
+cc_basename=$func_cc_basename_result
+])
+
+
+# _LT_FILEUTILS_DEFAULTS
+# ----------------------
+# It is okay to use these file commands and assume they have been set
+# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'.
+m4_defun([_LT_FILEUTILS_DEFAULTS],
+[: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+])# _LT_FILEUTILS_DEFAULTS
+
+
+# _LT_SETUP
+# ---------
+m4_defun([_LT_SETUP],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
+
+_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl
+dnl
+_LT_DECL([], [host_alias], [0], [The host system])dnl
+_LT_DECL([], [host], [0])dnl
+_LT_DECL([], [host_os], [0])dnl
+dnl
+_LT_DECL([], [build_alias], [0], [The build system])dnl
+_LT_DECL([], [build], [0])dnl
+_LT_DECL([], [build_os], [0])dnl
+dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+test -z "$LN_S" && LN_S="ln -s"
+_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
+dnl
+AC_REQUIRE([LT_CMD_MAX_LEN])dnl
+_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
+_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
+dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl
+m4_require([_LT_CMD_RELOAD])dnl
+m4_require([_LT_CHECK_MAGIC_METHOD])dnl
+m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
+m4_require([_LT_CMD_OLD_ARCHIVE])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_WITH_SYSROOT])dnl
+m4_require([_LT_CMD_TRUNCATE])dnl
+
+_LT_CONFIG_LIBTOOL_INIT([
+# See if we are running on zsh, and set the options that allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}"; then
+   setopt NO_GLOB_SUBST
+fi
+])
+if test -n "${ZSH_VERSION+set}"; then
+   setopt NO_GLOB_SUBST
+fi
+
+_LT_CHECK_OBJDIR
+
+m4_require([_LT_TAG_COMPILER])dnl
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test set != "${COLLECT_NAMES+set}"; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a '.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+old_CC=$CC
+old_CFLAGS=$CFLAGS
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+_LT_CC_BASENAME([$compiler])
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    _LT_PATH_MAGIC
+  fi
+  ;;
+esac
+
+# Use C for the default configuration in the libtool script
+LT_SUPPORTED_TAG([CC])
+_LT_LANG_C_CONFIG
+_LT_LANG_DEFAULT_CONFIG
+_LT_CONFIG_COMMANDS
+])# _LT_SETUP
+
+
+# _LT_PREPARE_SED_QUOTE_VARS
+# --------------------------
+# Define a few sed substitution that help us do robust quoting.
+m4_defun([_LT_PREPARE_SED_QUOTE_VARS],
+[# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([["`\\]]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+])
+
+# _LT_PROG_LTMAIN
+# ---------------
+# Note that this code is called both from 'configure', and 'config.status'
+# now that we use AC_CONFIG_COMMANDS to generate libtool.  Notably,
+# 'config.status' has no value for ac_aux_dir unless we are using Automake,
+# so we pass a copy along to make sure it has a sensible value anyway.
+m4_defun([_LT_PROG_LTMAIN],
+[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
+_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
+ltmain=$ac_aux_dir/ltmain.sh
+])# _LT_PROG_LTMAIN
+
+
+## ------------------------------------- ##
+## Accumulate code for creating libtool. ##
+## ------------------------------------- ##
+
+# So that we can recreate a full libtool script including additional
+# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
+# in macros and then make a single call at the end using the 'libtool'
+# label.
+
+
+# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
+# ----------------------------------------
+# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL_INIT],
+[m4_ifval([$1],
+          [m4_append([_LT_OUTPUT_LIBTOOL_INIT],
+                     [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_INIT])
+
+
+# _LT_CONFIG_LIBTOOL([COMMANDS])
+# ------------------------------
+# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL],
+[m4_ifval([$1],
+          [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
+                     [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
+
+
+# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
+# -----------------------------------------------------
+m4_defun([_LT_CONFIG_SAVE_COMMANDS],
+[_LT_CONFIG_LIBTOOL([$1])
+_LT_CONFIG_LIBTOOL_INIT([$2])
+])
+
+
+# _LT_FORMAT_COMMENT([COMMENT])
+# -----------------------------
+# Add leading comment marks to the start of each line, and a trailing
+# full-stop to the whole comment if one is not present already.
+m4_define([_LT_FORMAT_COMMENT],
+[m4_ifval([$1], [
+m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
+              [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
+)])
+
+
+
+## ------------------------ ##
+## FIXME: Eliminate VARNAME ##
+## ------------------------ ##
+
+
+# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
+# -------------------------------------------------------------------
+# CONFIGNAME is the name given to the value in the libtool script.
+# VARNAME is the (base) name used in the configure script.
+# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
+# VARNAME.  Any other value will be used directly.
+m4_define([_LT_DECL],
+[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
+    [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
+       [m4_ifval([$1], [$1], [$2])])
+    lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
+    m4_ifval([$4],
+       [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
+    lt_dict_add_subkey([lt_decl_dict], [$2],
+       [tagged?], [m4_ifval([$5], [yes], [no])])])
+])
+
+
+# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
+# --------------------------------------------------------
+m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
+
+
+# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_tag_varnames],
+[_lt_decl_filter([tagged?], [yes], $@)])
+
+
+# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
+# ---------------------------------------------------------
+m4_define([_lt_decl_filter],
+[m4_case([$#],
+  [0], [m4_fatal([$0: too few arguments: $#])],
+  [1], [m4_fatal([$0: too few arguments: $#: $1])],
+  [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
+  [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
+  [lt_dict_filter([lt_decl_dict], $@)])[]dnl
+])
+
+
+# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
+# --------------------------------------------------
+m4_define([lt_decl_quote_varnames],
+[_lt_decl_filter([value], [1], $@)])
+
+
+# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_dquote_varnames],
+[_lt_decl_filter([value], [2], $@)])
+
+
+# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_varnames_tagged],
+[m4_assert([$# <= 2])dnl
+_$0(m4_quote(m4_default([$1], [[, ]])),
+    m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
+    m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
+m4_define([_lt_decl_varnames_tagged],
+[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])
+
+
+# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_all_varnames],
+[_$0(m4_quote(m4_default([$1], [[, ]])),
+     m4_if([$2], [],
+          m4_quote(lt_decl_varnames),
+       m4_quote(m4_shift($@))))[]dnl
+])
+m4_define([_lt_decl_all_varnames],
+[lt_join($@, lt_decl_varnames_tagged([$1],
+                       lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
+])
+
+
+# _LT_CONFIG_STATUS_DECLARE([VARNAME])
+# ------------------------------------
+# Quote a variable value, and forward it to 'config.status' so that its
+# declaration there will have the same value as in 'configure'.  VARNAME
+# must have a single quote delimited value for this to work.
+m4_define([_LT_CONFIG_STATUS_DECLARE],
+[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`'])
+
+
+# _LT_CONFIG_STATUS_DECLARATIONS
+# ------------------------------
+# We delimit libtool config variables with single quotes, so when
+# we write them to config.status, we have to be sure to quote all
+# embedded single quotes properly.  In configure, this macro expands
+# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
+#
+#    <var>='`$ECHO "$<var>" | $SED "$delay_single_quote_subst"`'
+m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
+    [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAGS
+# ----------------
+# Output comment and list of tags supported by the script
+m4_defun([_LT_LIBTOOL_TAGS],
+[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
+available_tags='_LT_TAGS'dnl
+])
+
+
+# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
+# -----------------------------------
+# Extract the dictionary values for VARNAME (optionally with TAG) and
+# expand to a commented shell variable setting:
+#
+#    # Some comment about what VAR is for.
+#    visible_name=$lt_internal_name
+m4_define([_LT_LIBTOOL_DECLARE],
+[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
+                                          [description])))[]dnl
+m4_pushdef([_libtool_name],
+    m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
+m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
+    [0], [_libtool_name=[$]$1],
+    [1], [_libtool_name=$lt_[]$1],
+    [2], [_libtool_name=$lt_[]$1],
+    [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
+m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
+])
+
+
+# _LT_LIBTOOL_CONFIG_VARS
+# -----------------------
+# Produce commented declarations of non-tagged libtool config variables
+# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool'
+# script.  Tagged libtool config variables (even for the LIBTOOL CONFIG
+# section) are produced by _LT_LIBTOOL_TAG_VARS.
+m4_defun([_LT_LIBTOOL_CONFIG_VARS],
+[m4_foreach([_lt_var],
+    m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
+    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAG_VARS(TAG)
+# -------------------------
+m4_define([_LT_LIBTOOL_TAG_VARS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
+    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
+
+
+# _LT_TAGVAR(VARNAME, [TAGNAME])
+# ------------------------------
+m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
+
+
+# _LT_CONFIG_COMMANDS
+# -------------------
+# Send accumulated output to $CONFIG_STATUS.  Thanks to the lists of
+# variables for single and double quote escaping we saved from calls
+# to _LT_DECL, we can put quote escaped variables declarations
+# into 'config.status', and then the shell code to quote escape them in
+# for loops in 'config.status'.  Finally, any additional code accumulated
+# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
+m4_defun([_LT_CONFIG_COMMANDS],
+[AC_PROVIDE_IFELSE([LT_OUTPUT],
+       dnl If the libtool generation code has been placed in $CONFIG_LT,
+       dnl instead of duplicating it all over again into config.status,
+       dnl then we will have config.status run $CONFIG_LT later, so it
+       dnl needs to know what name is stored there:
+        [AC_CONFIG_COMMANDS([libtool],
+            [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
+    dnl If the libtool generation code is destined for config.status,
+    dnl expand the accumulated commands and init code now:
+    [AC_CONFIG_COMMANDS([libtool],
+        [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
+])#_LT_CONFIG_COMMANDS
+
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
+[
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+_LT_CONFIG_STATUS_DECLARATIONS
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+\$[]1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_quote_varnames); do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[[\\\\\\\`\\"\\\$]]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## 
exclude from sc_prohibit_nested_quotes
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Double-quote double-evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_dquote_varnames); do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[[\\\\\\\`\\"\\\$]]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e 
\\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from 
sc_prohibit_nested_quotes
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+_LT_OUTPUT_LIBTOOL_INIT
+])
+
+# _LT_GENERATED_FILE_INIT(FILE, [COMMENT])
+# ------------------------------------
+# Generate a child script FILE with all initialization necessary to
+# reuse the environment learned by the parent script, and make the
+# file executable.  If COMMENT is supplied, it is inserted after the
+# '#!' sequence but before initialization text begins.  After this
+# macro, additional text can be appended to FILE to form the body of
+# the child script.  The macro ends with non-zero status if the
+# file could not be fully written (such as if the disk is full).
+m4_ifdef([AS_INIT_GENERATED],
+[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])],
+[m4_defun([_LT_GENERATED_FILE_INIT],
+[m4_require([AS_PREPARE])]dnl
+[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl
+[lt_write_fail=0
+cat >$1 <<_ASEOF || lt_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+$2
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$1 <<\_ASEOF || lt_write_fail=1
+AS_SHELL_SANITIZE
+_AS_PREPARE
+exec AS_MESSAGE_FD>&1
+_ASEOF
+test 0 = "$lt_write_fail" && chmod +x $1[]dnl
+m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT
+
+# LT_OUTPUT
+# ---------
+# This macro allows early generation of the libtool script (before
+# AC_OUTPUT is called), incase it is used in configure for compilation
+# tests.
+AC_DEFUN([LT_OUTPUT],
+[: ${CONFIG_LT=./config.lt}
+AC_MSG_NOTICE([creating $CONFIG_LT])
+_LT_GENERATED_FILE_INIT(["$CONFIG_LT"],
+[# Run this file to recreate a libtool stub with the current configuration.])
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+lt_cl_silent=false
+exec AS_MESSAGE_LOG_FD>>config.log
+{
+  echo
+  AS_BOX([Running $as_me.])
+} >&AS_MESSAGE_LOG_FD
+
+lt_cl_help="\
+'$as_me' creates a local libtool stub from the current configuration,
+for use in further configure time tests before the real libtool is
+generated.
+
+Usage: $[0] [[OPTIONS]]
+
+  -h, --help      print this help, then exit
+  -V, --version   print version number, then exit
+  -q, --quiet     do not print progress messages
+  -d, --debug     don't remove temporary files
+
+Report bugs to <bug-libtool gnu org>."
+
+lt_cl_version="\
+m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
+m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
+configured by $[0], generated by m4_PACKAGE_STRING.
+
+Copyright (C) 2011 Free Software Foundation, Inc.
+This config.lt script is free software; the Free Software Foundation
+gives unlimited permision to copy, distribute and modify it."
+
+while test 0 != $[#]
+do
+  case $[1] in
+    --version | --v* | -V )
+      echo "$lt_cl_version"; exit 0 ;;
+    --help | --h* | -h )
+      echo "$lt_cl_help"; exit 0 ;;
+    --debug | --d* | -d )
+      debug=: ;;
+    --quiet | --q* | --silent | --s* | -q )
+      lt_cl_silent=: ;;
+
+    -*) AC_MSG_ERROR([unrecognized option: $[1]
+Try '$[0] --help' for more information.]) ;;
+
+    *) AC_MSG_ERROR([unrecognized argument: $[1]
+Try '$[0] --help' for more information.]) ;;
+  esac
+  shift
+done
+
+if $lt_cl_silent; then
+  exec AS_MESSAGE_FD>/dev/null
+fi
+_LTEOF
+
+cat >>"$CONFIG_LT" <<_LTEOF
+_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
+_LTEOF
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+AC_MSG_NOTICE([creating $ofile])
+_LT_OUTPUT_LIBTOOL_COMMANDS
+AS_EXIT(0)
+_LTEOF
+chmod +x "$CONFIG_LT"
+
+# configure is writing to config.log, but config.lt does its own redirection,
+# appending to config.log, which fails on DOS, as config.log is still kept
+# open by configure.  Here we exec the FD to /dev/null, effectively closing
+# config.log, so it can be properly (re)opened and appended to by config.lt.
+lt_cl_success=:
+test yes = "$silent" &&
+  lt_config_lt_args="$lt_config_lt_args --quiet"
+exec AS_MESSAGE_LOG_FD>/dev/null
+$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
+exec AS_MESSAGE_LOG_FD>>config.log
+$lt_cl_success || AS_EXIT(1)
+])# LT_OUTPUT
+
+
+# _LT_CONFIG(TAG)
+# ---------------
+# If TAG is the built-in tag, create an initial libtool script with a
+# default configuration from the untagged config vars.  Otherwise add code
+# to config.status for appending the configuration named by TAG from the
+# matching tagged config vars.
+m4_defun([_LT_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_CONFIG_SAVE_COMMANDS([
+  m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
+  m4_if(_LT_TAG, [C], [
+    # See if we are running on zsh, and set the options that allow our
+    # commands through without removal of \ escapes.
+    if test -n "${ZSH_VERSION+set}"; then
+      setopt NO_GLOB_SUBST
+    fi
+
+    cfgfile=${ofile}T
+    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+    $RM "$cfgfile"
+
+    cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+# Generated automatically by $as_me ($PACKAGE) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+
+# Provide generalized library-building support services.
+# Written by Gordon Matzigkeit, 1996
+
+_LT_COPYING
+_LT_LIBTOOL_TAGS
+
+# Configured defaults for sys_lib_dlsearch_path munging.
+: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}
+
+# ### BEGIN LIBTOOL CONFIG
+_LT_LIBTOOL_CONFIG_VARS
+_LT_LIBTOOL_TAG_VARS
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+    cat <<'_LT_EOF' >> "$cfgfile"
+
+# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE
+
+_LT_PREPARE_MUNGE_PATH_LIST
+_LT_PREPARE_CC_BASENAME
+
+# ### END FUNCTIONS SHARED WITH CONFIGURE
+
+_LT_EOF
+
+  case $host_os in
+  aix3*)
+    cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test set != "${COLLECT_NAMES+set}"; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+_LT_EOF
+    ;;
+  esac
+
+  _LT_PROG_LTMAIN
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '$q' "$ltmain" >> "$cfgfile" \
+     || (rm -f "$cfgfile"; exit 1)
+
+   mv -f "$cfgfile" "$ofile" ||
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+],
+[cat <<_LT_EOF >> "$ofile"
+
+dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
+dnl in a comment (ie after a #).
+# ### BEGIN LIBTOOL TAG CONFIG: $1
+_LT_LIBTOOL_TAG_VARS(_LT_TAG)
+# ### END LIBTOOL TAG CONFIG: $1
+_LT_EOF
+])dnl /m4_if
+],
+[m4_if([$1], [], [
+    PACKAGE='$PACKAGE'
+    VERSION='$VERSION'
+    RM='$RM'
+    ofile='$ofile'], [])
+])dnl /_LT_CONFIG_SAVE_COMMANDS
+])# _LT_CONFIG
+
+
+# LT_SUPPORTED_TAG(TAG)
+# ---------------------
+# Trace this macro to discover what tags are supported by the libtool
+# --tag option, using:
+#    autoconf --trace 'LT_SUPPORTED_TAG:$1'
+AC_DEFUN([LT_SUPPORTED_TAG], [])
+
+
+# C support is built-in for now
+m4_define([_LT_LANG_C_enabled], [])
+m4_define([_LT_TAGS], [])
+
+
+# LT_LANG(LANG)
+# -------------
+# Enable libtool support for the given language if not already enabled.
+AC_DEFUN([LT_LANG],
+[AC_BEFORE([$0], [LT_OUTPUT])dnl
+m4_case([$1],
+  [C],                 [_LT_LANG(C)],
+  [C++],               [_LT_LANG(CXX)],
+  [Go],                        [_LT_LANG(GO)],
+  [Java],              [_LT_LANG(GCJ)],
+  [Fortran 77],                [_LT_LANG(F77)],
+  [Fortran],           [_LT_LANG(FC)],
+  [Windows Resource],  [_LT_LANG(RC)],
+  [m4_ifdef([_LT_LANG_]$1[_CONFIG],
+    [_LT_LANG($1)],
+    [m4_fatal([$0: unsupported language: "$1"])])])dnl
+])# LT_LANG
+
+
+# _LT_LANG(LANGNAME)
+# ------------------
+m4_defun([_LT_LANG],
+[m4_ifdef([_LT_LANG_]$1[_enabled], [],
+  [LT_SUPPORTED_TAG([$1])dnl
+  m4_append([_LT_TAGS], [$1 ])dnl
+  m4_define([_LT_LANG_]$1[_enabled], [])dnl
+  _LT_LANG_$1_CONFIG($1)])dnl
+])# _LT_LANG
+
+
+m4_ifndef([AC_PROG_GO], [
+############################################################
+# NOTE: This macro has been submitted for inclusion into   #
+#  GNU Autoconf as AC_PROG_GO.  When it is available in    #
+#  a released version of Autoconf we should remove this    #
+#  macro and use it instead.                               #
+############################################################
+m4_defun([AC_PROG_GO],
+[AC_LANG_PUSH(Go)dnl
+AC_ARG_VAR([GOC],     [Go compiler command])dnl
+AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl
+_AC_ARG_VAR_LDFLAGS()dnl
+AC_CHECK_TOOL(GOC, gccgo)
+if test -z "$GOC"; then
+  if test -n "$ac_tool_prefix"; then
+    AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo])
+  fi
+fi
+if test -z "$GOC"; then
+  AC_CHECK_PROG(GOC, gccgo, gccgo, false)
+fi
+])#m4_defun
+])#m4_ifndef
+
+
+# _LT_LANG_DEFAULT_CONFIG
+# -----------------------
+m4_defun([_LT_LANG_DEFAULT_CONFIG],
+[AC_PROVIDE_IFELSE([AC_PROG_CXX],
+  [LT_LANG(CXX)],
+  [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_F77],
+  [LT_LANG(F77)],
+  [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_FC],
+  [LT_LANG(FC)],
+  [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
+
+dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
+dnl pulling things in needlessly.
+AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+  [LT_LANG(GCJ)],
+  [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+    [LT_LANG(GCJ)],
+    [AC_PROVIDE_IFELSE([LT_PROG_GCJ],
+      [LT_LANG(GCJ)],
+      [m4_ifdef([AC_PROG_GCJ],
+       [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
+       m4_ifdef([A][M_PROG_GCJ],
+       [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
+       m4_ifdef([LT_PROG_GCJ],
+       [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
+
+AC_PROVIDE_IFELSE([AC_PROG_GO],
+  [LT_LANG(GO)],
+  [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])])
+
+AC_PROVIDE_IFELSE([LT_PROG_RC],
+  [LT_LANG(RC)],
+  [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
+])# _LT_LANG_DEFAULT_CONFIG
+
+# Obsolete macros:
+AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
+AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
+AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
+AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
+AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
+dnl AC_DEFUN([AC_LIBTOOL_F77], [])
+dnl AC_DEFUN([AC_LIBTOOL_FC], [])
+dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
+dnl AC_DEFUN([AC_LIBTOOL_RC], [])
+
+
+# _LT_TAG_COMPILER
+# ----------------
+m4_defun([_LT_TAG_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
+
+_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
+_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
+_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
+_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_TAG_COMPILER
+
+
+# _LT_COMPILER_BOILERPLATE
+# ------------------------
+# Check for compiler boilerplate output or warnings with
+# the simple compiler test code.
+m4_defun([_LT_COMPILER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+])# _LT_COMPILER_BOILERPLATE
+
+
+# _LT_LINKER_BOILERPLATE
+# ----------------------
+# Check for linker boilerplate output or warnings with
+# the simple link test code.
+m4_defun([_LT_LINKER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+])# _LT_LINKER_BOILERPLATE
+
+# _LT_REQUIRED_DARWIN_CHECKS
+# -------------------------
+m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
+  case $host_os in
+    rhapsody* | darwin*)
+    AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
+    AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
+    AC_CHECK_TOOL([LIPO], [lipo], [:])
+    AC_CHECK_TOOL([OTOOL], [otool], [:])
+    AC_CHECK_TOOL([OTOOL64], [otool64], [:])
+    _LT_DECL([], [DSYMUTIL], [1],
+      [Tool to manipulate archived DWARF debug symbol files on Mac OS X])
+    _LT_DECL([], [NMEDIT], [1],
+      [Tool to change global to local symbols on Mac OS X])
+    _LT_DECL([], [LIPO], [1],
+      [Tool to manipulate fat objects and archives on Mac OS X])
+    _LT_DECL([], [OTOOL], [1],
+      [ldd/readelf like tool for Mach-O binaries on Mac OS X])
+    _LT_DECL([], [OTOOL64], [1],
+      [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
+
+    AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
+      [lt_cv_apple_cc_single_mod=no
+      if test -z "$LT_MULTI_MODULE"; then
+       # By default we will add the -single_module flag. You can override
+       # by either setting the environment variable LT_MULTI_MODULE
+       # non-empty at configure time, or by adding -multi_module to the
+       # link flags.
+       rm -rf libconftest.dylib*
+       echo "int foo(void){return 1;}" > conftest.c
+       echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
+       $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+         -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+        _lt_result=$?
+       # If there is a non-empty error log, and "single_module"
+       # appears in it, assume the flag caused a linker warning
+        if test -s conftest.err && $GREP single_module conftest.err; then
+         cat conftest.err >&AS_MESSAGE_LOG_FD
+       # Otherwise, if the output was created with a 0 exit code from
+       # the compiler, it worked.
+       elif test -f libconftest.dylib && test 0 = "$_lt_result"; then
+         lt_cv_apple_cc_single_mod=yes
+       else
+         cat conftest.err >&AS_MESSAGE_LOG_FD
+       fi
+       rm -rf libconftest.dylib*
+       rm -f conftest.*
+      fi])
+
+    AC_CACHE_CHECK([for -exported_symbols_list linker flag],
+      [lt_cv_ld_exported_symbols_list],
+      [lt_cv_ld_exported_symbols_list=no
+      save_LDFLAGS=$LDFLAGS
+      echo "_main" > conftest.sym
+      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+      AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+       [lt_cv_ld_exported_symbols_list=yes],
+       [lt_cv_ld_exported_symbols_list=no])
+       LDFLAGS=$save_LDFLAGS
+    ])
+
+    AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load],
+      [lt_cv_ld_force_load=no
+      cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD
+      $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
+      echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
+      $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
+      echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD
+      $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD
+      cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" 
&AS_MESSAGE_LOG_FD
+      $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+      _lt_result=$?
+      if test -s conftest.err && $GREP force_load conftest.err; then
+       cat conftest.err >&AS_MESSAGE_LOG_FD
+      elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then
+       lt_cv_ld_force_load=yes
+      else
+       cat conftest.err >&AS_MESSAGE_LOG_FD
+      fi
+        rm -f conftest.err libconftest.a conftest conftest.c
+        rm -rf conftest.dSYM
+    ])
+    case $host_os in
+    rhapsody* | darwin1.[[012]])
+      _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
+    darwin1.*)
+      _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+    darwin*) # darwin 5.x on
+      # if running on 10.5 or later, the deployment target defaults
+      # to the OS version, if on x86, and 10.4, the deployment
+      # target defaults to 10.4. Don't you love it?
+      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+       10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
+         _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
+       10.[[012]][[,.]]*)
+         _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+       10.*)
+         _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
+      esac
+    ;;
+  esac
+    if test yes = "$lt_cv_apple_cc_single_mod"; then
+      _lt_dar_single_mod='$single_module'
+    fi
+    if test yes = "$lt_cv_ld_exported_symbols_list"; then
+      _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym'
+    else
+      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib'
+    fi
+    if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then
+      _lt_dsymutil='~$DSYMUTIL $lib || :'
+    else
+      _lt_dsymutil=
+    fi
+    ;;
+  esac
+])
+
+
+# _LT_DARWIN_LINKER_FEATURES([TAG])
+# ---------------------------------
+# Checks for linker and compiler features on darwin
+m4_defun([_LT_DARWIN_LINKER_FEATURES],
+[
+  m4_require([_LT_REQUIRED_DARWIN_CHECKS])
+  _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+  _LT_TAGVAR(hardcode_direct, $1)=no
+  _LT_TAGVAR(hardcode_automatic, $1)=yes
+  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+  if test yes = "$lt_cv_ld_force_load"; then
+    _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test  -n \"$conv\" && 
new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+    m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes],
+                  [FC],  [_LT_TAGVAR(compiler_needs_object, $1)=yes])
+  else
+    _LT_TAGVAR(whole_archive_flag_spec, $1)=''
+  fi
+  _LT_TAGVAR(link_all_deplibs, $1)=yes
+  _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined
+  case $cc_basename in
+     ifort*|nagfor*) _lt_dar_can_shared=yes ;;
+     *) _lt_dar_can_shared=$GCC ;;
+  esac
+  if test yes = "$_lt_dar_can_shared"; then
+    output_verbose_link_cmd=func_echo_all
+    _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs 
\$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
+    _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs 
\$compiler_flags$_lt_dsymutil"
+    _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > 
\$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs 
\$compiler_flags -install_name \$rpath/\$soname \$verstring 
$_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
+    _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > 
\$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs 
\$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
+    m4_if([$1], [CXX],
+[   if test yes != "$lt_cv_apple_cc_single_mod"; then
+      _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC 
-dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name 
\$rpath/\$soname \$verstring$_lt_dsymutil"
+      _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > 
\$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o 
\$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags 
-install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
+    fi
+],[])
+  else
+  _LT_TAGVAR(ld_shlibs, $1)=no
+  fi
+])
+
+# _LT_SYS_MODULE_PATH_AIX([TAGNAME])
+# ----------------------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+# Store the results from the different compilers for each TAGNAME.
+# Allow to override them for all tags through lt_cv_aix_libpath.
+m4_defun([_LT_SYS_MODULE_PATH_AIX],
+[m4_require([_LT_DECL_SED])dnl
+if test set = "${lt_cv_aix_libpath+set}"; then
+  aix_libpath=$lt_cv_aix_libpath
+else
+  AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])],
+  [AC_LINK_IFELSE([AC_LANG_PROGRAM],[
+  lt_aix_libpath_sed='[
+      /Import File Strings/,/^$/ {
+         /^0/ {
+             s/^0  *\([^ ]*\) *$/\1/
+             p
+         }
+      }]'
+  _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e 
"$lt_aix_libpath_sed"`
+  # Check for a 64-bit object if we didn't find anything.
+  if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
+    _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e 
"$lt_aix_libpath_sed"`
+  fi],[])
+  if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
+    _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib
+  fi
+  ])
+  aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])
+fi
+])# _LT_SYS_MODULE_PATH_AIX
+
+
+# _LT_SHELL_INIT(ARG)
+# -------------------
+m4_define([_LT_SHELL_INIT],
+[m4_divert_text([M4SH-INIT], [$1
+])])# _LT_SHELL_INIT
+
+
+
+# _LT_PROG_ECHO_BACKSLASH
+# -----------------------
+# Find how we can fake an echo command that does not interpret backslash.
+# In particular, with Autoconf 2.60 or later we add some code to the start
+# of the generated configure script that will find a shell with a builtin
+# printf (that we can use as an echo command).
+m4_defun([_LT_PROG_ECHO_BACKSLASH],
+[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+AC_MSG_CHECKING([how to print strings])
+# Test print first, because it will be a builtin if present.
+if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
+   test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='printf %s\n'
+else
+  # Use this function as a fallback that always works.
+  func_fallback_echo ()
+  {
+    eval 'cat <<_LTECHO_EOF
+$[]1
+_LTECHO_EOF'
+  }
+  ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+    $ECHO "$*"
+}
+
+case $ECHO in
+  printf*) AC_MSG_RESULT([printf]) ;;
+  print*) AC_MSG_RESULT([print -r]) ;;
+  *) AC_MSG_RESULT([cat]) ;;
+esac
+
+m4_ifdef([_AS_DETECT_SUGGESTED],
+[_AS_DETECT_SUGGESTED([
+  test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || (
+    
ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+    ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+    ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+    PATH=/empty FPATH=/empty; export PATH FPATH
+    test "X`printf %s $ECHO`" = "X$ECHO" \
+      || test "X`print -r -- $ECHO`" = "X$ECHO" )])])
+
+_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
+_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes])
+])# _LT_PROG_ECHO_BACKSLASH
+
+
+# _LT_WITH_SYSROOT
+# ----------------
+AC_DEFUN([_LT_WITH_SYSROOT],
+[AC_MSG_CHECKING([for sysroot])
+AC_ARG_WITH([sysroot],
+[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@],
+  [Search for dependent libraries within DIR (or the compiler's sysroot
+   if not specified).])],
+[], [with_sysroot=no])
+
+dnl lt_sysroot will always be passed unquoted.  We quote it here
+dnl in case the user passed a directory name.
+lt_sysroot=
+case $with_sysroot in #(
+ yes)
+   if test yes = "$GCC"; then
+     lt_sysroot=`$CC --print-sysroot 2>/dev/null`
+   fi
+   ;; #(
+ /*)
+   lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"`
+   ;; #(
+ no|'')
+   ;; #(
+ *)
+   AC_MSG_RESULT([$with_sysroot])
+   AC_MSG_ERROR([The sysroot must be an absolute path.])
+   ;;
+esac
+
+ AC_MSG_RESULT([${lt_sysroot:-no}])
+_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl
+[dependent libraries, and where our libraries should be installed.])])
+
+# _LT_ENABLE_LOCK
+# ---------------
+m4_defun([_LT_ENABLE_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+  [AS_HELP_STRING([--disable-libtool-lock],
+    [avoid locking (might break parallel builds)])])
+test no = "$enable_libtool_lock" || enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out what ABI is being produced by ac_compile, and set mode
+  # options accordingly.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.$ac_objext` in
+      *ELF-32*)
+       HPUX_IA64_MODE=32
+       ;;
+      *ELF-64*)
+       HPUX_IA64_MODE=64
+       ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out what ABI is being produced by ac_compile, and set linker
+  # options accordingly.
+  echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    if test yes = "$lt_cv_prog_gnu_ld"; then
+      case `/usr/bin/file conftest.$ac_objext` in
+       *32-bit*)
+         LD="${LD-ld} -melf32bsmip"
+         ;;
+       *N32*)
+         LD="${LD-ld} -melf32bmipn32"
+         ;;
+       *64-bit*)
+         LD="${LD-ld} -melf64bmip"
+       ;;
+      esac
+    else
+      case `/usr/bin/file conftest.$ac_objext` in
+       *32-bit*)
+         LD="${LD-ld} -32"
+         ;;
+       *N32*)
+         LD="${LD-ld} -n32"
+         ;;
+       *64-bit*)
+         LD="${LD-ld} -64"
+         ;;
+      esac
+    fi
+  fi
+  rm -rf conftest*
+  ;;
+
+mips64*-*linux*)
+  # Find out what ABI is being produced by ac_compile, and set linker
+  # options accordingly.
+  echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    emul=elf
+    case `/usr/bin/file conftest.$ac_objext` in
+      *32-bit*)
+       emul="${emul}32"
+       ;;
+      *64-bit*)
+       emul="${emul}64"
+       ;;
+    esac
+    case `/usr/bin/file conftest.$ac_objext` in
+      *MSB*)
+       emul="${emul}btsmip"
+       ;;
+      *LSB*)
+       emul="${emul}ltsmip"
+       ;;
+    esac
+    case `/usr/bin/file conftest.$ac_objext` in
+      *N32*)
+       emul="${emul}n32"
+       ;;
+    esac
+    LD="${LD-ld} -m $emul"
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+  # Find out what ABI is being produced by ac_compile, and set linker
+  # options accordingly.  Note that the listed cases only cover the
+  # situations where additional linker options are needed (such as when
+  # doing 32-bit compilation for a host where ld defaults to 64-bit, or
+  # vice versa); the common cases where no linker options are needed do
+  # not appear in the list.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.o` in
+      *32-bit*)
+       case $host in
+         x86_64-*kfreebsd*-gnu)
+           LD="${LD-ld} -m elf_i386_fbsd"
+           ;;
+         x86_64-*linux*)
+           case `/usr/bin/file conftest.o` in
+             *x86-64*)
+               LD="${LD-ld} -m elf32_x86_64"
+               ;;
+             *)
+               LD="${LD-ld} -m elf_i386"
+               ;;
+           esac
+           ;;
+         powerpc64le-*linux*)
+           LD="${LD-ld} -m elf32lppclinux"
+           ;;
+         powerpc64-*linux*)
+           LD="${LD-ld} -m elf32ppclinux"
+           ;;
+         s390x-*linux*)
+           LD="${LD-ld} -m elf_s390"
+           ;;
+         sparc64-*linux*)
+           LD="${LD-ld} -m elf32_sparc"
+           ;;
+       esac
+       ;;
+      *64-bit*)
+       case $host in
+         x86_64-*kfreebsd*-gnu)
+           LD="${LD-ld} -m elf_x86_64_fbsd"
+           ;;
+         x86_64-*linux*)
+           LD="${LD-ld} -m elf_x86_64"
+           ;;
+         powerpcle-*linux*)
+           LD="${LD-ld} -m elf64lppc"
+           ;;
+         powerpc-*linux*)
+           LD="${LD-ld} -m elf64ppc"
+           ;;
+         s390*-*linux*|s390*-*tpf*)
+           LD="${LD-ld} -m elf64_s390"
+           ;;
+         sparc*-*linux*)
+           LD="${LD-ld} -m elf64_sparc"
+           ;;
+       esac
+       ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS=$CFLAGS
+  CFLAGS="$CFLAGS -belf"
+  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+    [AC_LANG_PUSH(C)
+     AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+     AC_LANG_POP])
+  if test yes != "$lt_cv_cc_needs_belf"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS=$SAVE_CFLAGS
+  fi
+  ;;
+*-*solaris*)
+  # Find out what ABI is being produced by ac_compile, and set linker
+  # options accordingly.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.o` in
+    *64-bit*)
+      case $lt_cv_prog_gnu_ld in
+      yes*)
+        case $host in
+        i?86-*-solaris*|x86_64-*-solaris*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
+        sparc*-*-solaris*)
+          LD="${LD-ld} -m elf64_sparc"
+          ;;
+        esac
+        # GNU ld 2.21 introduced _sol2 emulations.  Use them if available.
+        if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
+          LD=${LD-ld}_sol2
+        fi
+        ;;
+      *)
+       if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+         LD="${LD-ld} -64"
+       fi
+       ;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+esac
+
+need_locks=$enable_libtool_lock
+])# _LT_ENABLE_LOCK
+
+
+# _LT_PROG_AR
+# -----------
+m4_defun([_LT_PROG_AR],
+[AC_CHECK_TOOLS(AR, [ar], false)
+: ${AR=ar}
+: ${AR_FLAGS=cru}
+_LT_DECL([], [AR], [1], [The archiver])
+_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive])
+
+AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file],
+  [lt_cv_ar_at_file=no
+   AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
+     [echo conftest.$ac_objext > conftest.lst
+      lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD'
+      AC_TRY_EVAL([lt_ar_try])
+      if test 0 -eq "$ac_status"; then
+       # Ensure the archiver fails upon bogus file names.
+       rm -f conftest.$ac_objext libconftest.a
+       AC_TRY_EVAL([lt_ar_try])
+       if test 0 -ne "$ac_status"; then
+          lt_cv_ar_at_file=@
+        fi
+      fi
+      rm -f conftest.* libconftest.a
+     ])
+  ])
+
+if test no = "$lt_cv_ar_at_file"; then
+  archiver_list_spec=
+else
+  archiver_list_spec=$lt_cv_ar_at_file
+fi
+_LT_DECL([], [archiver_list_spec], [1],
+  [How to feed a file listing to the archiver])
+])# _LT_PROG_AR
+
+
+# _LT_CMD_OLD_ARCHIVE
+# -------------------
+m4_defun([_LT_CMD_OLD_ARCHIVE],
+[_LT_PROG_AR
+
+AC_CHECK_TOOL(STRIP, strip, :)
+test -z "$STRIP" && STRIP=:
+_LT_DECL([], [STRIP], [1], [A symbol stripping program])
+
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+test -z "$RANLIB" && RANLIB=:
+_LT_DECL([], [RANLIB], [1],
+    [Commands used to install an old-style archive])
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  bitrig* | openbsd*)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
+    ;;
+  *)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
+fi
+
+case $host_os in
+  darwin*)
+    lock_old_archive_extraction=yes ;;
+  *)
+    lock_old_archive_extraction=no ;;
+esac
+_LT_DECL([], [old_postinstall_cmds], [2])
+_LT_DECL([], [old_postuninstall_cmds], [2])
+_LT_TAGDECL([], [old_archive_cmds], [2],
+    [Commands used to build an old-style archive])
+_LT_DECL([], [lock_old_archive_extraction], [0],
+    [Whether to use a lock for old archive extraction])
+])# _LT_CMD_OLD_ARCHIVE
+
+
+# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#              [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([_LT_COMPILER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+   m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$3"  ## exclude from sc_useless_quotes_in_assignment
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       $2=yes
+     fi
+   fi
+   $RM conftest*
+])
+
+if test yes = "[$]$2"; then
+    m4_if([$5], , :, [$5])
+else
+    m4_if([$6], , :, [$6])
+fi
+])# _LT_COMPILER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
+
+
+# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#                  [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------
+# Check whether the given linker option works
+AC_DEFUN([_LT_LINKER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+   save_LDFLAGS=$LDFLAGS
+   LDFLAGS="$LDFLAGS $3"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&AS_MESSAGE_LOG_FD
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         $2=yes
+       fi
+     else
+       $2=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS=$save_LDFLAGS
+])
+
+if test yes = "[$]$2"; then
+    m4_if([$4], , :, [$4])
+else
+    m4_if([$5], , :, [$5])
+fi
+])# _LT_LINKER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
+
+
+# LT_CMD_MAX_LEN
+#---------------
+AC_DEFUN([LT_CMD_MAX_LEN],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+  i=0
+  teststring=ABCD
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw* | cegcc*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  mint*)
+    # On MiNT this can take a long time and run out of memory.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536      # usable default for all BSDs
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+
+  interix*)
+    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+    lt_cv_sys_max_cmd_len=196608
+    ;;
+
+  os2*)
+    # The test takes a long time on OS/2.
+    lt_cv_sys_max_cmd_len=8192
+    ;;
+
+  osf*)
+    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+    # nice to cause kernel panics so lets avoid the loop below.
+    # First set a reasonable default.
+    lt_cv_sys_max_cmd_len=16384
+    #
+    if test -x /sbin/sysconfig; then
+      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+      esac
+    fi
+    ;;
+  sco3.2v5*)
+    lt_cv_sys_max_cmd_len=102400
+    ;;
+  sysv5* | sco5v6* | sysv4.2uw2*)
+    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+    if test -n "$kargmax"; then
+      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[        ]]//'`
+    else
+      lt_cv_sys_max_cmd_len=32768
+    fi
+    ;;
+  *)
+    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+    if test -n "$lt_cv_sys_max_cmd_len" && \
+       test undefined != "$lt_cv_sys_max_cmd_len"; then
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    else
+      # Make teststring a little bigger before we do anything with it.
+      # a 1K string should be a reasonable start.
+      for i in 1 2 3 4 5 6 7 8; do
+        teststring=$teststring$teststring
+      done
+      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+      # If test is not a shell built-in, we'll probably end up computing a
+      # maximum length that is only half of the actual maximum length, but
+      # we can't tell.
+      while { test X`env echo "$teststring$teststring" 2>/dev/null` \
+                = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+             test 17 != "$i" # 1/2 MB should be enough
+      do
+        i=`expr $i + 1`
+        teststring=$teststring$teststring
+      done
+      # Only check the string length outside the loop.
+      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+      teststring=
+      # Add a significant safety factor because C++ compilers can tack on
+      # massive amounts of additional arguments before passing them to the
+      # linker.  It appears as though 1/2 is a usable value.
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    fi
+    ;;
+  esac
+])
+if test -n "$lt_cv_sys_max_cmd_len"; then
+  AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+  AC_MSG_RESULT(none)
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+_LT_DECL([], [max_cmd_len], [0],
+    [What is the maximum length of a command?])
+])# LT_CMD_MAX_LEN
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
+
+
+# _LT_HEADER_DLFCN
+# ----------------
+m4_defun([_LT_HEADER_DLFCN],
+[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
+])# _LT_HEADER_DLFCN
+
+
+# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+#                      ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ----------------------------------------------------------------
+m4_defun([_LT_TRY_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test yes = "$cross_compiling"; then :
+  [$4]
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+[#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL          RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL                DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL                0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW           RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW         DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW       RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW     DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW     0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisibility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+         if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+       }
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}]
+_LT_EOF
+  if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then
+    (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) $1 ;;
+      x$lt_dlneed_uscore) $2 ;;
+      x$lt_dlunknown|x*) $3 ;;
+    esac
+  else :
+    # compilation failed
+    $3
+  fi
+fi
+rm -fr conftest*
+])# _LT_TRY_DLOPEN_SELF
+
+
+# LT_SYS_DLOPEN_SELF
+# ------------------
+AC_DEFUN([LT_SYS_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test yes != "$enable_dlopen"; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen=load_add_on
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32* | cegcc*)
+    lt_cv_dlopen=LoadLibrary
+    lt_cv_dlopen_libs=
+    ;;
+
+  cygwin*)
+    lt_cv_dlopen=dlopen
+    lt_cv_dlopen_libs=
+    ;;
+
+  darwin*)
+    # if libdl is installed we need to link against it
+    AC_CHECK_LIB([dl], [dlopen],
+               [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[
+    lt_cv_dlopen=dyld
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ])
+    ;;
+
+  tpf*)
+    # Don't try to run any link tests for TPF.  We know it's impossible
+    # because TPF is a cross-compiler, and we know how we open DSOs.
+    lt_cv_dlopen=dlopen
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=no
+    ;;
+
+  *)
+    AC_CHECK_FUNC([shl_load],
+         [lt_cv_dlopen=shl_load],
+      [AC_CHECK_LIB([dld], [shl_load],
+           [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld],
+       [AC_CHECK_FUNC([dlopen],
+             [lt_cv_dlopen=dlopen],
+         [AC_CHECK_LIB([dl], [dlopen],
+               [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],
+           [AC_CHECK_LIB([svld], [dlopen],
+                 [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld],
+             [AC_CHECK_LIB([dld], [dld_link],
+                   [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld])
+             ])
+           ])
+         ])
+       ])
+      ])
+    ;;
+  esac
+
+  if test no = "$lt_cv_dlopen"; then
+    enable_dlopen=no
+  else
+    enable_dlopen=yes
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS=$CPPFLAGS
+    test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS=$LDFLAGS
+    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS=$LIBS
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    AC_CACHE_CHECK([whether a program can dlopen itself],
+         lt_cv_dlopen_self, [dnl
+         _LT_TRY_DLOPEN_SELF(
+           lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+           lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+    ])
+
+    if test yes = "$lt_cv_dlopen_self"; then
+      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+      AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+         lt_cv_dlopen_self_static, [dnl
+         _LT_TRY_DLOPEN_SELF(
+           lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+           lt_cv_dlopen_self_static=no,  lt_cv_dlopen_self_static=cross)
+      ])
+    fi
+
+    CPPFLAGS=$save_CPPFLAGS
+    LDFLAGS=$save_LDFLAGS
+    LIBS=$save_LIBS
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+_LT_DECL([dlopen_support], [enable_dlopen], [0],
+        [Whether dlopen is supported])
+_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
+        [Whether dlopen of programs is supported])
+_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
+        [Whether dlopen of statically linked programs is supported])
+])# LT_SYS_DLOPEN_SELF
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
+
+
+# _LT_COMPILER_C_O([TAGNAME])
+# ---------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler.
+# This macro does not hard code the compiler like AC_PROG_CC_C_O.
+m4_defun([_LT_COMPILER_C_O],
+[m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+     fi
+   fi
+   chmod u+w . 2>&AS_MESSAGE_LOG_FD
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+])
+_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
+       [Does compiler simultaneously support -c and -o options?])
+])# _LT_COMPILER_C_O
+
+
+# _LT_COMPILER_FILE_LOCKS([TAGNAME])
+# ----------------------------------
+# Check to see if we can do hard links to lock some files if needed
+m4_defun([_LT_COMPILER_FILE_LOCKS],
+[m4_require([_LT_ENABLE_LOCK])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_COMPILER_C_O([$1])
+
+hard_links=nottested
+if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then
+  # do not overwrite the value of need_locks provided by the user
+  AC_MSG_CHECKING([if we can lock with hard links])
+  hard_links=yes
+  $RM conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  AC_MSG_RESULT([$hard_links])
+  if test no = "$hard_links"; then
+    AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe])
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
+])# _LT_COMPILER_FILE_LOCKS
+
+
+# _LT_CHECK_OBJDIR
+# ----------------
+m4_defun([_LT_CHECK_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+_LT_DECL([], [objdir], [0],
+         [The name of the directory that contains temporary libtool files])dnl
+m4_pattern_allow([LT_OBJDIR])dnl
+AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/",
+  [Define to the sub-directory where libtool stores uninstalled libraries.])
+])# _LT_CHECK_OBJDIR
+
+
+# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
+# --------------------------------------
+# Check hardcoding attributes.
+m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
+   test -n "$_LT_TAGVAR(runpath_var, $1)" ||
+   test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then
+
+  # We can hardcode non-existent directories.
+  if test no != "$_LT_TAGVAR(hardcode_direct, $1)" &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" &&
+     test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then
+    # Linking always hardcodes the temporary library directory.
+    _LT_TAGVAR(hardcode_action, $1)=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    _LT_TAGVAR(hardcode_action, $1)=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  _LT_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
+
+if test relink = "$_LT_TAGVAR(hardcode_action, $1)" ||
+   test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test yes = "$shlibpath_overrides_runpath" ||
+     test no = "$enable_shared"; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+_LT_TAGDECL([], [hardcode_action], [0],
+    [How to hardcode a shared library path into an executable])
+])# _LT_LINKER_HARDCODE_LIBPATH
+
+
+# _LT_CMD_STRIPLIB
+# ----------------
+m4_defun([_LT_CMD_STRIPLIB],
+[m4_require([_LT_DECL_EGREP])
+striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  AC_MSG_RESULT([yes])
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+  case $host_os in
+  darwin*)
+    if test -n "$STRIP"; then
+      striplib="$STRIP -x"
+      old_striplib="$STRIP -S"
+      AC_MSG_RESULT([yes])
+    else
+      AC_MSG_RESULT([no])
+    fi
+    ;;
+  *)
+    AC_MSG_RESULT([no])
+    ;;
+  esac
+fi
+_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
+_LT_DECL([], [striplib], [1])
+])# _LT_CMD_STRIPLIB
+
+
+# _LT_PREPARE_MUNGE_PATH_LIST
+# ---------------------------
+# Make sure func_munge_path_list() is defined correctly.
+m4_defun([_LT_PREPARE_MUNGE_PATH_LIST],
+[[# func_munge_path_list VARIABLE PATH
+# -----------------------------------
+# VARIABLE is name of variable containing _space_ separated list of
+# directories to be munged by the contents of PATH, which is string
+# having a format:
+# "DIR[:DIR]:"
+#       string "DIR[ DIR]" will be prepended to VARIABLE
+# ":DIR[:DIR]"
+#       string "DIR[ DIR]" will be appended to VARIABLE
+# "DIRP[:DIRP]::[DIRA:]DIRA"
+#       string "DIRP[ DIRP]" will be prepended to VARIABLE and string
+#       "DIRA[ DIRA]" will be appended to VARIABLE
+# "DIR[:DIR]"
+#       VARIABLE will be replaced by "DIR[ DIR]"
+func_munge_path_list ()
+{
+    case x S|@2 in
+    x)
+        ;;
+    *:)
+        eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \ S|@@S|@1\"
+        ;;
+    x:*)
+        eval @S|@1=\"\ S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\"
+        ;;
+    *::*)
+        eval @S|@1=\"\ S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
+        eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \ S|@@S|@1\"
+        ;;
+    *)
+        eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\"
+        ;;
+    esac
+}
+]])# _LT_PREPARE_PATH_LIST
+
+
+# _LT_SYS_DYNAMIC_LINKER([TAG])
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+m4_defun([_LT_SYS_DYNAMIC_LINKER],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_OBJDUMP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl
+AC_MSG_CHECKING([dynamic linker characteristics])
+m4_if([$1],
+       [], [
+if test yes = "$GCC"; then
+  case $host_os in
+    darwin*) lt_awk_arg='/^libraries:/,/LR/' ;;
+    *) lt_awk_arg='/^libraries:/' ;;
+  esac
+  case $host_os in
+    mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;;
+    *) lt_sed_strip_eq='s|=/|/|g' ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e 
$lt_sed_strip_eq`
+  case $lt_search_path_spec in
+  *\;*)
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+    ;;
+  *)
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+    ;;
+  esac
+  # Ok, now we have the path, separated by spaces, we can step through it
+  # and add multilib dir if necessary...
+  lt_tmp_lt_search_path_spec=
+  lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+  # ...but if some path component already ends with the multilib dir we assume
+  # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer).
+  case "$lt_multi_os_dir; $lt_search_path_spec " in
+  "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*)
+    lt_multi_os_dir=
+    ;;
+  esac
+  for lt_sys_path in $lt_search_path_spec; do
+    if test -d "$lt_sys_path$lt_multi_os_dir"; then
+      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir"
+    elif test -n "$lt_multi_os_dir"; then
+      test -d "$lt_sys_path" && \
+       lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+    fi
+  done
+  lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+BEGIN {RS = " "; FS = "/|\n";} {
+  lt_foo = "";
+  lt_count = 0;
+  for (lt_i = NF; lt_i > 0; lt_i--) {
+    if ($lt_i != "" && $lt_i != ".") {
+      if ($lt_i == "..") {
+        lt_count++;
+      } else {
+        if (lt_count == 0) {
+          lt_foo = "/" $lt_i lt_foo;
+        } else {
+          lt_count--;
+        }
+      }
+    }
+  }
+  if (lt_foo != "") { lt_freq[[lt_foo]]++; }
+  if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
+}'`
+  # AWK program above erroneously prepends '/' to C:/dos/paths
+  # for these hosts.
+  case $host_os in
+    mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+      $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;;
+  esac
+  sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=.so
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+AC_ARG_VAR([LT_SYS_LIBRARY_PATH],
+[User-defined run-time library search path.])
+
+case $host_os in
+aix3*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='$libname$release$shared_ext$major'
+  ;;
+
+aix[[4-9]]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test ia64 = "$host_cpu"; then
+    # AIX 5 supports IA64
+    library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix 
$libname$shared_ext'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line '#! .'.  This would cause the generated library to
+    # depend on '.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[[01]] | aix4.[[01]].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+          echo ' yes '
+          echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
+       :
+      else
+       can_build_shared=no
+      fi
+      ;;
+    esac
+    # Using Import Files as archive members, it is possible to support
+    # filename-based versioning of shared library archives on AIX. While
+    # this would work for both with and without runtime linking, it will
+    # prevent static linking of such archives. So we do filename-based
+    # shared library versioning with .so extension only, which is used
+    # when both runtime linking and shared linking is enabled.
+    # Unfortunately, runtime linking may impact performance, so we do
+    # not want this to be the default eventually. Also, we use the
+    # versioned .so libs for executables only if there is the -brtl
+    # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
+    # To allow for filename-based versioning support, we need to create
+    # libNAME.so.V as an archive file, containing:
+    # *) an Import File, referring to the versioned filename of the
+    #    archive as well as the shared archive member, telling the
+    #    bitwidth (32 or 64) of that shared object, and providing the
+    #    list of exported symbols of that shared object, eventually
+    #    decorated with the 'weak' keyword
+    # *) the shared object with the F_LOADONLY flag set, to really avoid
+    #    it being seen by the linker.
+    # At run time we better use the real file rather than another symlink,
+    # but for link time we create the symlink libNAME.so -> libNAME.so.V
+
+    case $with_aix_soname,$aix_use_runtimelinking in
+    # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    aix,yes) # traditional libtool
+      dynamic_linker='AIX unversionable lib.so'
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major 
$libname$shared_ext'
+      ;;
+    aix,no) # traditional AIX only
+      dynamic_linker='AIX lib.a[(]lib.so.V[)]'
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='$libname$release.a $libname.a'
+      soname_spec='$libname$release$shared_ext$major'
+      ;;
+    svr4,*) # full svr4 only
+      dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]"
+      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+      # We do not specify a path in Import Files, so LIBPATH fires.
+      shlibpath_overrides_runpath=yes
+      ;;
+    *,yes) # both, prefer svr4
+      dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]"
+      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+      # unpreferred sharedlib libNAME.a needs extra handling
+      postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" 
"$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" 
"$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib 
"$destdir/$func_stripname_result.$libext"'
+      postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test 
"$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
+      # We do not specify a path in Import Files, so LIBPATH fires.
+      shlibpath_overrides_runpath=yes
+      ;;
+    *,no) # both, prefer aix
+      dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]"
+      library_names_spec='$libname$release.a $libname.a'
+      soname_spec='$libname$release$shared_ext$major'
+      # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
+      postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z 
"$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || 
linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname 
$func_stripname_result.so)'
+      postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library 
$library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
+      ;;
+    esac
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  case $host_cpu in
+  powerpc)
+    # Since July 2007 AmigaOS4 officially supports .so libraries.
+    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major 
$libname$shared_ext'
+    ;;
+  m68k)
+    library_names_spec='$libname.ixlibrary $libname.a'
+    # Create ${libname}_ixlibrary.a entries in /sys/libs.
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED 
'\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && 
$LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    ;;
+  esac
+  ;;
+
+beos*)
+  library_names_spec='$libname$shared_ext'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[[45]]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major 
$libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+  version_type=windows
+  shrext_cmds=.dll
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$cc_basename in
+  yes,*)
+    # gcc
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \$file`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname~
+      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+      fi'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 
's/[[.]]/-/g'`$versuffix$shared_ext'
+m4_if([$1], [],[
+      sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"])
+      ;;
+    mingw* | cegcc*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 
's/[[.]]/-/g'`$versuffix$shared_ext'
+      ;;
+    esac
+    dynamic_linker='Win32 ld.exe'
+    ;;
+
+  *,cl*)
+    # Native MSVC
+    libname_spec='$name'
+    soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+    library_names_spec='$libname.dll.lib'
+
+    case $build_os in
+    mingw*)
+      sys_lib_search_path_spec=
+      lt_save_ifs=$IFS
+      IFS=';'
+      for lt_path in $LIB
+      do
+        IFS=$lt_save_ifs
+        # Let DOS variable expansion print the short 8.3 style file name.
+        lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+        sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+      done
+      IFS=$lt_save_ifs
+      # Convert to MSYS style.
+      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| 
\\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
+      ;;
+    cygwin*)
+      # Convert to unix form, then to dos form, then back to unix form
+      # but this time dos style (no spaces!) so that the unix form looks
+      # like /cygdrive/c/PROGRA~1:/cygdr...
+      sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+      sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+      sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e 
"s/$PATH_SEPARATOR/ /g"`
+      ;;
+    *)
+      sys_lib_search_path_spec=$LIB
+      if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
+        # It is most probably a Windows format PATH.
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      # FIXME: find the short name or the path components, as spaces are
+      # common. (e.g. "Program Files" -> "PROGRA~1")
+      ;;
+    esac
+
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \$file`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+    dynamic_linker='Win32 link.exe'
+    ;;
+
+  *)
+    # Assume MSVC wrapper
+    library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib'
+    dynamic_linker='Win32 ld.exe'
+    ;;
+  esac
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
+  soname_spec='$libname$release$major$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+m4_if([$1], [],[
+  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major 
$libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[[23]].*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major 
$libname$shared_ext'
+      soname_spec='$libname$release$shared_ext$major'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2.*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[[01]]* | freebsdelf3.[[01]]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
+  freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+haiku*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  dynamic_linker="$host_os runtime_loader"
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major 
$libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major 
$libname$shared_ext'
+    soname_spec='$libname$release$shared_ext$major'
+    if test 32 = "$HPUX_IA64_MODE"; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+      sys_lib_dlsearch_path_spec=/usr/lib/hpux32
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+      sys_lib_dlsearch_path_spec=/usr/lib/hpux64
+    fi
+    ;;
+  hppa*64*)
+    shrext_cmds='.sl'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major 
$libname$shared_ext'
+    soname_spec='$libname$release$shared_ext$major'
+    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major 
$libname$shared_ext'
+    soname_spec='$libname$release$shared_ext$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+  postinstall_cmds='chmod 555 $lib'
+  # or fails outright, so override atomically:
+  install_override_mode=555
+  ;;
+
+interix[[3-9]]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major 
$libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+       if test yes = "$lt_cv_prog_gnu_ld"; then
+               version_type=linux # correct to gnu/linux during the next big refactor
+       else
+               version_type=irix
+       fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='$libname$release$shared_ext$major'
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major 
$libname$release$shared_ext $libname$shared_ext'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
+  sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+linux*android*)
+  version_type=none # Android doesn't support versioned libraries.
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext'
+  soname_spec='$libname$release$shared_ext'
+  finish_cmds=
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  dynamic_linker='Android linker'
+  # Don't embed -rpath directories since the linker doesn't support them.
+  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+  ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major 
$libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+
+  # Some binutils ld are patched to set DT_RUNPATH
+  AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath],
+    [lt_cv_shlibpath_overrides_runpath=no
+    save_LDFLAGS=$LDFLAGS
+    save_libdir=$libdir
+    eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
+        LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
+    AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+      [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
+        [lt_cv_shlibpath_overrides_runpath=yes])])
+    LDFLAGS=$save_LDFLAGS
+    libdir=$save_libdir
+    ])
+  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Add ABI-specific directories to the system library path.
+  sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib"
+
+  # Ideally, we could use ldconfig to report *all* directores which are
+  # searched for libraries, however this is still not possible.  Aside from not
+  # being certain /sbin/ldconfig is available, command
+  # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
+  # even though it is searched at run-time.  Try to do the best guess by
+  # appending ld.so.conf contents (and includes) to the search path.
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if 
(!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[  ]*hwcap[        ]/d;s/[:,      ]/ 
/g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major 
$libname$shared_ext'
+    soname_spec='$libname$release$shared_ext$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major 
$libname$shared_ext'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+*nto* | *qnx*)
+  version_type=qnx
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major 
$libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='ldqnx.so'
+  ;;
+
+openbsd* | bitrig*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec=/usr/lib
+  need_lib_prefix=no
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+    need_version=no
+  else
+    need_version=yes
+  fi
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+os2*)
+  libname_spec='$name'
+  version_type=windows
+  shrext_cmds=.dll
+  need_version=no
+  need_lib_prefix=no
+  # OS/2 can only load a DLL with a base name of 8 characters or less.
+  soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
+    v=$($ECHO $release$versuffix | tr -d .-);
+    n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
+    $ECHO $n$v`$shared_ext'
+  library_names_spec='${libname}_dll.$libext'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=BEGINLIBPATH
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+  postinstall_cmds='base_file=`basename \$file`~
+    dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
+    dldir=$destdir/`dirname \$dlpath`~
+    test -d \$dldir || mkdir -p \$dldir~
+    $install_prog $dir/$dlname \$dldir/$dlname~
+    chmod a+x \$dldir/$dlname~
+    if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+      eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+    fi'
+  postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
+    dlpath=$dir/\$dldll~
+    $RM \$dlpath'
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='$libname$release$shared_ext$major'
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major 
$libname$shared_ext'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major 
$libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test yes = "$with_gnu_ld"; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major 
$libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec; then
+    version_type=linux # correct to gnu/linux during the next big refactor
+    library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
+    soname_spec='$libname$shared_ext.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=sco
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  if test yes = "$with_gnu_ld"; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+       ;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+tpf*)
+  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major 
$libname$shared_ext'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+uts4*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major 
$libname$shared_ext'
+  soname_spec='$libname$release$shared_ext$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test no = "$dynamic_linker" && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test yes = "$GCC"; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
+  sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
+fi
+
+if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
+  sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
+fi
+
+# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
+configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
+
+# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
+func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
+
+# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
+configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
+
+_LT_DECL([], [variables_saved_for_relink], [1],
+    [Variables whose values should be saved in libtool wrapper scripts and
+    restored at link time])
+_LT_DECL([], [need_lib_prefix], [0],
+    [Do we need the "lib" prefix for modules?])
+_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
+_LT_DECL([], [version_type], [0], [Library versioning type])
+_LT_DECL([], [runpath_var], [0],  [Shared library runtime path variable])
+_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
+_LT_DECL([], [shlibpath_overrides_runpath], [0],
+    [Is shlibpath searched before the hard-coded library search path?])
+_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
+_LT_DECL([], [library_names_spec], [1],
+    [[List of archive names.  First name is the real one, the rest are links.
+    The last name is the one that the linker finds with -lNAME]])
+_LT_DECL([], [soname_spec], [1],
+    [[The coded name of the library, if different from the real name]])
+_LT_DECL([], [install_override_mode], [1],
+    [Permission mode override for installation of shared libraries])
+_LT_DECL([], [postinstall_cmds], [2],
+    [Command to use after installation of a shared archive])
+_LT_DECL([], [postuninstall_cmds], [2],
+    [Command to use after uninstallation of a shared archive])
+_LT_DECL([], [finish_cmds], [2],
+    [Commands used to finish a libtool library installation in a directory])
+_LT_DECL([], [finish_eval], [1],
+    [[As "finish_cmds", except a single script fragment to be evaled but
+    not shown]])
+_LT_DECL([], [hardcode_into_libs], [0],
+    [Whether we should hardcode library paths into libraries])
+_LT_DECL([], [sys_lib_search_path_spec], [2],
+    [Compile-time system search path for libraries])
+_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2],
+    [Detected run-time system search path for libraries])
+_LT_DECL([], [configure_time_lt_sys_library_path], [2],
+    [Explicit LT_SYS_LIBRARY_PATH set during ./configure time])
+])# _LT_SYS_DYNAMIC_LINKER
+
+
+# _LT_PATH_TOOL_PREFIX(TOOL)
+# --------------------------
+# find a file program that can recognize shared library
+AC_DEFUN([_LT_PATH_TOOL_PREFIX],
+[m4_require([_LT_DECL_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] |  ?:[\\/]*])
+  lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD=$MAGIC_CMD
+  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word.  This closes a longstanding sh security hole.
+  ac_dummy="m4_if([$2], , $PATH, [$2])"
+  for ac_dir in $ac_dummy; do
+    IFS=$lt_save_ifs
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$1"; then
+      lt_cv_path_MAGIC_CMD=$ac_dir/"$1"
+      if test -n "$file_magic_test_file"; then
+       case $deplibs_check_method in
+       "file_magic "*)
+         file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+         MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+         if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+           $EGREP "$file_magic_regex" > /dev/null; then
+           :
+         else
+           cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool gnu org
+
+_LT_EOF
+         fi ;;
+       esac
+      fi
+      break
+    fi
+  done
+  IFS=$lt_save_ifs
+  MAGIC_CMD=$lt_save_MAGIC_CMD
+  ;;
+esac])
+MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+if test -n "$MAGIC_CMD"; then
+  AC_MSG_RESULT($MAGIC_CMD)
+else
+  AC_MSG_RESULT(no)
+fi
+_LT_DECL([], [MAGIC_CMD], [0],
+        [Used to examine libraries when file_magic_cmd begins with "file"])dnl
+])# _LT_PATH_TOOL_PREFIX
+
+# Old name:
+AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
+
+
+# _LT_PATH_MAGIC
+# --------------
+# find a file program that can recognize a shared library
+m4_defun([_LT_PATH_MAGIC],
+[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+  else
+    MAGIC_CMD=:
+  fi
+fi
+])# _LT_PATH_MAGIC
+
+
+# LT_PATH_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([LT_PATH_LD],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_PROG_ECHO_BACKSLASH])dnl
+
+AC_ARG_WITH([gnu-ld],
+    [AS_HELP_STRING([--with-gnu-ld],
+       [assume the C compiler uses GNU ld @<:@default=no@:>@])],
+    [test no = "$withval" || with_gnu_ld=yes],
+    [with_gnu_ld=no])dnl
+
+ac_prog=ld
+if test yes = "$GCC"; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  AC_MSG_CHECKING([for ld used by $CC])
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return, which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [[\\/]]* | ?:[[\\/]]*)
+      re_direlt='/[[^/]][[^/]]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD=$ac_prog
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test yes = "$with_gnu_ld"; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS=$lt_save_ifs
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD=$ac_dir/$ac_prog
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+       test no != "$with_gnu_ld" && break
+       ;;
+      *)
+       test yes != "$with_gnu_ld" && break
+       ;;
+      esac
+    fi
+  done
+  IFS=$lt_save_ifs
+else
+  lt_cv_path_LD=$LD # Let the user override the test with a path.
+fi])
+LD=$lt_cv_path_LD
+if test -n "$LD"; then
+  AC_MSG_RESULT($LD)
+else
+  AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+_LT_PATH_LD_GNU
+AC_SUBST([LD])
+
+_LT_TAGDECL([], [LD], [1], [The linker used to build libraries])
+])# LT_PATH_LD
+
+# Old names:
+AU_ALIAS([AM_PROG_LD], [LT_PATH_LD])
+AU_ALIAS([AC_PROG_LD], [LT_PATH_LD])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_LD], [])
+dnl AC_DEFUN([AC_PROG_LD], [])
+
+
+# _LT_PATH_LD_GNU
+#- --------------
+m4_defun([_LT_PATH_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# _LT_PATH_LD_GNU
+
+
+# _LT_CMD_RELOAD
+# --------------
+# find reload flag for linker
+#   -- PORTME Some linkers may need a different reload flag.
+m4_defun([_LT_CMD_RELOAD],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+  lt_cv_ld_reload_flag,
+  [lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    if test yes != "$GCC"; then
+      reload_cmds=false
+    fi
+    ;;
+  darwin*)
+    if test yes = "$GCC"; then
+      reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+_LT_TAGDECL([], [reload_flag], [1], [How to create reloadable object files])dnl
+_LT_TAGDECL([], [reload_cmds], [2])dnl
+])# _LT_CMD_RELOAD
+
+
+# _LT_PATH_DD
+# -----------
+# find a working dd
+m4_defun([_LT_PATH_DD],
+[AC_CACHE_CHECK([for a working dd], [ac_cv_path_lt_DD],
+[printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+: ${lt_DD:=$DD}
+AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd],
+[if "$ac_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then
+  cmp -s conftest.i conftest.out \
+  && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=:
+fi])
+rm -f conftest.i conftest2.i conftest.out])
+])# _LT_PATH_DD
+
+
+# _LT_CMD_TRUNCATE
+# ----------------
+# find command to truncate a binary pipe
+m4_defun([_LT_CMD_TRUNCATE],
+[m4_require([_LT_PATH_DD])
+AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin],
+[printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+lt_cv_truncate_bin=
+if "$ac_cv_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then
+  cmp -s conftest.i conftest.out \
+  && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1"
+fi
+rm -f conftest.i conftest2.i conftest.out
+test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"])
+_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1],
+  [Command to truncate a binary pipe])
+])# _LT_CMD_TRUNCATE
+
+
+# _LT_CHECK_MAGIC_METHOD
+# ----------------------
+# how to check for library dependencies
+#  -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_MAGIC_METHOD],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+AC_CACHE_CHECK([how to recognize dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# 'unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# that responds to the $file_magic_cmd with a given extended regex.
+# If you have 'file' or equivalent on your system and you're not sure
+# whether 'pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[[4-9]]*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[[45]]*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+  # unless we find 'file', for example because we are cross-compiling.
+  if ( file / ) >/dev/null 2>&1; then
+    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+    lt_cv_file_magic_cmd='func_win32_libid'
+  else
+    # Keep this pattern in sync with the one in func_win32_libid.
+    lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: 
i386)?|pe-arm-wince|pe-x86-64)'
+    lt_cv_file_magic_cmd='$OBJDUMP -f'
+  fi
+  ;;
+
+cegcc*)
+  # use the weaker test based on 'objdump'. See mingw*.
+  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | dragonfly*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged 
shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+haiku*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  case $host_cpu in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - 
IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared 
object( file)?[, -]* PA-RISC [0-9]\.[0-9]']
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+interix[[3-9]]*)
+  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+  lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+*nto* | *qnx*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+openbsd* | bitrig*)
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+rdos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.3*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) 
M[[0-9]][[0-9]]* Version [[0-9]]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  pc)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+tpf*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+os2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+])
+
+file_magic_glob=
+want_nocaseglob=no
+if test "$build" = "$host"; then
+  case $host_os in
+  mingw* | pw32*)
+    if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
+      want_nocaseglob=yes
+    else
+      file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e 
"s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"`
+    fi
+    ;;
+  esac
+fi
+
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+_LT_DECL([], [deplibs_check_method], [1],
+    [Method to check whether dependent libraries are shared objects])
+_LT_DECL([], [file_magic_cmd], [1],
+    [Command to use when deplibs_check_method = "file_magic"])
+_LT_DECL([], [file_magic_glob], [1],
+    [How to find potential files when deplibs_check_method = "file_magic"])
+_LT_DECL([], [want_nocaseglob], [1],
+    [Find potential files using nocaseglob when deplibs_check_method = "file_magic"])
+])# _LT_CHECK_MAGIC_METHOD
+
+
+# LT_PATH_NM
+# ----------
+# find the pathname to a BSD- or MS-compatible name lister
+AC_DEFUN([LT_PATH_NM],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
+[if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM=$NM
+else
+  lt_nm_to_check=${ac_tool_prefix}nm
+  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+    lt_nm_to_check="$lt_nm_to_check nm"
+  fi
+  for lt_tmp_nm in $lt_nm_to_check; do
+    lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+      IFS=$lt_save_ifs
+      test -z "$ac_dir" && ac_dir=.
+      tmp_nm=$ac_dir/$lt_tmp_nm
+      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then
+       # Check to see if the nm accepts a BSD-compat flag.
+       # Adding the 'sed 1q' prevents false positives on HP-UX, which says:
+       #   nm: unknown option "B" ignored
+       # Tru64's nm complains that /dev/null is an invalid object file
+       # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty
+       case $build_os in
+       mingw*) lt_bad_file=conftest.nm/nofile ;;
+       *) lt_bad_file=/dev/null ;;
+       esac
+       case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in
+       *$lt_bad_file* | *'Invalid file or object type'*)
+         lt_cv_path_NM="$tmp_nm -B"
+         break 2
+         ;;
+       *)
+         case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+         */dev/null*)
+           lt_cv_path_NM="$tmp_nm -p"
+           break 2
+           ;;
+         *)
+           lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+           continue # so that we can try to find one that supports BSD flags
+           ;;
+         esac
+         ;;
+       esac
+      fi
+    done
+    IFS=$lt_save_ifs
+  done
+  : ${lt_cv_path_NM=no}
+fi])
+if test no != "$lt_cv_path_NM"; then
+  NM=$lt_cv_path_NM
+else
+  # Didn't find any BSD compatible name lister, look for dumpbin.
+  if test -n "$DUMPBIN"; then :
+    # Let the user override the test.
+  else
+    AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :)
+    case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in
+    *COFF*)
+      DUMPBIN="$DUMPBIN -symbols -headers"
+      ;;
+    *)
+      DUMPBIN=:
+      ;;
+    esac
+  fi
+  AC_SUBST([DUMPBIN])
+  if test : != "$DUMPBIN"; then
+    NM=$DUMPBIN
+  fi
+fi
+test -z "$NM" && NM=nm
+AC_SUBST([NM])
+_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
+
+AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
+  [lt_cv_nm_interface="BSD nm"
+  echo "int some_variable = 0;" > conftest.$ac_ext
+  (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
+  (eval "$ac_compile" 2>conftest.err)
+  cat conftest.err >&AS_MESSAGE_LOG_FD
+  (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
+  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+  cat conftest.err >&AS_MESSAGE_LOG_FD
+  (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD)
+  cat conftest.out >&AS_MESSAGE_LOG_FD
+  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+    lt_cv_nm_interface="MS dumpbin"
+  fi
+  rm -f conftest*])
+])# LT_PATH_NM
+
+# Old names:
+AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
+AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_NM], [])
+dnl AC_DEFUN([AC_PROG_NM], [])
+
+# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
+# --------------------------------
+# how to determine the name of the shared library
+# associated with a specific link library.
+#  -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+m4_require([_LT_DECL_DLLTOOL])
+AC_CACHE_CHECK([how to associate runtime and link libraries],
+lt_cv_sharedlib_from_linklib_cmd,
+[lt_cv_sharedlib_from_linklib_cmd='unknown'
+
+case $host_os in
+cygwin* | mingw* | pw32* | cegcc*)
+  # two different shell functions defined in ltmain.sh;
+  # decide which one to use based on capabilities of $DLLTOOL
+  case `$DLLTOOL --help 2>&1` in
+  *--identify-strict*)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
+    ;;
+  *)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
+    ;;
+  esac
+  ;;
+*)
+  # fallback: assume linklib IS sharedlib
+  lt_cv_sharedlib_from_linklib_cmd=$ECHO
+  ;;
+esac
+])
+sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
+test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
+
+_LT_DECL([], [sharedlib_from_linklib_cmd], [1],
+    [Command to associate shared and link libraries])
+])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
+
+
+# _LT_PATH_MANIFEST_TOOL
+# ----------------------
+# locate the manifest tool
+m4_defun([_LT_PATH_MANIFEST_TOOL],
+[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :)
+test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
+AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool],
+  [lt_cv_path_mainfest_tool=no
+  echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD
+  $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
+  cat conftest.err >&AS_MESSAGE_LOG_FD
+  if $GREP 'Manifest Tool' conftest.out > /dev/null; then
+    lt_cv_path_mainfest_tool=yes
+  fi
+  rm -f conftest*])
+if test yes != "$lt_cv_path_mainfest_tool"; then
+  MANIFEST_TOOL=:
+fi
+_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl
+])# _LT_PATH_MANIFEST_TOOL
+
+
+# _LT_DLL_DEF_P([FILE])
+# ---------------------
+# True iff FILE is a Windows DLL '.def' file.
+# Keep in sync with func_dll_def_p in the libtool script
+AC_DEFUN([_LT_DLL_DEF_P],
+[dnl
+  test DEF = "`$SED -n dnl
+    -e '\''s/^[[        ]]*//'\'' dnl Strip leading whitespace
+    -e '\''/^\(;.*\)*$/d'\'' dnl      Delete empty lines and comments
+    -e '\''s/^\(EXPORTS\|LIBRARY\)\([[  ]].*\)*$/DEF/p'\'' dnl
+    -e q dnl                          Only consider the first "real" line
+    $1`" dnl
+])# _LT_DLL_DEF_P
+
+
+# LT_LIB_M
+# --------
+# check for math library
+AC_DEFUN([LT_LIB_M],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)
+  # These system don't have libm, or don't need it
+  ;;
+*-ncr-sysv4.3*)
+  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw)
+  AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+  ;;
+*)
+  AC_CHECK_LIB(m, cos, LIBM=-lm)
+  ;;
+esac
+AC_SUBST([LIBM])
+])# LT_LIB_M
+
+# Old name:
+AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_CHECK_LIBM], [])
+
+
+# _LT_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------
+m4_defun([_LT_COMPILER_NO_RTTI],
+[m4_require([_LT_TAG_COMPILER])dnl
+
+_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test yes = "$GCC"; then
+  case $cc_basename in
+  nvcc*)
+    _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;;
+  *)
+    _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;;
+  esac
+
+  _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+    lt_cv_prog_compiler_rtti_exceptions,
+    [-fno-rtti -fno-exceptions], [],
+    [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) 
-fno-rtti -fno-exceptions"])
+fi
+_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
+       [Compiler flag to turn off builtin functions])
+])# _LT_COMPILER_NO_RTTI
+
+
+# _LT_CMD_GLOBAL_SYMBOLS
+# ----------------------
+m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[[BCDT]]'
+  ;;
+cygwin* | mingw* | pw32* | cegcc*)
+  symcode='[[ABCDGISTW]]'
+  ;;
+hpux*)
+  if test ia64 = "$host_cpu"; then
+    symcode='[[ABCDEGRST]]'
+  fi
+  ;;
+irix* | nonstopux*)
+  symcode='[[BCDEGRST]]'
+  ;;
+osf*)
+  symcode='[[BCDEGQRST]]'
+  ;;
+solaris*)
+  symcode='[[BDRT]]'
+  ;;
+sco3.2v5*)
+  symcode='[[DT]]'
+  ;;
+sysv4.2uw2*)
+  symcode='[[DT]]'
+  ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+  symcode='[[ABDT]]'
+  ;;
+sysv4)
+  symcode='[[DFNSTU]]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[[ABCDGIRSTW]]' ;;
+esac
+
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+  # Gets list of data symbols to import.
+  lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'"
+  # Adjust the below global symbol transforms to fixup imported variables.
+  lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
+  lt_c_name_hook=" -e 's/^I .* \(.*\)$/  {\"\1\", (void *) 0},/p'"
+  lt_c_name_lib_hook="\
+  -e 's/^I .* \(lib.*\)$/  {\"\1\", (void *) 0},/p'\
+  -e 's/^I .* \(.*\)$/  {\"lib\1\", (void *) 0},/p'"
+else
+  # Disable hooks by default.
+  lt_cv_sys_global_symbol_to_import=
+  lt_cdecl_hook=
+  lt_c_name_hook=
+  lt_c_name_lib_hook=
+fi
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n"\
+$lt_cdecl_hook\
+" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n"\
+$lt_c_name_hook\
+" -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/p'"
+
+# Transform an extracted symbol line into symbol name with lib prefix and
+# symbol address.
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\
+$lt_c_name_lib_hook\
+" -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(lib.*\)$/  {\"\1\", (void *) \&\1},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/  {\"lib\1\", (void *) \&\1},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+  symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+  # Write the raw and C identifiers.
+  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+    # Fake it for dumpbin and say T for any non-static function,
+    # D for any global variable and I for any imported variable.
+    # Also find C++ and __fastcall symbols from MSVC++,
+    # which start with @ or ?.
+    lt_cv_sys_global_symbol_pipe="$AWK ['"\
+"     {last_section=section; section=\$ 3};"\
+"     /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
+"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+"     /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
+"     /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
+"     /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
+"     \$ 0!~/External *\|/{next};"\
+"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+"     {if(hide[section]) next};"\
+"     {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\
+"     {split(\$ 0,a,/\||\r/); split(a[2],s)};"\
+"     s[1]~/^[ ?]/{print f,s[1],s[1]; next};"\
+"     s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
+"     ' prfx=^$ac_symprfx]"
+  else
+    lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[    ]]\($symcode$symcode*\)[[       ]][[    
]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+  fi
+  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'"
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+  if AC_TRY_EVAL(ac_compile); then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; 
then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+       mv -f "$nlist"T "$nlist"
+      else
+       rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+       if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+         cat <<_LT_EOF > conftest.$ac_ext
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
+#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
+/* DATA imports from DLLs on WIN32 can't be const, because runtime
+   relocations are performed -- see ld's documentation on pseudo-relocs.  */
+# define LT@&t _DLSYM_CONST
+#elif defined __osf__
+/* This system does not cope well with relocations in const data.  */
+# define LT@&t _DLSYM_CONST
+#else
+# define LT@&t _DLSYM_CONST const
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+         # Now generate the symbol file.
+         eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+         cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols.  */
+LT@&t _DLSYM_CONST struct {
+  const char *name;
+  void       *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[[]] =
+{
+  { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+         $SED "s/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> 
conftest.$ac_ext
+         cat <<\_LT_EOF >> conftest.$ac_ext
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+         # Now try linking the two files.
+         mv conftest.$ac_objext conftstm.$ac_objext
+         lt_globsym_save_LIBS=$LIBS
+         lt_globsym_save_CFLAGS=$CFLAGS
+         LIBS=conftstm.$ac_objext
+         CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+         if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then
+           pipe_works=yes
+         fi
+         LIBS=$lt_globsym_save_LIBS
+         CFLAGS=$lt_globsym_save_CFLAGS
+       else
+         echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+       fi
+      else
+       echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+    fi
+  else
+    echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+    cat conftest.$ac_ext >&5
+  fi
+  rm -rf conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test yes = "$pipe_works"; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  AC_MSG_RESULT(failed)
+else
+  AC_MSG_RESULT(ok)
+fi
+
+# Response file support.
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+  nm_file_list_spec='@'
+elif $NM --help 2>/dev/null | grep '[[ ]]FILE' >/dev/null; then
+  nm_file_list_spec='@'
+fi
+
+_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
+    [Take the output of nm and produce a listing of raw symbols and C names])
+_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
+    [Transform the output of nm in a proper C declaration])
+_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1],
+    [Transform the output of nm into a list of symbols to manually relocate])
+_LT_DECL([global_symbol_to_c_name_address],
+    [lt_cv_sys_global_symbol_to_c_name_address], [1],
+    [Transform the output of nm in a C name address pair])
+_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
+    [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
+    [Transform the output of nm in a C name address pair when lib prefix is needed])
+_LT_DECL([nm_interface], [lt_cv_nm_interface], [1],
+    [The name lister interface])
+_LT_DECL([], [nm_file_list_spec], [1],
+    [Specify filename containing input files for $NM])
+]) # _LT_CMD_GLOBAL_SYMBOLS
+
+
+# _LT_COMPILER_PIC([TAGNAME])
+# ---------------------------
+m4_defun([_LT_COMPILER_PIC],
+[m4_require([_LT_TAG_COMPILER])dnl
+_LT_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_TAGVAR(lt_prog_compiler_static, $1)=
+
+m4_if([$1], [CXX], [
+  # C++ specific cases for pic, static, wl, etc.
+  if test yes = "$GXX"; then
+    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+    case $host_os in
+    aix*)
+      # All AIX code is PIC.
+      if test ia64 = "$host_cpu"; then
+       # AIX 5 now supports IA64 processor
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the '-m68020' flag to GCC prevents building anything better,
+            # like '-m68040'.
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+    mingw* | cygwin* | os2* | pw32* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      m4_if([$1], [GCJ], [],
+       [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      case $host_os in
+      os2*)
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
+       ;;
+      esac
+      ;;
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+    *djgpp*)
+      # DJGPP does not support shared libraries at all
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+      ;;
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)=
+      ;;
+    interix[[3-9]]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+       ;;
+      *)
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+       ;;
+      esac
+      ;;
+    *qnx* | *nto*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+    *)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+  else
+    case $host_os in
+      aix[[4-9]]*)
+       # All AIX code is PIC.
+       if test ia64 = "$host_cpu"; then
+         # AIX 5 now supports IA64 processor
+         _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+       else
+         _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+       fi
+       ;;
+      chorus*)
+       case $cc_basename in
+       cxch68*)
+         # Green Hills C++ Compiler
+         # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort 
-r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+         ;;
+       esac
+       ;;
+      mingw* | cygwin* | os2* | pw32* | cegcc*)
+       # This hack is so that the source file can tell whether it is being
+       # built for inclusion in a dll (and should export symbols for example).
+       m4_if([$1], [GCJ], [],
+         [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+       ;;
+      dgux*)
+       case $cc_basename in
+         ec++*)
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           ;;
+         ghcx*)
+           # Green Hills C++ Compiler
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      freebsd* | dragonfly*)
+       # FreeBSD uses GNU C++
+       ;;
+      hpux9* | hpux10* | hpux11*)
+       case $cc_basename in
+         CC*)
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
+           if test ia64 != "$host_cpu"; then
+             _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+           fi
+           ;;
+         aCC*)
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
+           case $host_cpu in
+           hppa*64*|ia64*)
+             # +Z the default
+             ;;
+           *)
+             _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+             ;;
+           esac
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      interix*)
+       # This is c89, which is MS Visual C++ (no shared libs)
+       # Anyone wants to do a port?
+       ;;
+      irix5* | irix6* | nonstopux*)
+       case $cc_basename in
+         CC*)
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+           # CC pic flag -KPIC is the default.
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+       case $cc_basename in
+         KCC*)
+           # KAI C++ Compiler
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+           ;;
+         ecpc* )
+           # old Intel C++ for x86_64, which still supported -KPIC.
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+           ;;
+         icpc* )
+           # Intel C++, used to be incompatible with GCC.
+           # ICC 10 doesn't accept -KPIC any more.
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+           ;;
+         pgCC* | pgcpp*)
+           # Portland Group C++ compiler
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+           ;;
+         cxx*)
+           # Compaq C++
+           # Make sure the PIC flag is empty.  It appears that all Alpha
+           # Linux and Compaq Tru64 Unix objects are PIC.
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+           ;;
+         xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*)
+           # IBM XL 8.0, 9.0 on PPC and BlueGene
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+           ;;
+         *)
+           case `$CC -V 2>&1 | sed 5q` in
+           *Sun\ C*)
+             # Sun C++ 5.9
+             _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+             _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+             _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+             ;;
+           esac
+           ;;
+       esac
+       ;;
+      lynxos*)
+       ;;
+      m88k*)
+       ;;
+      mvs*)
+       case $cc_basename in
+         cxx*)
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      netbsd*)
+       ;;
+      *qnx* | *nto*)
+        # QNX uses GNU C++, but need to define -shared option too, otherwise
+        # it will coredump.
+        _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+        ;;
+      osf3* | osf4* | osf5*)
+       case $cc_basename in
+         KCC*)
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+           ;;
+         RCC*)
+           # Rational C++ 2.4.1
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           ;;
+         cxx*)
+           # Digital/Compaq C++
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           # Make sure the PIC flag is empty.  It appears that all Alpha
+           # Linux and Compaq Tru64 Unix objects are PIC.
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      psos*)
+       ;;
+      solaris*)
+       case $cc_basename in
+         CC* | sunCC*)
+           # Sun C++ 4.2, 5.x and Centerline C++
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+           ;;
+         gcx*)
+           # Green Hills C++ Compiler
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      sunos4*)
+       case $cc_basename in
+         CC*)
+           # Sun C++ 4.x
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+           ;;
+         lcc*)
+           # Lucid
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+       case $cc_basename in
+         CC*)
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+           ;;
+       esac
+       ;;
+      tandem*)
+       case $cc_basename in
+         NCC*)
+           # NonStop-UX NCC 3.20
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      vxworks*)
+       ;;
+      *)
+       _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+       ;;
+    esac
+  fi
+],
+[
+  if test yes = "$GCC"; then
+    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test ia64 = "$host_cpu"; then
+       # AIX 5 now supports IA64 processor
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the '-m68020' flag to GCC prevents building anything better,
+            # like '-m68040'.
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      m4_if([$1], [GCJ], [],
+       [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      case $host_os in
+      os2*)
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
+       ;;
+      esac
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)=
+      ;;
+
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+       # +Z the default
+       ;;
+      *)
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+       ;;
+      esac
+      ;;
+
+    interix[[3-9]]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      enable_shared=no
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+
+    *)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+
+    case $cc_basename in
+    nvcc*) # Cuda Compiler Driver 2.2
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker '
+      if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+        _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)"
+      fi
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      if test ia64 = "$host_cpu"; then
+       # AIX 5 now supports IA64 processor
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      else
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      case $cc_basename in
+      nagfor*)
+        # NAG Fortran compiler
+        _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
+        _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+        _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+        ;;
+      esac
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      m4_if([$1], [GCJ], [],
+       [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      case $host_os in
+      os2*)
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
+       ;;
+      esac
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+       ;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC (with -KPIC) is the default.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+      case $cc_basename in
+      # old Intel for x86_64, which still supported -KPIC.
+      ecc*)
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+        ;;
+      # icc used to be incompatible with GCC.
+      # ICC 10 doesn't accept -KPIC any more.
+      icc* | ifort*)
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+        ;;
+      # Lahey Fortran 8.1.
+      lf95*)
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
+       ;;
+      nagfor*)
+       # NAG Fortran compiler
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+       ;;
+      tcc*)
+       # Fabrice Bellard et al's Tiny C Compiler
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+       ;;
+      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+       # which looks to be a dead project)
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+        ;;
+      ccc*)
+        _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+        # All Alpha code is PIC.
+        _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+        ;;
+      xl* | bgxl* | bgf* | mpixl*)
+       # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+       ;;
+      *)
+       case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*)
+         # Sun Fortran 8.3 passes all unrecognized flags to the linker
+         _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+         _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+         _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
+         ;;
+       *Sun\ F* | *Sun*Fortran*)
+         _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+         _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+         _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+         ;;
+       *Sun\ C*)
+         # Sun C 5.9
+         _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+         _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+         _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+         ;;
+        *Intel*\ [[CF]]*Compiler*)
+         _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+         _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+         _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+         ;;
+       *Portland\ Group*)
+         _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+         _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+         _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+         ;;
+       esac
+       ;;
+      esac
+      ;;
+
+    newsos6)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # All OSF/1 code is PIC.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    rdos*)
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    solaris*)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
+      *)
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    unicos*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      ;;
+
+    uts4*)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    *)
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      ;;
+    esac
+  fi
+])
+case $host_os in
+  # For platforms that do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+    ;;
+  *)
+    _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t m4_if([$1],[],[ 
-DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
+    ;;
+esac
+
+AC_CACHE_CHECK([for $compiler option to produce PIC],
+  [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)],
+  [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+  _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
+    [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
+    [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
+    [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
+     "" | " "*) ;;
+     *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+     esac],
+    [_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+     _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
+       [Additional compiler flags for building library objects])
+
+_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
+       [How to pass a linker flag through the compiler])
+#
+# Check to make sure the static flag actually works.
+#
+wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
+_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
+  _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
+  $lt_tmp_static_flag,
+  [],
+  [_LT_TAGVAR(lt_prog_compiler_static, $1)=])
+_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
+       [Compiler flag to prevent dynamic linking])
+])# _LT_COMPILER_PIC
+
+
+# _LT_LINKER_SHLIBS([TAGNAME])
+# ----------------------------
+# See if the linker supports building shared libraries.
+m4_defun([_LT_LINKER_SHLIBS],
+[AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+m4_require([_LT_PATH_MANIFEST_TOOL])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+m4_if([$1], [CXX], [
+  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* 
//'\'' | sort | uniq > $export_symbols'
+  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+  case $host_os in
+  aix[[4-9]]*)
+    # If we're using GNU nm, then we don't want the "-C" option.
+    # -C means demangle to GNU nm, but means don't demangle to AIX nm.
+    # Without the "-l" option, or with the "-B" option, AIX nm treats
+    # weak defined symbols like other global defined symbols, whereas
+    # GNU nm marks them as "W".
+    # While the 'weak' keyword is ignored in the Export File, we need
+    # it in the Import File for the 'aix-soname' feature, so we have
+    # to replace the "-B" option with "-P" for AIX nm.
+    if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || 
(\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print 
\$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
+    else
+      _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl 
$libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || 
(\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 
== "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
+    fi
+    ;;
+  pw32*)
+    _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds
+    ;;
+  cygwin* | mingw* | cegcc*)
+    case $cc_basename in
+    cl*)
+      _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+      ;;
+    *)
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e 
'\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ 
]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+      _LT_TAGVAR(exclude_expsyms, 
$1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
+      ;;
+    esac
+    ;;
+  *)
+    _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* 
//'\'' | sort | uniq > $export_symbols'
+    ;;
+  esac
+], [
+  runpath_var=
+  _LT_TAGVAR(allow_undefined_flag, $1)=
+  _LT_TAGVAR(always_export_symbols, $1)=no
+  _LT_TAGVAR(archive_cmds, $1)=
+  _LT_TAGVAR(archive_expsym_cmds, $1)=
+  _LT_TAGVAR(compiler_needs_object, $1)=no
+  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+  _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* 
//'\'' | sort | uniq > $export_symbols'
+  _LT_TAGVAR(hardcode_automatic, $1)=no
+  _LT_TAGVAR(hardcode_direct, $1)=no
+  _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+  _LT_TAGVAR(hardcode_libdir_separator, $1)=
+  _LT_TAGVAR(hardcode_minus_L, $1)=no
+  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+  _LT_TAGVAR(inherit_rpath, $1)=no
+  _LT_TAGVAR(link_all_deplibs, $1)=unknown
+  _LT_TAGVAR(module_cmds, $1)=
+  _LT_TAGVAR(module_expsym_cmds, $1)=
+  _LT_TAGVAR(old_archive_from_new_cmds, $1)=
+  _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+  _LT_TAGVAR(thread_safe_flag_spec, $1)=
+  _LT_TAGVAR(whole_archive_flag_spec, $1)=
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  _LT_TAGVAR(include_expsyms, $1)=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ' (' and ')$', so one must not match beginning or
+  # end of line.  Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc',
+  # as well as any symbol that contains 'd'.
+  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  # Exclude shared library initialization/finalization symbols.
+dnl Note also adjust exclude_expsyms for C++ above.
+  extract_expsyms_cmds=
+
+  case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test yes != "$GCC"; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd* | bitrig*)
+    with_gnu_ld=no
+    ;;
+  esac
+
+  _LT_TAGVAR(ld_shlibs, $1)=yes
+
+  # On some targets, GNU ld is compatible enough with the native linker
+  # that we're better off using the native interface for both.
+  lt_use_gnu_ld_interface=no
+  if test yes = "$with_gnu_ld"; then
+    case $host_os in
+      aix*)
+       # The AIX port of GNU ld has always aspired to compatibility
+       # with the native linker.  However, as the warning in the GNU ld
+       # block says, versions before 2.19.5* couldn't really create working
+       # shared libraries, regardless of the interface used.
+       case `$LD -v 2>&1` in
+         *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+         *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;;
+         *\ \(GNU\ Binutils\)\ [[3-9]]*) ;;
+         *)
+           lt_use_gnu_ld_interface=yes
+           ;;
+       esac
+       ;;
+      *)
+       lt_use_gnu_ld_interface=yes
+       ;;
+    esac
+  fi
+
+  if test yes = "$lt_use_gnu_ld_interface"; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='$wl'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+      _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+    else
+      _LT_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in
+      *GNU\ gold*) supports_anon_versioning=yes ;;
+      *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix[[3-9]]*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test ia64 != "$host_cpu"; then
+       _LT_TAGVAR(ld_shlibs, $1)=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.19, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
+
+_LT_EOF
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname 
$wl$soname -o $lib'
+            _LT_TAGVAR(archive_expsym_cmds, $1)=''
+        ;;
+      m68k)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" 
$output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO 
"#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> 
$output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary 
-32)'
+            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes
+        ;;
+      esac
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+       _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+       # Joseph Beckenbach <jrb3 best com> says some releases of gcc
+       # support --undefined.  This deserves some investigation.  FIXME
+       _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o 
$lib'
+      else
+       _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+      # as there is no search path for DLLs.
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols'
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_TAGVAR(always_export_symbols, $1)=no
+      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e 
'\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ 
]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+      _LT_TAGVAR(exclude_expsyms, 
$1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
+
+      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o 
$output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+       # If the export-symbols file already is a .def file, use it as
+       # is; otherwise, prepend EXPORTS...
+       _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+          cp $export_symbols $output_objdir/$soname.def;
+        else
+          echo EXPORTS > $output_objdir/$soname.def;
+          cat $export_symbols >> $output_objdir/$soname.def;
+        fi~
+        $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname 
$wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+       _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    haiku*)
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o 
$lib'
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    os2*)
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      shrext_cmds=.dll
+      _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > 
$output_objdir/$libname.def~
+       $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+       $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+       $ECHO EXPORTS >> $output_objdir/$libname.def~
+       emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+       $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags 
$output_objdir/$libname.def~
+       emximp -o $lib $output_objdir/$libname.def'
+      _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > 
$output_objdir/$libname.def~
+       $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+       $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+       $ECHO EXPORTS >> $output_objdir/$libname.def~
+       prefix_cmds="$SED"~
+       if test EXPORTS = "`$SED 1q $export_symbols`"; then
+         prefix_cmds="$prefix_cmds -e 1d";
+       fi~
+       prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+       cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+       $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags 
$output_objdir/$libname.def~
+       emximp -o $lib $output_objdir/$libname.def'
+      _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a 
$output_objdir/$libname.def'
+      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      ;;
+
+    interix[[3-9]]*)
+      _LT_TAGVAR(hardcode_direct, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname 
$wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC 
-shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname 
$wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 
262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+      tmp_diet=no
+      if test linux-dietlibc = "$host_os"; then
+       case $cc_basename in
+         diet\ *) tmp_diet=yes;;       # linux-dietlibc with static linking (!diet-dyn)
+       esac
+      fi
+      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+        && test no = "$tmp_diet"
+      then
+       tmp_addflag=' $pic_flag'
+       tmp_sharedflag='-shared'
+       case $cc_basename,$host_cpu in
+        pgcc*)                         # Portland Group C compiler
+         _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test  
-n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` 
$wl--no-whole-archive'
+         tmp_addflag=' $pic_flag'
+         ;;
+       pgf77* | pgf90* | pgf95* | pgfortran*)
+                                       # Portland Group f77 and f90 compilers
+         _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test  
-n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` 
$wl--no-whole-archive'
+         tmp_addflag=' $pic_flag -Mnomain' ;;
+       ecc*,ia64* | icc*,ia64*)        # Intel C compiler on ia64
+         tmp_addflag=' -i_dynamic' ;;
+       efc*,ia64* | ifort*,ia64*)      # Intel Fortran compiler on ia64
+         tmp_addflag=' -i_dynamic -nofor_main' ;;
+       ifc* | ifort*)                  # Intel Fortran compiler
+         tmp_addflag=' -nofor_main' ;;
+       lf95*)                          # Lahey Fortran 8.1
+         _LT_TAGVAR(whole_archive_flag_spec, $1)=
+         tmp_sharedflag='--shared' ;;
+        nagfor*)                        # NAGFOR 5.3
+          tmp_sharedflag='-Wl,-shared' ;;
+       xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+         tmp_sharedflag='-qmkshrobj'
+         tmp_addflag= ;;
+       nvcc*)  # Cuda Compiler Driver 2.2
+         _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test  
-n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` 
$wl--no-whole-archive'
+         _LT_TAGVAR(compiler_needs_object, $1)=yes
+         ;;
+       esac
+       case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)                       # Sun C 5.9
+         _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in 
$convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all 
\"$new_convenience\"` $wl--no-whole-archive'
+         _LT_TAGVAR(compiler_needs_object, $1)=yes
+         tmp_sharedflag='-G' ;;
+       *Sun\ F*)                       # Sun Fortran 8.3
+         tmp_sharedflag='-G' ;;
+       esac
+       _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags 
$wl-soname $wl$soname -o $lib'
+
+        if test yes = "$supports_anon_versioning"; then
+          _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+            cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+            echo "local: *; };" >> $output_objdir/$libname.ver~
+            $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname 
$wl-version-script $wl$output_objdir/$libname.ver -o $lib'
+        fi
+
+       case $cc_basename in
+       tcc*)
+         _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic'
+         ;;
+       xlf* | bgf* | bgxlf* | mpixlf*)
+         # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+         _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+         _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
+         if test yes = "$supports_anon_versioning"; then
+           _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+              cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+              echo "local: *; };" >> $output_objdir/$libname.ver~
+              $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script 
$output_objdir/$libname.ver -o $lib'
+         fi
+         ;;
+       esac
+      else
+        _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+       _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+       wlarc=
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname 
$wl$soname -o $lib'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags 
$wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+       _LT_TAGVAR(ld_shlibs, $1)=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname 
$wl$soname -o $lib'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags 
$wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
+       _LT_TAGVAR(ld_shlibs, $1)=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+       ;;
+       *)
+         # For security reasons, it is highly recommended that you always
+         # use absolute paths for naming shared libraries, and exclude the
+         # DT_RUNPATH tag from executables and libraries.  But doing so
+         # requires that you compile everything twice, which is a pain.
+         if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+           _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname 
-o $lib'
+           _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname 
$wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+         else
+           _LT_TAGVAR(ld_shlibs, $1)=no
+         fi
+       ;;
+      esac
+      ;;
+
+    sunos4*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs 
$linker_flags'
+      wlarc=
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname 
$wl$soname -o $lib'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags 
$wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+    esac
+
+    if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then
+      runpath_var=
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+      _LT_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_TAGVAR(always_export_symbols, $1)=yes
+      _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags 
-bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then
+       # Neither direct hardcoding nor static linking is supported with a
+       # broken collect2.
+       _LT_TAGVAR(hardcode_direct, $1)=unsupported
+      fi
+      ;;
+
+    aix[[4-9]]*)
+      if test ia64 = "$host_cpu"; then
+       # On IA64, the linker does run time linking by default, so we don't
+       # have to do anything special.
+       aix_use_runtimelinking=no
+       exp_sym_flag='-Bexport'
+       no_entry_flag=
+      else
+       # If we're using GNU nm, then we don't want the "-C" option.
+       # -C means demangle to GNU nm, but means don't demangle to AIX nm.
+       # Without the "-l" option, or with the "-B" option, AIX nm treats
+       # weak defined symbols like other global defined symbols, whereas
+       # GNU nm marks them as "W".
+       # While the 'weak' keyword is ignored in the Export File, we need
+       # it in the Import File for the 'aix-soname' feature, so we have
+       # to replace the "-B" option with "-P" for AIX nm.
+       if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+         _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") 
|| (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { 
print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
+       else
+         _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` 
-PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == 
"W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") 
|| (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
+       fi
+       aix_use_runtimelinking=no
+
+       # Test if we are trying to use run time linking or normal
+       # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+       # have runtime linking enabled, and use it for executables.
+       # For shared libraries, we enable/disable runtime linking
+       # depending on the kind of the shared library created -
+       # when "with_aix_soname,aix_use_runtimelinking" is:
+       # "aix,no"   lib.a(lib.so.V) shared, rtl:no,  for executables
+       # "aix,yes"  lib.so          shared, rtl:yes, for executables
+       #            lib.a           static archive
+       # "both,no"  lib.so.V(shr.o) shared, rtl:yes
+       #            lib.a(lib.so.V) shared, rtl:no,  for executables
+       # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+       #            lib.a(lib.so.V) shared, rtl:no
+       # "svr4,*"   lib.so.V(shr.o) shared, rtl:yes, for executables
+       #            lib.a           static archive
+       case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+         for ld_flag in $LDFLAGS; do
+         if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then
+           aix_use_runtimelinking=yes
+           break
+         fi
+         done
+         if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+           # With aix-soname=svr4, we create the lib.so.V shared archives only,
+           # so we don't have lib.a shared libs to link our executables.
+           # We have to force runtime linking in this case.
+           aix_use_runtimelinking=yes
+           LDFLAGS="$LDFLAGS -Wl,-brtl"
+         fi
+         ;;
+       esac
+
+       exp_sym_flag='-bexport'
+       no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      _LT_TAGVAR(archive_cmds, $1)=''
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      _LT_TAGVAR(file_list_spec, $1)='$wl-f,'
+      case $with_aix_soname,$aix_use_runtimelinking in
+      aix,*) ;; # traditional, no import file
+      svr4,* | *,yes) # use import file
+       # The Import File defines what to hardcode.
+       _LT_TAGVAR(hardcode_direct, $1)=no
+       _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+       ;;
+      esac
+
+      if test yes = "$GCC"; then
+       case $host_os in aix4.[[012]]|aix4.[[012]].*)
+       # We only want to do this on AIX 4.2 and lower, the check
+       # below for broken collect2 doesn't work under 4.3+
+         collect2name=`$CC -print-prog-name=collect2`
+         if test -f "$collect2name" &&
+          strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+         then
+         # We have reworked collect2
+         :
+         else
+         # We have old collect2
+         _LT_TAGVAR(hardcode_direct, $1)=unsupported
+         # It fails to find uninstalled libraries when the uninstalled
+         # path is not listed in the libpath.  Setting hardcode_minus_L
+         # to unsupported forces relinking
+         _LT_TAGVAR(hardcode_minus_L, $1)=yes
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+         _LT_TAGVAR(hardcode_libdir_separator, $1)=
+         fi
+         ;;
+       esac
+       shared_flag='-shared'
+       if test yes = "$aix_use_runtimelinking"; then
+         shared_flag="$shared_flag "'$wl-G'
+       fi
+       # Need to ensure runtime linking is disabled for the traditional
+       # shared library, or the linker may eventually find shared libraries
+       # /with/ Import File - we do not want to mix them.
+       shared_flag_aix='-shared'
+       shared_flag_svr4='-shared $wl-G'
+      else
+       # not using gcc
+       if test ia64 = "$host_cpu"; then
+       # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+       # chokes on -Wl,-G. The following line is correct:
+         shared_flag='-G'
+       else
+         if test yes = "$aix_use_runtimelinking"; then
+           shared_flag='$wl-G'
+         else
+           shared_flag='$wl-bM:SRE'
+         fi
+         shared_flag_aix='$wl-bM:SRE'
+         shared_flag_svr4='$wl-G'
+       fi
+      fi
+
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall'
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      _LT_TAGVAR(always_export_symbols, $1)=yes
+      if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
+       # Warning - without using the other runtime loading flags (-brtl),
+       # -berok will link without error, but may produce a broken library.
+       _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        _LT_SYS_MODULE_PATH_AIX([$1])
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs 
$wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all 
"$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
+      else
+       if test ia64 = "$host_cpu"; then
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib'
+         _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+         _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs 
$deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
+       else
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        _LT_SYS_MODULE_PATH_AIX([$1])
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+         # Warning - without using the other run time loading flags,
+         # -berok will link without error, but may produce a broken library.
+         _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok'
+         _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok'
+         if test yes = "$with_gnu_ld"; then
+           # We only use this code for GNU lds that support --whole-archive.
+           _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
+         else
+           # Exported symbols can be pulled into shared objects from archives
+           _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+         fi
+         _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+         _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR 
$output_objdir/$realname.d'
+         # -brtl affects multiple linker settings, -berok does not and is overridden later
+         compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, 
]]\\)%-berok\\1%g"`'
+         if test svr4 != "$with_aix_soname"; then
+           # This is similar to how AIX traditionally builds its shared libraries.
+           _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC 
'$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry 
'$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS 
$output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+         fi
+         if test aix != "$with_aix_soname"; then
+           _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC 
'$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs 
$wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e 
$output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! 
$soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all 
"# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > 
$output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname 
$output_objdir/$realname.d/$shared_archive_member_spec.o 
$output_objdir/$realname.d/$shared_archive_member_spec.imp'
+         else
+           # used by -dlpreopen to get the symbols
+           _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV  
$output_objdir/$realname.d/$soname $output_objdir'
+         fi
+         _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r 
$output_objdir/$realname.d'
+       fi
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname 
$wl$soname -o $lib'
+            _LT_TAGVAR(archive_expsym_cmds, $1)=''
+        ;;
+      m68k)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" 
$output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO 
"#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> 
$output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary 
-32)'
+            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes
+        ;;
+      esac
+      ;;
+
+    bsdi[[45]]*)
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      case $cc_basename in
+      cl*)
+       # Native MSVC
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+       _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+       _LT_TAGVAR(always_export_symbols, $1)=yes
+       _LT_TAGVAR(file_list_spec, $1)='@'
+       # Tell ltmain to make .lib files, not .a files.
+       libext=lib
+       # Tell ltmain to make .dll files, not .so files.
+       shrext_cmds=.dll
+       # FIXME: Setting linknames here is a bad hack.
+       _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs 
-Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+       _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+            cp "$export_symbols" "$output_objdir/$soname.def";
+            echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+          else
+            $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
+          fi~
+          $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs 
"@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+          linknames='
+       # The linker will not automatically build a static lib if we build a DLL.
+       # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+       _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+       _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+       _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e 
'\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort 
| uniq > $export_symbols'
+       # Don't use ranlib
+       _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
+       _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
+          lt_tool_outputfile="@TOOL_OUTPUT@"~
+          case $lt_outputfile in
+            *.exe|*.EXE) ;;
+            *)
+              lt_outputfile=$lt_outputfile.exe
+              lt_tool_outputfile=$lt_tool_outputfile.exe
+              ;;
+          esac~
+          if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
+            $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || 
exit 1;
+            $RM "$lt_outputfile.manifest";
+          fi'
+       ;;
+      *)
+       # Assume MSVC wrapper
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+       _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+       # Tell ltmain to make .lib files, not .a files.
+       libext=lib
+       # Tell ltmain to make .dll files, not .so files.
+       shrext_cmds=.dll
+       # FIXME: Setting linknames here is a bad hack.
+       _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED 
'\''s/ -lc$//'\''` -link -dll~linknames='
+       # The linker will automatically build a .lib file if we build a DLL.
+       _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+       # FIXME: Should let the user specify the lib program.
+       _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
+       _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+       ;;
+      esac
+      ;;
+
+    darwin* | rhapsody*)
+      _LT_DARWIN_LINKER_FEATURES($1)
+      ;;
+
+    dgux*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags 
/usr/lib/c++rt0.o'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2.*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    hpux9*)
+      if test yes = "$GCC"; then
+       _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b 
$wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" 
= "x$lib" || mv $output_objdir/$soname $lib'
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o 
$output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv 
$output_objdir/$soname $lib'
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+      ;;
+
+    hpux10*)
+      if test yes,no = "$GCC,$with_gnu_ld"; then
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib 
$libobjs $deplibs $compiler_flags'
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs 
$linker_flags'
+      fi
+      if test no = "$with_gnu_ld"; then
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+       _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+       _LT_TAGVAR(hardcode_direct, $1)=yes
+       _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+       _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+       # hardcode_minus_L: Not really in the search PATH,
+       # but as the default location of the library.
+       _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test yes,no = "$GCC,$with_gnu_ld"; then
+       case $host_cpu in
+       hppa*64*)
+         _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs 
$compiler_flags'
+         ;;
+       ia64*)
+         _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib 
$libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o 
$lib $libobjs $deplibs $compiler_flags'
+         ;;
+       esac
+      else
+       case $host_cpu in
+       hppa*64*)
+         _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs 
$compiler_flags'
+         ;;
+       *)
+       m4_if($1, [], [
+         # Older versions of the 11.00 compiler do not understand -b yet
+         # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+         _LT_LINKER_OPTION([if $CC understands -b],
+           _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b],
+           [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs 
$deplibs $compiler_flags'],
+           [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs 
$linker_flags'])],
+         [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs 
$deplibs $compiler_flags'])
+         ;;
+       esac
+      fi
+      if test no = "$with_gnu_ld"; then
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+       _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+       case $host_cpu in
+       hppa*64*|ia64*)
+         _LT_TAGVAR(hardcode_direct, $1)=no
+         _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+         ;;
+       *)
+         _LT_TAGVAR(hardcode_direct, $1)=yes
+         _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+         _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+
+         # hardcode_minus_L: Not really in the search PATH,
+         # but as the default location of the library.
+         _LT_TAGVAR(hardcode_minus_L, $1)=yes
+         ;;
+       esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test yes = "$GCC"; then
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname 
$wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry 
$wl$output_objdir/so_locations -o $lib'
+       # Try to use the -exported_symbol ld option, if it does not
+       # work, assume that -exports_file does not work either and
+       # implicitly export all symbols.
+       # This should be the same for all languages, so no per-tag cache variable.
+       AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol],
+         [lt_cv_irix_exported_symbol],
+         [save_LDFLAGS=$LDFLAGS
+          LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null"
+          AC_LINK_IFELSE(
+            [AC_LANG_SOURCE(
+               [AC_LANG_CASE([C], [[int foo (void) { return 0; }]],
+                             [C++], [[int foo (void) { return 0; }]],
+                             [Fortran 77], [[
+      subroutine foo
+      end]],
+                             [Fortran], [[
+      subroutine foo
+      end]])])],
+             [lt_cv_irix_exported_symbol=yes],
+             [lt_cv_irix_exported_symbol=no])
+           LDFLAGS=$save_LDFLAGS])
+       if test yes = "$lt_cv_irix_exported_symbol"; then
+          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags 
$wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` 
$wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
+       fi
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n 
"$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname 
`test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry 
$output_objdir/so_locations -exports_file $export_symbols -o $lib'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(inherit_rpath, $1)=yes
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    linux*)
+      case $cc_basename in
+      tcc*)
+       # Fabrice Bellard et al's Tiny C Compiler
+       _LT_TAGVAR(ld_shlibs, $1)=yes
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+       ;;
+      esac
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+       _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    newsos6)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *nto* | *qnx*)
+      ;;
+
+    openbsd* | bitrig*)
+      if test -f /usr/libexec/ld.so; then
+       _LT_TAGVAR(hardcode_direct, $1)=yes
+       _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+       _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+       if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+         _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+         _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs 
$compiler_flags $wl-retain-symbols-file,$export_symbols'
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+         _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+       else
+         _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+       fi
+      else
+       _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    os2*)
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      shrext_cmds=.dll
+      _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > 
$output_objdir/$libname.def~
+       $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+       $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+       $ECHO EXPORTS >> $output_objdir/$libname.def~
+       emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+       $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags 
$output_objdir/$libname.def~
+       emximp -o $lib $output_objdir/$libname.def'
+      _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > 
$output_objdir/$libname.def~
+       $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+       $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+       $ECHO EXPORTS >> $output_objdir/$libname.def~
+       prefix_cmds="$SED"~
+       if test EXPORTS = "`$SED 1q $export_symbols`"; then
+         prefix_cmds="$prefix_cmds -e 1d";
+       fi~
+       prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+       cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+       $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags 
$output_objdir/$libname.def~
+       emximp -o $lib $output_objdir/$libname.def'
+      _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a 
$output_objdir/$libname.def'
+      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      ;;
+
+    osf3*)
+      if test yes = "$GCC"; then
+       _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags 
$wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` 
$wl-update_registry $wl$output_objdir/so_locations -o $lib'
+      else
+       _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags 
-soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry 
$output_objdir/so_locations -o $lib'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
+
+    osf4* | osf5*)     # as osf3* with the addition of -msym flag
+      if test yes = "$GCC"; then
+       _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs 
$compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version 
$wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+      else
+       _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags 
-msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry 
$output_objdir/so_locations -o $lib'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" 
-exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+          $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname 
$soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry 
$output_objdir/so_locations -o $lib~$RM $lib.exp'
+
+       # Both c and cxx compiler support -rpath directly
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
+
+    solaris*)
+      _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
+      if test yes = "$GCC"; then
+       wlarc='$wl'
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs 
$deplibs $compiler_flags'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e 
"s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+          $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs 
$compiler_flags~$RM $lib.exp'
+      else
+       case `$CC -V 2>&1` in
+       *"Compilers 5.0"*)
+         wlarc=''
+         _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs 
$linker_flags'
+         _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e 
"s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+            $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM 
$lib.exp'
+         ;;
+       *)
+         wlarc='$wl'
+         _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs 
$compiler_flags'
+         _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e 
"s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+            $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM 
$lib.exp'
+         ;;
+       esac
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      case $host_os in
+      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+      *)
+       # The compiler driver will combine and reorder linker options,
+       # but understands '-z linker_flag'.  GCC discards it without '$wl',
+       # but is careful enough not to reorder.
+       # Supported since Solaris 2.6 (maybe 2.5.1?)
+       if test yes = "$GCC"; then
+         _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z 
${wl}defaultextract'
+       else
+         _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+       fi
+       ;;
+      esac
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    sunos4*)
+      if test sequent = "$host_vendor"; then
+       # Use $CC to link under sequent, because it throws in some extra .o
+       # files that make .init and .fini sections work.
+       _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+       sni)
+         _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+       ;;
+       siemens)
+         ## LD is ld it makes a PLAMLIB
+         ## CC just makes a GrossModule.
+         _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+         _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+         _LT_TAGVAR(hardcode_direct, $1)=no
+        ;;
+       motorola)
+         _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+       ;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv4.3*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+       runpath_var=LD_RUN_PATH
+       hardcode_runpath_var=yes
+       _LT_TAGVAR(ld_shlibs, $1)=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+      _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      runpath_var='LD_RUN_PATH'
+
+      if test yes = "$GCC"; then
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib 
$libobjs $deplibs $compiler_flags'
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib 
$libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We CANNOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+      _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test yes = "$GCC"; then
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib 
$libobjs $deplibs $compiler_flags'
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib 
$libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *)
+      _LT_TAGVAR(ld_shlibs, $1)=no
+      ;;
+    esac
+
+    if test sni = "$host_vendor"; then
+      case $host in
+      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+       _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym'
+       ;;
+      esac
+    fi
+  fi
+])
+AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no
+
+_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
+
+_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
+_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
+_LT_DECL([], [extract_expsyms_cmds], [2],
+    [The commands to extract the exported symbol list from a shared archive])
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+  # Assume -lc should be added
+  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+  if test yes,yes = "$GCC,$enable_shared"; then
+    case $_LT_TAGVAR(archive_cmds, $1) in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      AC_CACHE_CHECK([whether -lc should be explicitly linked in],
+       [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1),
+       [$RM conftest*
+       echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+       if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+         soname=conftest
+         lib=conftest
+         libobjs=conftest.$ac_objext
+         deplibs=
+         wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
+         pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
+         compiler_flags=-v
+         linker_flags=-v
+         verstring=
+         output_objdir=.
+         libname=conftest
+         lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
+         _LT_TAGVAR(allow_undefined_flag, $1)=
+         if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
+         then
+           lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+         else
+           lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+         fi
+         _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+       else
+         cat conftest.err 1>&5
+       fi
+       $RM conftest*
+       ])
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
+    [Whether or not to add -lc for building shared libraries])
+_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
+    [enable_shared_with_static_runtimes], [0],
+    [Whether or not to disallow shared libs when runtime libs are static])
+_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
+    [Compiler flag to allow reflexive dlopens])
+_LT_TAGDECL([], [whole_archive_flag_spec], [1],
+    [Compiler flag to generate shared objects directly from archives])
+_LT_TAGDECL([], [compiler_needs_object], [1],
+    [Whether the compiler copes with passing no objects directly])
+_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
+    [Create an old-style archive from a shared archive])
+_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
+    [Create a temporary old-style archive to link instead of a shared archive])
+_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
+_LT_TAGDECL([], [archive_expsym_cmds], [2])
+_LT_TAGDECL([], [module_cmds], [2],
+    [Commands used to build a loadable module if different from building
+    a shared archive.])
+_LT_TAGDECL([], [module_expsym_cmds], [2])
+_LT_TAGDECL([], [with_gnu_ld], [1],
+    [Whether we are building with GNU ld or not])
+_LT_TAGDECL([], [allow_undefined_flag], [1],
+    [Flag that allows shared libraries with undefined symbols to be built])
+_LT_TAGDECL([], [no_undefined_flag], [1],
+    [Flag that enforces no undefined symbols])
+_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
+    [Flag to hardcode $libdir into a binary during linking.
+    This must work even if $libdir does not exist])
+_LT_TAGDECL([], [hardcode_libdir_separator], [1],
+    [Whether we need a single "-rpath" flag with a separated argument])
+_LT_TAGDECL([], [hardcode_direct], [0],
+    [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes
+    DIR into the resulting binary])
+_LT_TAGDECL([], [hardcode_direct_absolute], [0],
+    [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes
+    DIR into the resulting binary and the resulting library dependency is
+    "absolute", i.e impossible to change by setting $shlibpath_var if the
+    library is relocated])
+_LT_TAGDECL([], [hardcode_minus_L], [0],
+    [Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+    into the resulting binary])
+_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
+    [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+    into the resulting binary])
+_LT_TAGDECL([], [hardcode_automatic], [0],
+    [Set to "yes" if building a shared library automatically hardcodes DIR
+    into the library and all subsequent libraries and executables linked
+    against it])
+_LT_TAGDECL([], [inherit_rpath], [0],
+    [Set to yes if linker adds runtime paths of dependent libraries
+    to runtime path list])
+_LT_TAGDECL([], [link_all_deplibs], [0],
+    [Whether libtool must link a program against all its dependency libraries])
+_LT_TAGDECL([], [always_export_symbols], [0],
+    [Set to "yes" if exported symbols are required])
+_LT_TAGDECL([], [export_symbols_cmds], [2],
+    [The commands to list exported symbols])
+_LT_TAGDECL([], [exclude_expsyms], [1],
+    [Symbols that should not be listed in the preloaded symbols])
+_LT_TAGDECL([], [include_expsyms], [1],
+    [Symbols that must always be exported])
+_LT_TAGDECL([], [prelink_cmds], [2],
+    [Commands necessary for linking programs (against libraries) with templates])
+_LT_TAGDECL([], [postlink_cmds], [2],
+    [Commands necessary for finishing linking programs])
+_LT_TAGDECL([], [file_list_spec], [1],
+    [Specify filename containing input files])
+dnl FIXME: Not yet implemented
+dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
+dnl    [Compiler flag to generate thread safe objects])
+])# _LT_LINKER_SHLIBS
+
+
+# _LT_LANG_C_CONFIG([TAG])
+# ------------------------
+# Ensure that the configuration variables for a C compiler are suitably
+# defined.  These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_C_CONFIG],
+[m4_require([_LT_DECL_EGREP])dnl
+lt_save_CC=$CC
+AC_LANG_PUSH(C)
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+_LT_TAG_COMPILER
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+  _LT_COMPILER_NO_RTTI($1)
+  _LT_COMPILER_PIC($1)
+  _LT_COMPILER_C_O($1)
+  _LT_COMPILER_FILE_LOCKS($1)
+  _LT_LINKER_SHLIBS($1)
+  _LT_SYS_DYNAMIC_LINKER($1)
+  _LT_LINKER_HARDCODE_LIBPATH($1)
+  LT_SYS_DLOPEN_SELF
+  _LT_CMD_STRIPLIB
+
+  # Report what library types will actually be built
+  AC_MSG_CHECKING([if libtool supports shared libraries])
+  AC_MSG_RESULT([$can_build_shared])
+
+  AC_MSG_CHECKING([whether to build shared libraries])
+  test no = "$can_build_shared" && enable_shared=no
+
+  # On AIX, shared libraries and static libraries use the same namespace, and
+  # are all built from PIC.
+  case $host_os in
+  aix3*)
+    test yes = "$enable_shared" && enable_static=no
+    if test -n "$RANLIB"; then
+      archive_cmds="$archive_cmds~\$RANLIB \$lib"
+      postinstall_cmds='$RANLIB $lib'
+    fi
+    ;;
+
+  aix[[4-9]]*)
+    if test ia64 != "$host_cpu"; then
+      case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+      yes,aix,yes) ;;                  # shared object as lib.so file only
+      yes,svr4,*) ;;                   # shared object as lib.so archive member only
+      yes,*) enable_static=no ;;       # shared object in lib.a archive as well
+      esac
+    fi
+    ;;
+  esac
+  AC_MSG_RESULT([$enable_shared])
+
+  AC_MSG_CHECKING([whether to build static libraries])
+  # Make sure either enable_shared or enable_static is yes.
+  test yes = "$enable_shared" || enable_static=yes
+  AC_MSG_RESULT([$enable_static])
+
+  _LT_CONFIG($1)
+fi
+AC_LANG_POP
+CC=$lt_save_CC
+])# _LT_LANG_C_CONFIG
+
+
+# _LT_LANG_CXX_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a C++ compiler are suitably
+# defined.  These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_CXX_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_PATH_MANIFEST_TOOL])dnl
+if test -n "$CXX" && ( test no != "$CXX" &&
+    ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) ||
+    (test g++ != "$CXX"))); then
+  AC_PROG_CXXCPP
+else
+  _lt_caught_CXX_error=yes
+fi
+
+AC_LANG_PUSH(C++)
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(compiler_needs_object, $1)=no
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the CXX compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test yes != "$_lt_caught_CXX_error"; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="int some_variable = 0;"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC=$CC
+  lt_save_CFLAGS=$CFLAGS
+  lt_save_LD=$LD
+  lt_save_GCC=$GCC
+  GCC=$GXX
+  lt_save_with_gnu_ld=$with_gnu_ld
+  lt_save_path_LD=$lt_cv_path_LD
+  if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+    lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+  else
+    $as_unset lt_cv_prog_gnu_ld
+  fi
+  if test -n "${lt_cv_path_LDCXX+set}"; then
+    lt_cv_path_LD=$lt_cv_path_LDCXX
+  else
+    $as_unset lt_cv_path_LD
+  fi
+  test -z "${LDCXX+set}" || LD=$LDCXX
+  CC=${CXX-"c++"}
+  CFLAGS=$CXXFLAGS
+  compiler=$CC
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+
+  if test -n "$compiler"; then
+    # We don't want -fno-exception when compiling C++ code, so set the
+    # no_builtin_flag separately
+    if test yes = "$GXX"; then
+      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+    else
+      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+    fi
+
+    if test yes = "$GXX"; then
+      # Set up default GNU C++ configuration
+
+      LT_PATH_LD
+
+      # Check if GNU C++ uses GNU ld as the underlying linker, since the
+      # archiving commands below assume that GNU ld is being used.
+      if test yes = "$with_gnu_ld"; then
+        _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs 
$postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs 
$deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o 
$lib'
+
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+
+        # If archive_cmds runs LD, not CC, wlarc should be empty
+        # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+        #     investigate it a little bit more. (MM)
+        wlarc='$wl'
+
+        # ancient GNU ld didn't support --whole-archive et. al.
+        if eval "`$CC -print-prog-name=ld` --help 2>&1" |
+         $GREP 'no-whole-archive' > /dev/null; then
+          _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience 
'$wlarc'--no-whole-archive'
+        else
+          _LT_TAGVAR(whole_archive_flag_spec, $1)=
+        fi
+      else
+        with_gnu_ld=no
+        wlarc=
+
+        # A generic and very simple default shared library creation
+        # command for GNU C++ for the case where it uses the native
+        # linker, instead of GNU ld.  If possible, this setting should
+        # overridden to take advantage of the native linker features on
+        # the platform it is being used on.
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs 
$postdep_objects $compiler_flags -o $lib'
+      fi
+
+      # Commands to make compiler produce verbose output that lists
+      # what "hidden" libraries, object files and flags are used when
+      # linking a shared library.
+      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | 
$GREP "\-L"'
+
+    else
+      GXX=no
+      with_gnu_ld=no
+      wlarc=
+    fi
+
+    # PORTME: fill in a description of your system's C++ link characteristics
+    AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+    _LT_TAGVAR(ld_shlibs, $1)=yes
+    case $host_os in
+      aix3*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+      aix[[4-9]]*)
+        if test ia64 = "$host_cpu"; then
+          # On IA64, the linker does run time linking by default, so we don't
+          # have to do anything special.
+          aix_use_runtimelinking=no
+          exp_sym_flag='-Bexport'
+          no_entry_flag=
+        else
+          aix_use_runtimelinking=no
+
+          # Test if we are trying to use run time linking or normal
+          # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+          # have runtime linking enabled, and use it for executables.
+          # For shared libraries, we enable/disable runtime linking
+          # depending on the kind of the shared library created -
+          # when "with_aix_soname,aix_use_runtimelinking" is:
+          # "aix,no"   lib.a(lib.so.V) shared, rtl:no,  for executables
+          # "aix,yes"  lib.so          shared, rtl:yes, for executables
+          #            lib.a           static archive
+          # "both,no"  lib.so.V(shr.o) shared, rtl:yes
+          #            lib.a(lib.so.V) shared, rtl:no,  for executables
+          # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+          #            lib.a(lib.so.V) shared, rtl:no
+          # "svr4,*"   lib.so.V(shr.o) shared, rtl:yes, for executables
+          #            lib.a           static archive
+          case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+           for ld_flag in $LDFLAGS; do
+             case $ld_flag in
+             *-brtl*)
+               aix_use_runtimelinking=yes
+               break
+               ;;
+             esac
+           done
+           if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+             # With aix-soname=svr4, we create the lib.so.V shared archives only,
+             # so we don't have lib.a shared libs to link our executables.
+             # We have to force runtime linking in this case.
+             aix_use_runtimelinking=yes
+             LDFLAGS="$LDFLAGS -Wl,-brtl"
+           fi
+           ;;
+          esac
+
+          exp_sym_flag='-bexport'
+          no_entry_flag='-bnoentry'
+        fi
+
+        # When large executables or shared objects are built, AIX ld can
+        # have problems creating the table of contents.  If linking a library
+        # or program results in "error TOC overflow" add -mminimal-toc to
+        # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+        # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+        _LT_TAGVAR(archive_cmds, $1)=''
+        _LT_TAGVAR(hardcode_direct, $1)=yes
+        _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+        _LT_TAGVAR(link_all_deplibs, $1)=yes
+        _LT_TAGVAR(file_list_spec, $1)='$wl-f,'
+        case $with_aix_soname,$aix_use_runtimelinking in
+        aix,*) ;;      # no import file
+        svr4,* | *,yes) # use import file
+          # The Import File defines what to hardcode.
+          _LT_TAGVAR(hardcode_direct, $1)=no
+          _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+          ;;
+        esac
+
+        if test yes = "$GXX"; then
+          case $host_os in aix4.[[012]]|aix4.[[012]].*)
+          # We only want to do this on AIX 4.2 and lower, the check
+          # below for broken collect2 doesn't work under 4.3+
+         collect2name=`$CC -print-prog-name=collect2`
+         if test -f "$collect2name" &&
+            strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+         then
+           # We have reworked collect2
+           :
+         else
+           # We have old collect2
+           _LT_TAGVAR(hardcode_direct, $1)=unsupported
+           # It fails to find uninstalled libraries when the uninstalled
+           # path is not listed in the libpath.  Setting hardcode_minus_L
+           # to unsupported forces relinking
+           _LT_TAGVAR(hardcode_minus_L, $1)=yes
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+           _LT_TAGVAR(hardcode_libdir_separator, $1)=
+         fi
+          esac
+          shared_flag='-shared'
+         if test yes = "$aix_use_runtimelinking"; then
+           shared_flag=$shared_flag' $wl-G'
+         fi
+         # Need to ensure runtime linking is disabled for the traditional
+         # shared library, or the linker may eventually find shared libraries
+         # /with/ Import File - we do not want to mix them.
+         shared_flag_aix='-shared'
+         shared_flag_svr4='-shared $wl-G'
+        else
+          # not using gcc
+          if test ia64 = "$host_cpu"; then
+         # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+         # chokes on -Wl,-G. The following line is correct:
+         shared_flag='-G'
+          else
+           if test yes = "$aix_use_runtimelinking"; then
+             shared_flag='$wl-G'
+           else
+             shared_flag='$wl-bM:SRE'
+           fi
+           shared_flag_aix='$wl-bM:SRE'
+           shared_flag_svr4='$wl-G'
+          fi
+        fi
+
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall'
+        # It seems that -bexpall does not export symbols beginning with
+        # underscore (_), so it is better to generate a list of symbols to
+       # export.
+        _LT_TAGVAR(always_export_symbols, $1)=yes
+       if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
+          # Warning - without using the other runtime loading flags (-brtl),
+          # -berok will link without error, but may produce a broken library.
+          # The "-G" linker flag allows undefined symbols.
+          _LT_TAGVAR(no_undefined_flag, $1)='-bernotok'
+          # Determine the default libpath from the value encoded in an empty
+          # executable.
+          _LT_SYS_MODULE_PATH_AIX([$1])
+          _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+
+          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs 
$wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all 
"$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
+        else
+          if test ia64 = "$host_cpu"; then
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib'
+           _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+           _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs 
$deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
+          else
+           # Determine the default libpath from the value encoded in an
+           # empty executable.
+           _LT_SYS_MODULE_PATH_AIX([$1])
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+           # Warning - without using the other run time loading flags,
+           # -berok will link without error, but may produce a broken library.
+           _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok'
+           _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok'
+           if test yes = "$with_gnu_ld"; then
+             # We only use this code for GNU lds that support --whole-archive.
+             _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
+           else
+             # Exported symbols can be pulled into shared objects from archives
+             _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+           fi
+           _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+           _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR 
$output_objdir/$realname.d'
+           # -brtl affects multiple linker settings, -berok does not and is overridden later
+           compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, 
]]\\)%-berok\\1%g"`'
+           if test svr4 != "$with_aix_soname"; then
+             # This is similar to how AIX traditionally builds its shared
+             # libraries. Need -bnortl late, we may have -brtl in LDFLAGS.
+             _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC 
'$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry 
'$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS 
$output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+           fi
+           if test aix != "$with_aix_soname"; then
+             _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC 
'$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs 
$wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e 
$output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! 
$soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all 
"# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > 
$output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname 
$output_objdir/$realname.d/$shared_archive_member_spec.o 
$output_objdir/$realname.d/$shared_archive_member_spec.imp'
+           else
+             # used by -dlpreopen to get the symbols
+             _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV  
$output_objdir/$realname.d/$soname $output_objdir'
+           fi
+           _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r 
$output_objdir/$realname.d'
+          fi
+        fi
+        ;;
+
+      beos*)
+       if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+         _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+         # Joseph Beckenbach <jrb3 best com> says some releases of gcc
+         # support --undefined.  This deserves some investigation.  FIXME
+         _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname 
-o $lib'
+       else
+         _LT_TAGVAR(ld_shlibs, $1)=no
+       fi
+       ;;
+
+      chorus*)
+        case $cc_basename in
+          *)
+         # FIXME: insert proper C++ library support
+         _LT_TAGVAR(ld_shlibs, $1)=no
+         ;;
+        esac
+        ;;
+
+      cygwin* | mingw* | pw32* | cegcc*)
+       case $GXX,$cc_basename in
+       ,cl* | no,cl*)
+         # Native MSVC
+         # hardcode_libdir_flag_spec is actually meaningless, as there is
+         # no search path for DLLs.
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+         _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+         _LT_TAGVAR(always_export_symbols, $1)=yes
+         _LT_TAGVAR(file_list_spec, $1)='@'
+         # Tell ltmain to make .lib files, not .a files.
+         libext=lib
+         # Tell ltmain to make .dll files, not .so files.
+         shrext_cmds=.dll
+         # FIXME: Setting linknames here is a bad hack.
+         _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs 
-Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+         _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+              cp "$export_symbols" "$output_objdir/$soname.def";
+              echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+            else
+              $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
+            fi~
+            $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs 
"@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+            linknames='
+         # The linker will not automatically build a static lib if we build a DLL.
+         # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+         _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+         # Don't use ranlib
+         _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
+         _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
+            lt_tool_outputfile="@TOOL_OUTPUT@"~
+            case $lt_outputfile in
+              *.exe|*.EXE) ;;
+              *)
+                lt_outputfile=$lt_outputfile.exe
+                lt_tool_outputfile=$lt_tool_outputfile.exe
+                ;;
+            esac~
+            func_to_tool_file "$lt_outputfile"~
+            if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
+              $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" 
|| exit 1;
+              $RM "$lt_outputfile.manifest";
+            fi'
+         ;;
+       *)
+         # g++
+         # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+         # as there is no search path for DLLs.
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+         _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols'
+         _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+         _LT_TAGVAR(always_export_symbols, $1)=no
+         _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+         if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+           _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs 
$postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib 
-Xlinker $lib'
+           # If the export-symbols file already is a .def file, use it as
+           # is; otherwise, prepend EXPORTS...
+           _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+              cp $export_symbols $output_objdir/$soname.def;
+            else
+              echo EXPORTS > $output_objdir/$soname.def;
+              cat $export_symbols >> $output_objdir/$soname.def;
+            fi~
+            $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs 
$postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib 
-Xlinker $lib'
+         else
+           _LT_TAGVAR(ld_shlibs, $1)=no
+         fi
+         ;;
+       esac
+       ;;
+      darwin* | rhapsody*)
+        _LT_DARWIN_LINKER_FEATURES($1)
+       ;;
+
+      os2*)
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+       _LT_TAGVAR(hardcode_minus_L, $1)=yes
+       _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+       shrext_cmds=.dll
+       _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > 
$output_objdir/$libname.def~
+         $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+         $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+         $ECHO EXPORTS >> $output_objdir/$libname.def~
+         emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+         $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags 
$output_objdir/$libname.def~
+         emximp -o $lib $output_objdir/$libname.def'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" 
$output_objdir/$libname.def~
+         $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+         $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+         $ECHO EXPORTS >> $output_objdir/$libname.def~
+         prefix_cmds="$SED"~
+         if test EXPORTS = "`$SED 1q $export_symbols`"; then
+           prefix_cmds="$prefix_cmds -e 1d";
+         fi~
+         prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+         cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+         $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags 
$output_objdir/$libname.def~
+         emximp -o $lib $output_objdir/$libname.def'
+       _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a 
$output_objdir/$libname.def'
+       _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+       ;;
+
+      dgux*)
+        case $cc_basename in
+          ec++*)
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+          ghcx*)
+           # Green Hills C++ Compiler
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+          *)
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+        esac
+        ;;
+
+      freebsd2.*)
+        # C++ shared libraries reported to be fairly broken before
+       # switch to ELF
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      freebsd-elf*)
+        _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+        ;;
+
+      freebsd* | dragonfly*)
+        # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+        # conventions
+        _LT_TAGVAR(ld_shlibs, $1)=yes
+        ;;
+
+      haiku*)
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o 
$lib'
+        _LT_TAGVAR(link_all_deplibs, $1)=yes
+        ;;
+
+      hpux9*)
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+        _LT_TAGVAR(hardcode_direct, $1)=yes
+        _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+                                            # but as the default
+                                            # location of the library.
+
+        case $cc_basename in
+          CC*)
+            # FIXME: insert proper C++ library support
+            _LT_TAGVAR(ld_shlibs, $1)=no
+            ;;
+          aCC*)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o 
$output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test 
"x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+            # Commands to make compiler produce verbose output that lists
+            # what "hidden" libraries, object files and flags are used when
+            # linking a shared library.
+            #
+            # There doesn't appear to be a way to prevent this compiler from
+            # explicitly linking system object files so we need to strip them
+            # from the output so that they don't get included in the library
+            # dependencies.
+            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; 
list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list 
$z";;esac; done; func_echo_all "$list"'
+            ;;
+          *)
+            if test yes = "$GXX"; then
+              _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b 
$wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects 
$compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+            else
+              # FIXME: insert proper C++ library support
+              _LT_TAGVAR(ld_shlibs, $1)=no
+            fi
+            ;;
+        esac
+        ;;
+
+      hpux10*|hpux11*)
+        if test no = "$with_gnu_ld"; then
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+         _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+          case $host_cpu in
+            hppa*64*|ia64*)
+              ;;
+            *)
+             _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+              ;;
+          esac
+        fi
+        case $host_cpu in
+          hppa*64*|ia64*)
+            _LT_TAGVAR(hardcode_direct, $1)=no
+            _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+            ;;
+          *)
+            _LT_TAGVAR(hardcode_direct, $1)=yes
+            _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+                                                # but as the default
+                                                # location of the library.
+            ;;
+        esac
+
+        case $cc_basename in
+          CC*)
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+          aCC*)
+           case $host_cpu in
+             hppa*64*)
+               _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs 
$deplibs $postdep_objects $compiler_flags'
+               ;;
+             ia64*)
+               _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib 
$predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+               ;;
+             *)
+               _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib 
$predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+               ;;
+           esac
+           # Commands to make compiler produce verbose output that lists
+           # what "hidden" libraries, object files and flags are used when
+           # linking a shared library.
+           #
+           # There doesn't appear to be a way to prevent this compiler from
+           # explicitly linking system object files so we need to strip them
+           # from the output so that they don't get included in the library
+           # dependencies.
+           output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; 
list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list 
$z";;esac; done; func_echo_all "$list"'
+           ;;
+          *)
+           if test yes = "$GXX"; then
+             if test no = "$with_gnu_ld"; then
+               case $host_cpu in
+                 hppa*64*)
+                   _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib 
$predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+                   ;;
+                 ia64*)
+                   _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname 
$wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+                   ;;
+                 *)
+                   _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b 
$wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+                   ;;
+               esac
+             fi
+           else
+             # FIXME: insert proper C++ library support
+             _LT_TAGVAR(ld_shlibs, $1)=no
+           fi
+           ;;
+        esac
+        ;;
+
+      interix[[3-9]]*)
+       _LT_TAGVAR(hardcode_direct, $1)=no
+       _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+       _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+       # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+       # Instead, shared libraries are loaded at an image base (0x10000000 by
+       # default) and relocated if they conflict, which is a slow very memory
+       # consuming and fragmenting process.  To avoid this, we pick a random,
+       # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+       # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname 
$wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC 
-shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname 
$wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 
262144 + 1342177280` -o $lib'
+       ;;
+      irix5* | irix6*)
+        case $cc_basename in
+          CC*)
+           # SGI C++
+           _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs 
$postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version 
$verstring"` -update_registry $output_objdir/so_locations -o $lib'
+
+           # Archives containing C++ object files must be created using
+           # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
+           # necessary to make sure instantiated templates are included
+           # in the archive.
+           _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+           ;;
+          *)
+           if test yes = "$GXX"; then
+             if test no = "$with_gnu_ld"; then
+               _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs 
$deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all 
"$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+             else
+               _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs 
$deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all 
"$wl-set_version $wl$verstring"` -o $lib'
+             fi
+           fi
+           _LT_TAGVAR(link_all_deplibs, $1)=yes
+           ;;
+        esac
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+        _LT_TAGVAR(inherit_rpath, $1)=yes
+        ;;
+
+      linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+        case $cc_basename in
+          KCC*)
+           # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+           # KCC will only create a shared library if the output file
+           # ends with ".so" (or ".sl" for HP-UX), so rename the library
+           # to its proper name (with version) after linking.
+           _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e 
'\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC 
$predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv 
\$templib $lib'
+           _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e 
'\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC 
$predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib 
$wl-retain-symbols-file,$export_symbols; mv \$templib $lib'
+           # Commands to make compiler produce verbose output that lists
+           # what "hidden" libraries, object files and flags are used when
+           # linking a shared library.
+           #
+           # There doesn't appear to be a way to prevent this compiler from
+           # explicitly linking system object files so we need to strip them
+           # from the output so that they don't get included in the library
+           # dependencies.
+           output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 
| $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) 
list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+           _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+
+           # Archives containing C++ object files must be created using
+           # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+           _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+           ;;
+         icpc* | ecpc* )
+           # Intel C++
+           with_gnu_ld=yes
+           # version 8.0 and above of icpc choke on multiply defined symbols
+           # if we add $predep_objects and $postdep_objects, however 7.1 and
+           # earlier do not add the objects themselves.
+           case `$CC -V 2>&1` in
+             *"Version 7."*)
+               _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects 
$compiler_flags $wl-soname $wl$soname -o $lib'
+               _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs 
$postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+               ;;
+             *)  # Version 8.0 or newer
+               tmp_idyn=
+               case $host_cpu in
+                 ia64*) tmp_idyn=' -i_dynamic';;
+               esac
+               _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags 
$wl-soname $wl$soname -o $lib'
+               _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs 
$compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+               ;;
+           esac
+           _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+           _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+           _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
+           ;;
+          pgCC* | pgcpp*)
+            # Portland Group C++ compiler
+           case `$CC -V` in
+           *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*)
+             _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
+               rm -rf $tpldir~
+               $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
+               compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
+             _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
+                rm -rf $tpldir~
+                $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
+                $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
+                $RANLIB $oldlib'
+             _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
+                rm -rf $tpldir~
+                $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs 
$convenience $postdep_objects~
+                $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | 
$NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+             _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
+                rm -rf $tpldir~
+                $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs 
$convenience $postdep_objects~
+                $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | 
$NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o 
$lib'
+             ;;
+           *) # Version 6 and above use weak symbols
+             _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs 
$postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+             _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs 
$postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+             ;;
+           esac
+
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir'
+           _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+           _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test 
 -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` 
$wl--no-whole-archive'
+            ;;
+         cxx*)
+           # Compaq C++
+           _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects 
$compiler_flags $wl-soname $wl$soname -o $lib'
+           _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs 
$postdep_objects $compiler_flags $wl-soname $wl$soname  -o $lib $wl-retain-symbols-file $wl$export_symbols'
+
+           runpath_var=LD_RUN_PATH
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+           _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+           # Commands to make compiler produce verbose output that lists
+           # what "hidden" libraries, object files and flags are used when
+           # linking a shared library.
+           #
+           # There doesn't appear to be a way to prevent this compiler from
+           # explicitly linking system object files so we need to strip them
+           # from the output so that they don't get included in the library
+           # dependencies.
+           output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; 
templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do 
case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all 
"X$list" | $Xsed'
+           ;;
+         xl* | mpixl* | bgxl*)
+           # IBM XL 8.0 on PPC, with GNU ld
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+           _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+           _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname 
$wl$soname -o $lib'
+           if test yes = "$supports_anon_versioning"; then
+             _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+                cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+                echo "local: *; };" >> $output_objdir/$libname.ver~
+                $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script 
$wl$output_objdir/$libname.ver -o $lib'
+           fi
+           ;;
+         *)
+           case `$CC -V 2>&1 | sed 5q` in
+           *Sun\ C*)
+             # Sun C++ 5.9
+             _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+             _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects 
$libobjs $deplibs $postdep_objects $compiler_flags'
+             _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib 
$predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols'
+             _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+             _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in 
$convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all 
\"$new_convenience\"` $wl--no-whole-archive'
+             _LT_TAGVAR(compiler_needs_object, $1)=yes
+
+             # Not sure whether something based on
+             # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+             # would be better.
+             output_verbose_link_cmd='func_echo_all'
+
+             # Archives containing C++ object files must be created using
+             # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+             # necessary to make sure instantiated templates are included
+             # in the archive.
+             _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+             ;;
+           esac
+           ;;
+       esac
+       ;;
+
+      lynxos*)
+        # FIXME: insert proper C++ library support
+       _LT_TAGVAR(ld_shlibs, $1)=no
+       ;;
+
+      m88k*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+       ;;
+
+      mvs*)
+        case $cc_basename in
+          cxx*)
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+         *)
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+       esac
+       ;;
+
+      netbsd*)
+        if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+         _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable  -o $lib $predep_objects $libobjs $deplibs 
$postdep_objects $linker_flags'
+         wlarc=
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+         _LT_TAGVAR(hardcode_direct, $1)=yes
+         _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+       fi
+       # Workaround some broken pre-1.5 toolchains
+       output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED 
-e "s:-lgcc -lc -lgcc::"'
+       ;;
+
+      *nto* | *qnx*)
+        _LT_TAGVAR(ld_shlibs, $1)=yes
+       ;;
+
+      openbsd* | bitrig*)
+       if test -f /usr/libexec/ld.so; then
+         _LT_TAGVAR(hardcode_direct, $1)=yes
+         _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+         _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+         _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs 
$postdep_objects $compiler_flags -o $lib'
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+         if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then
+           _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs 
$postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib'
+           _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+           _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience 
'$wlarc'--no-whole-archive'
+         fi
+         output_verbose_link_cmd=func_echo_all
+       else
+         _LT_TAGVAR(ld_shlibs, $1)=no
+       fi
+       ;;
+
+      osf3* | osf4* | osf5*)
+        case $cc_basename in
+          KCC*)
+           # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+           # KCC will only create a shared library if the output file
+           # ends with ".so" (or ".sl" for HP-UX), so rename the library
+           # to its proper name (with version) after linking.
+           _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e 
'\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC 
$predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv 
\$templib $lib'
+
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+           _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+           # Archives containing C++ object files must be created using
+           # the KAI C++ compiler.
+           case $host in
+             osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
+             *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
+           esac
+           ;;
+          RCC*)
+           # Rational C++ 2.4.1
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+          cxx*)
+           case $host in
+             osf3*)
+               _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+               _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs 
$deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all 
"$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+               _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+               ;;
+             *)
+               _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+               _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs 
$deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all 
"-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+               _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" 
-exported_symbol "\$i" >> $lib.exp; done~
+                  echo "-hidden">> $lib.exp~
+                  $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects 
$compiler_flags -msym -soname $soname $wl-input $wl$lib.exp  `test -n "$verstring" && $ECHO "-set_version 
$verstring"` -update_registry $output_objdir/so_locations -o $lib~
+                  $RM $lib.exp'
+               _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+               ;;
+           esac
+
+           _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+           # Commands to make compiler produce verbose output that lists
+           # what "hidden" libraries, object files and flags are used when
+           # linking a shared library.
+           #
+           # There doesn't appear to be a way to prevent this compiler from
+           # explicitly linking system object files so we need to strip them
+           # from the output so that they don't get included in the library
+           # dependencies.
+           output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | 
$GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z 
in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; 
func_echo_all "$list"'
+           ;;
+         *)
+           if test yes,no = "$GXX,$with_gnu_ld"; then
+             _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+             case $host in
+               osf3*)
+                 _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects 
$libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && 
func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+                 ;;
+               *)
+                 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag 
$predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n 
"$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry 
$wl$output_objdir/so_locations -o $lib'
+                 ;;
+             esac
+
+             _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+             _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+             # Commands to make compiler produce verbose output that lists
+             # what "hidden" libraries, object files and flags are used when
+             # linking a shared library.
+             output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured 
with:" | $GREP "\-L"'
+
+           else
+             # FIXME: insert proper C++ library support
+             _LT_TAGVAR(ld_shlibs, $1)=no
+           fi
+           ;;
+        esac
+        ;;
+
+      psos*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      sunos4*)
+        case $cc_basename in
+          CC*)
+           # Sun C++ 4.x
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+          lcc*)
+           # Lucid
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+          *)
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+        esac
+        ;;
+
+      solaris*)
+        case $cc_basename in
+          CC* | sunCC*)
+           # Sun C++ 4.2, 5.x and Centerline C++
+            _LT_TAGVAR(archive_cmds_need_lc,$1)=yes
+           _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+           _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects 
$libobjs $deplibs $postdep_objects $compiler_flags'
+           _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e 
"s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+              $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs 
$deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+           _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+           case $host_os in
+             solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+             *)
+               # The compiler driver will combine and reorder linker options,
+               # but understands '-z linker_flag'.
+               # Supported since Solaris 2.6 (maybe 2.5.1?)
+               _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+               ;;
+           esac
+           _LT_TAGVAR(link_all_deplibs, $1)=yes
+
+           output_verbose_link_cmd='func_echo_all'
+
+           # Archives containing C++ object files must be created using
+           # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+           # necessary to make sure instantiated templates are included
+           # in the archive.
+           _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+           ;;
+          gcx*)
+           # Green Hills C++ Compiler
+           _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects 
$compiler_flags $wl-h $wl$soname -o $lib'
+
+           # The C++ compiler must be used to create the archive.
+           _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+           ;;
+          *)
+           # GNU C++ compiler with Solaris linker
+           if test yes,no = "$GXX,$with_gnu_ld"; then
+             _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs'
+             if $CC --version | $GREP -v '^2\.7' > /dev/null; then
+               _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs 
$deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
+               _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED 
-e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+                  $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects 
$libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+               # Commands to make compiler produce verbose output that lists
+               # what "hidden" libraries, object files and flags are used when
+               # linking a shared library.
+               output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured 
with:" | $GREP "\-L"'
+             else
+               # g++ 2.7 appears to require '-G' NOT '-shared' on this
+               # platform.
+               _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs 
$postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
+               _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED 
-e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+                  $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs 
$deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+               # Commands to make compiler produce verbose output that lists
+               # what "hidden" libraries, object files and flags are used when
+               # linking a shared library.
+               output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured 
with:" | $GREP "\-L"'
+             fi
+
+             _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir'
+             case $host_os in
+               solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+               *)
+                 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z 
${wl}defaultextract'
+                 ;;
+             esac
+           fi
+           ;;
+        esac
+        ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+      _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      runpath_var='LD_RUN_PATH'
+
+      case $cc_basename in
+        CC*)
+         _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+         _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib 
$libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+         _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib 
$libobjs $deplibs $compiler_flags'
+         ;;
+      esac
+      ;;
+
+      sysv5* | sco3.2v5* | sco5v6*)
+       # Note: We CANNOT use -z defs as we might desire, because we do not
+       # link with -lc, and that would cause any symbols used from libc to
+       # always be unresolved, which means just about no library would
+       # ever link correctly.  If we're not using GNU ld we use -z text
+       # though, which does catch some bad symbols but isn't as heavy-handed
+       # as -z defs.
+       _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+       _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs'
+       _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+       _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir'
+       _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+       _LT_TAGVAR(link_all_deplibs, $1)=yes
+       _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport'
+       runpath_var='LD_RUN_PATH'
+
+       case $cc_basename in
+          CC*)
+           _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+           _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib 
$libobjs $deplibs $compiler_flags'
+           _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~
+              '"$_LT_TAGVAR(old_archive_cmds, $1)"
+           _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~
+              '"$_LT_TAGVAR(reload_cmds, $1)"
+           ;;
+         *)
+           _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+           _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o 
$lib $libobjs $deplibs $compiler_flags'
+           ;;
+       esac
+      ;;
+
+      tandem*)
+        case $cc_basename in
+          NCC*)
+           # NonStop-UX NCC 3.20
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+          *)
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+        esac
+        ;;
+
+      vxworks*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      *)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+    esac
+
+    AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+    test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no
+
+    _LT_TAGVAR(GCC, $1)=$GXX
+    _LT_TAGVAR(LD, $1)=$LD
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_SYS_HIDDEN_LIBDEPS($1)
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  CC=$lt_save_CC
+  CFLAGS=$lt_save_CFLAGS
+  LDCXX=$LD
+  LD=$lt_save_LD
+  GCC=$lt_save_GCC
+  with_gnu_ld=$lt_save_with_gnu_ld
+  lt_cv_path_LDCXX=$lt_cv_path_LD
+  lt_cv_path_LD=$lt_save_path_LD
+  lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+  lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+fi # test yes != "$_lt_caught_CXX_error"
+
+AC_LANG_POP
+])# _LT_LANG_CXX_CONFIG
+
+
+# _LT_FUNC_STRIPNAME_CNF
+# ----------------------
+# func_stripname_cnf prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+#
+# This function is identical to the (non-XSI) version of func_stripname,
+# except this one can be used by m4 code that may be executed by configure,
+# rather than the libtool script.
+m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl
+AC_REQUIRE([_LT_DECL_SED])
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])
+func_stripname_cnf ()
+{
+  case @S|@2 in
+  .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^ S|@1%%; s%\\\\ S|@2\$%%"`;;
+  *)  func_stripname_result=`$ECHO "@S|@3" | $SED "s%^ S|@1%%; s% S|@2\$%%"`;;
+  esac
+} # func_stripname_cnf
+])# _LT_FUNC_STRIPNAME_CNF
+
+
+# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
+# ---------------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl
+# Dependencies to place before and after the object being linked:
+_LT_TAGVAR(predep_objects, $1)=
+_LT_TAGVAR(postdep_objects, $1)=
+_LT_TAGVAR(predeps, $1)=
+_LT_TAGVAR(postdeps, $1)=
+_LT_TAGVAR(compiler_lib_search_path, $1)=
+
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library.  It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
+int a;
+void foo (void) { a = 0; }
+_LT_EOF
+], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
+class Foo
+{
+public:
+  Foo (void) { a = 0; }
+private:
+  int a;
+};
+_LT_EOF
+], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
+      subroutine foo
+      implicit none
+      integer*4 a
+      a=0
+      return
+      end
+_LT_EOF
+], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
+      subroutine foo
+      implicit none
+      integer a
+      a=0
+      return
+      end
+_LT_EOF
+], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
+public class foo {
+  private int a;
+  public void bar (void) {
+    a = 0;
+  }
+};
+_LT_EOF
+], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF
+package foo
+func foo() {
+}
+_LT_EOF
+])
+
+_lt_libdeps_save_CFLAGS=$CFLAGS
+case "$CC $CFLAGS " in #(
+*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;;
+*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;;
+*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;;
+esac
+
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+  # Parse the compiler output and extract the necessary
+  # objects, libraries and library flags.
+
+  # Sentinel used to keep track of whether or not we are before
+  # the conftest object file.
+  pre_test_object_deps_done=no
+
+  for p in `eval "$output_verbose_link_cmd"`; do
+    case $prev$p in
+
+    -L* | -R* | -l*)
+       # Some compilers place space between "-{L,R}" and the path.
+       # Remove the space.
+       if test x-L = "$p" ||
+          test x-R = "$p"; then
+        prev=$p
+        continue
+       fi
+
+       # Expand the sysroot to ease extracting the directories later.
+       if test -z "$prev"; then
+         case $p in
+         -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;;
+         -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;;
+         -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;;
+         esac
+       fi
+       case $p in
+       =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;;
+       esac
+       if test no = "$pre_test_object_deps_done"; then
+        case $prev in
+        -L | -R)
+          # Internal compiler library paths should come after those
+          # provided the user.  The postdeps already come after the
+          # user supplied libs so there is no need to process them.
+          if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
+            _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p
+          else
+            _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p"
+          fi
+          ;;
+        # The "-l" case would never come before the object being
+        # linked, so don't bother handling this case.
+        esac
+       else
+        if test -z "$_LT_TAGVAR(postdeps, $1)"; then
+          _LT_TAGVAR(postdeps, $1)=$prev$p
+        else
+          _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p"
+        fi
+       fi
+       prev=
+       ;;
+
+    *.lto.$objext) ;; # Ignore GCC LTO objects
+    *.$objext)
+       # This assumes that the test object file only shows up
+       # once in the compiler output.
+       if test "$p" = "conftest.$objext"; then
+        pre_test_object_deps_done=yes
+        continue
+       fi
+
+       if test no = "$pre_test_object_deps_done"; then
+        if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
+          _LT_TAGVAR(predep_objects, $1)=$p
+        else
+          _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
+        fi
+       else
+        if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
+          _LT_TAGVAR(postdep_objects, $1)=$p
+        else
+          _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
+        fi
+       fi
+       ;;
+
+    *) ;; # Ignore the rest.
+
+    esac
+  done
+
+  # Clean up.
+  rm -f a.out a.exe
+else
+  echo "libtool.m4: error: problem compiling $1 test program"
+fi
+
+$RM -f confest.$objext
+CFLAGS=$_lt_libdeps_save_CFLAGS
+
+# PORTME: override above test on systems where it is broken
+m4_if([$1], [CXX],
+[case $host_os in
+interix[[3-9]]*)
+  # Interix 3.5 installs completely hosed .la files for C++, so rather than
+  # hack all around it, let's just trust "g++" to DTRT.
+  _LT_TAGVAR(predep_objects,$1)=
+  _LT_TAGVAR(postdep_objects,$1)=
+  _LT_TAGVAR(postdeps,$1)=
+  ;;
+esac
+])
+
+case " $_LT_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+esac
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=
+if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! 
-L! !g' -e 's!^ !!'`
+fi
+_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
+    [The directories searched by this compiler when creating a shared library])
+_LT_TAGDECL([], [predep_objects], [1],
+    [Dependencies to place before and after the objects being linked to
+    create a shared library])
+_LT_TAGDECL([], [postdep_objects], [1])
+_LT_TAGDECL([], [predeps], [1])
+_LT_TAGDECL([], [postdeps], [1])
+_LT_TAGDECL([], [compiler_lib_search_path], [1],
+    [The library search path used internally by the compiler when linking
+    a shared library])
+])# _LT_SYS_HIDDEN_LIBDEPS
+
+
+# _LT_LANG_F77_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a Fortran 77 compiler are
+# suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_F77_CONFIG],
+[AC_LANG_PUSH(Fortran 77)
+if test -z "$F77" || test no = "$F77"; then
+  _lt_disable_F77=yes
+fi
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the F77 compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test yes != "$_lt_disable_F77"; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="\
+      subroutine t
+      return
+      end
+"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code="\
+      program t
+      end
+"
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC=$CC
+  lt_save_GCC=$GCC
+  lt_save_CFLAGS=$CFLAGS
+  CC=${F77-"f77"}
+  CFLAGS=$FFLAGS
+  compiler=$CC
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+  GCC=$G77
+  if test -n "$compiler"; then
+    AC_MSG_CHECKING([if libtool supports shared libraries])
+    AC_MSG_RESULT([$can_build_shared])
+
+    AC_MSG_CHECKING([whether to build shared libraries])
+    test no = "$can_build_shared" && enable_shared=no
+
+    # On AIX, shared libraries and static libraries use the same namespace, and
+    # are all built from PIC.
+    case $host_os in
+      aix3*)
+        test yes = "$enable_shared" && enable_static=no
+        if test -n "$RANLIB"; then
+          archive_cmds="$archive_cmds~\$RANLIB \$lib"
+          postinstall_cmds='$RANLIB $lib'
+        fi
+        ;;
+      aix[[4-9]]*)
+       if test ia64 != "$host_cpu"; then
+         case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+         yes,aix,yes) ;;               # shared object as lib.so file only
+         yes,svr4,*) ;;                # shared object as lib.so archive member only
+         yes,*) enable_static=no ;;    # shared object in lib.a archive as well
+         esac
+       fi
+        ;;
+    esac
+    AC_MSG_RESULT([$enable_shared])
+
+    AC_MSG_CHECKING([whether to build static libraries])
+    # Make sure either enable_shared or enable_static is yes.
+    test yes = "$enable_shared" || enable_static=yes
+    AC_MSG_RESULT([$enable_static])
+
+    _LT_TAGVAR(GCC, $1)=$G77
+    _LT_TAGVAR(LD, $1)=$LD
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  GCC=$lt_save_GCC
+  CC=$lt_save_CC
+  CFLAGS=$lt_save_CFLAGS
+fi # test yes != "$_lt_disable_F77"
+
+AC_LANG_POP
+])# _LT_LANG_F77_CONFIG
+
+
+# _LT_LANG_FC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for a Fortran compiler are
+# suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_FC_CONFIG],
+[AC_LANG_PUSH(Fortran)
+
+if test -z "$FC" || test no = "$FC"; then
+  _lt_disable_FC=yes
+fi
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for fc test sources.
+ac_ext=${ac_fc_srcext-f}
+
+# Object file extension for compiled fc test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the FC compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test yes != "$_lt_disable_FC"; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="\
+      subroutine t
+      return
+      end
+"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code="\
+      program t
+      end
+"
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC=$CC
+  lt_save_GCC=$GCC
+  lt_save_CFLAGS=$CFLAGS
+  CC=${FC-"f95"}
+  CFLAGS=$FCFLAGS
+  compiler=$CC
+  GCC=$ac_cv_fc_compiler_gnu
+
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+
+  if test -n "$compiler"; then
+    AC_MSG_CHECKING([if libtool supports shared libraries])
+    AC_MSG_RESULT([$can_build_shared])
+
+    AC_MSG_CHECKING([whether to build shared libraries])
+    test no = "$can_build_shared" && enable_shared=no
+
+    # On AIX, shared libraries and static libraries use the same namespace, and
+    # are all built from PIC.
+    case $host_os in
+      aix3*)
+        test yes = "$enable_shared" && enable_static=no
+        if test -n "$RANLIB"; then
+          archive_cmds="$archive_cmds~\$RANLIB \$lib"
+          postinstall_cmds='$RANLIB $lib'
+        fi
+        ;;
+      aix[[4-9]]*)
+       if test ia64 != "$host_cpu"; then
+         case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+         yes,aix,yes) ;;               # shared object as lib.so file only
+         yes,svr4,*) ;;                # shared object as lib.so archive member only
+         yes,*) enable_static=no ;;    # shared object in lib.a archive as well
+         esac
+       fi
+        ;;
+    esac
+    AC_MSG_RESULT([$enable_shared])
+
+    AC_MSG_CHECKING([whether to build static libraries])
+    # Make sure either enable_shared or enable_static is yes.
+    test yes = "$enable_shared" || enable_static=yes
+    AC_MSG_RESULT([$enable_static])
+
+    _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu
+    _LT_TAGVAR(LD, $1)=$LD
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_SYS_HIDDEN_LIBDEPS($1)
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  GCC=$lt_save_GCC
+  CC=$lt_save_CC
+  CFLAGS=$lt_save_CFLAGS
+fi # test yes != "$_lt_disable_FC"
+
+AC_LANG_POP
+])# _LT_LANG_FC_CONFIG
+
+
+# _LT_LANG_GCJ_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Java Compiler compiler
+# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_GCJ_CONFIG],
+[AC_REQUIRE([LT_PROG_GCJ])dnl
+AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=yes
+CC=${GCJ-"gcj"}
+CFLAGS=$GCJFLAGS
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)=$LD
+_LT_CC_BASENAME([$compiler])
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+  _LT_COMPILER_NO_RTTI($1)
+  _LT_COMPILER_PIC($1)
+  _LT_COMPILER_C_O($1)
+  _LT_COMPILER_FILE_LOCKS($1)
+  _LT_LINKER_SHLIBS($1)
+  _LT_LINKER_HARDCODE_LIBPATH($1)
+
+  _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_GCJ_CONFIG
+
+
+# _LT_LANG_GO_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Go compiler
+# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_GO_CONFIG],
+[AC_REQUIRE([LT_PROG_GO])dnl
+AC_LANG_SAVE
+
+# Source file extension for Go test sources.
+ac_ext=go
+
+# Object file extension for compiled Go test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="package main; func main() { }"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='package main; func main() { }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=yes
+CC=${GOC-"gccgo"}
+CFLAGS=$GOFLAGS
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)=$LD
+_LT_CC_BASENAME([$compiler])
+
+# Go did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+  _LT_COMPILER_NO_RTTI($1)
+  _LT_COMPILER_PIC($1)
+  _LT_COMPILER_C_O($1)
+  _LT_COMPILER_FILE_LOCKS($1)
+  _LT_LINKER_SHLIBS($1)
+  _LT_LINKER_HARDCODE_LIBPATH($1)
+
+  _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_GO_CONFIG
+
+
+# _LT_LANG_RC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for the Windows resource compiler
+# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_RC_CONFIG],
+[AC_REQUIRE([LT_PROG_RC])dnl
+AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code=$lt_simple_compile_test_code
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=
+CC=${RC-"windres"}
+CFLAGS=
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+if test -n "$compiler"; then
+  :
+  _LT_CONFIG($1)
+fi
+
+GCC=$lt_save_GCC
+AC_LANG_RESTORE
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_RC_CONFIG
+
+
+# LT_PROG_GCJ
+# -----------
+AC_DEFUN([LT_PROG_GCJ],
+[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
+  [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
+    [AC_CHECK_TOOL(GCJ, gcj,)
+      test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2"
+      AC_SUBST(GCJFLAGS)])])[]dnl
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
+
+
+# LT_PROG_GO
+# ----------
+AC_DEFUN([LT_PROG_GO],
+[AC_CHECK_TOOL(GOC, gccgo,)
+])
+
+
+# LT_PROG_RC
+# ----------
+AC_DEFUN([LT_PROG_RC],
+[AC_CHECK_TOOL(RC, windres,)
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_RC], [])
+
+
+# _LT_DECL_EGREP
+# --------------
+# If we don't have a new enough Autoconf to choose the best grep
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_EGREP],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_REQUIRE([AC_PROG_FGREP])dnl
+test -z "$GREP" && GREP=grep
+_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
+_LT_DECL([], [EGREP], [1], [An ERE matcher])
+_LT_DECL([], [FGREP], [1], [A literal string matcher])
+dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
+AC_SUBST([GREP])
+])
+
+
+# _LT_DECL_OBJDUMP
+# --------------
+# If we don't have a new enough Autoconf to choose the best objdump
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_OBJDUMP],
+[AC_CHECK_TOOL(OBJDUMP, objdump, false)
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
+AC_SUBST([OBJDUMP])
+])
+
+# _LT_DECL_DLLTOOL
+# ----------------
+# Ensure DLLTOOL variable is set.
+m4_defun([_LT_DECL_DLLTOOL],
+[AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [1], [DLL creation program])
+AC_SUBST([DLLTOOL])
+])
+
+# _LT_DECL_SED
+# ------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible.  Prefer GNU sed if found.
+m4_defun([_LT_DECL_SED],
+[AC_PROG_SED
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
+_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
+    [Sed that helps us avoid accidentally triggering echo(1) options like -n])
+])# _LT_DECL_SED
+
+m4_ifndef([AC_PROG_SED], [
+############################################################
+# NOTE: This macro has been submitted for inclusion into   #
+#  GNU Autoconf as AC_PROG_SED.  When it is available in   #
+#  a released version of Autoconf we should remove this    #
+#  macro and use it instead.                               #
+############################################################
+
+m4_defun([AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for lt_ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+        lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+      fi
+    done
+  done
+done
+IFS=$as_save_IFS
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+  test ! -f "$lt_ac_sed" && continue
+  cat /dev/null > conftest.in
+  lt_ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+  # Check for GNU sed and select it if it is found.
+  if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+    lt_cv_path_SED=$lt_ac_sed
+    break
+  fi
+  while true; do
+    cat conftest.in conftest.in >conftest.tmp
+    mv conftest.tmp conftest.in
+    cp conftest.in conftest.nl
+    echo >>conftest.nl
+    $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+    cmp -s conftest.out conftest.nl || break
+    # 10000 chars as input seems more than enough
+    test 10 -lt "$lt_ac_count" && break
+    lt_ac_count=`expr $lt_ac_count + 1`
+    if test "$lt_ac_count" -gt "$lt_ac_max"; then
+      lt_ac_max=$lt_ac_count
+      lt_cv_path_SED=$lt_ac_sed
+    fi
+  done
+done
+])
+SED=$lt_cv_path_SED
+AC_SUBST([SED])
+AC_MSG_RESULT([$SED])
+])#AC_PROG_SED
+])#m4_ifndef
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_SED], [])
+
+
+# _LT_CHECK_SHELL_FEATURES
+# ------------------------
+# Find out whether the shell is Bourne or XSI compatible,
+# or has some other useful features.
+m4_defun([_LT_CHECK_SHELL_FEATURES],
+[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  lt_unset=unset
+else
+  lt_unset=false
+fi
+_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  lt_SP2NL='tr \040 \012'
+  lt_NL2SP='tr \015\012 \040\040'
+  ;;
+ *) # EBCDIC based system
+  lt_SP2NL='tr \100 \n'
+  lt_NL2SP='tr \r\n \100\100'
+  ;;
+esac
+_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
+_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
+])# _LT_CHECK_SHELL_FEATURES
+
+
+# _LT_PATH_CONVERSION_FUNCTIONS
+# -----------------------------
+# Determine what file name conversion functions should be used by
+# func_to_host_file (and, implicitly, by func_to_host_path).  These are needed
+# for certain cross-compile configurations and native mingw.
+m4_defun([_LT_PATH_CONVERSION_FUNCTIONS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_MSG_CHECKING([how to convert $build file names to $host format])
+AC_CACHE_VAL(lt_cv_to_host_file_cmd,
+[case $host in
+  *-*-mingw* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
+        ;;
+      *-*-cygwin* )
+        lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
+        ;;
+      * ) # otherwise, assume *nix
+        lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
+        ;;
+    esac
+    ;;
+  *-*-cygwin* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
+        ;;
+      *-*-cygwin* )
+        lt_cv_to_host_file_cmd=func_convert_file_noop
+        ;;
+      * ) # otherwise, assume *nix
+        lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
+        ;;
+    esac
+    ;;
+  * ) # unhandled hosts (and "normal" native builds)
+    lt_cv_to_host_file_cmd=func_convert_file_noop
+    ;;
+esac
+])
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+AC_MSG_RESULT([$lt_cv_to_host_file_cmd])
+_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd],
+         [0], [convert $build file names to $host format])dnl
+
+AC_MSG_CHECKING([how to convert $build file names to toolchain format])
+AC_CACHE_VAL(lt_cv_to_tool_file_cmd,
+[#assume ordinary cross tools, or native build.
+lt_cv_to_tool_file_cmd=func_convert_file_noop
+case $host in
+  *-*-mingw* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
+        ;;
+    esac
+    ;;
+esac
+])
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+AC_MSG_RESULT([$lt_cv_to_tool_file_cmd])
+_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd],
+         [0], [convert $build files to toolchain format])dnl
+])# _LT_PATH_CONVERSION_FUNCTIONS
diff --git a/m4/lock.m4 b/m4/lock.m4
new file mode 100644
index 0000000..9fd4aa7
--- /dev/null
+++ b/m4/lock.m4
@@ -0,0 +1,42 @@
+# lock.m4 serial 13 (gettext-0.18.2)
+dnl Copyright (C) 2005-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_DEFUN([gl_LOCK],
+[
+  AC_REQUIRE([gl_THREADLIB])
+  if test "$gl_threads_api" = posix; then
+    # OSF/1 4.0 and Mac OS X 10.1 lack the pthread_rwlock_t type and the
+    # pthread_rwlock_* functions.
+    AC_CHECK_TYPE([pthread_rwlock_t],
+      [AC_DEFINE([HAVE_PTHREAD_RWLOCK], [1],
+         [Define if the POSIX multithreading library has read/write locks.])],
+      [],
+      [#include <pthread.h>])
+    # glibc defines PTHREAD_MUTEX_RECURSIVE as enum, not as a macro.
+    AC_COMPILE_IFELSE([
+      AC_LANG_PROGRAM(
+        [[#include <pthread.h>]],
+        [[
+#if __FreeBSD__ == 4
+error "No, in FreeBSD 4.0 recursive mutexes actually don't work."
+#elif (defined __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ \
+       && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070)
+error "No, in Mac OS X < 10.7 recursive mutexes actually don't work."
+#else
+int x = (int)PTHREAD_MUTEX_RECURSIVE;
+return !x;
+#endif
+        ]])],
+      [AC_DEFINE([HAVE_PTHREAD_MUTEX_RECURSIVE], [1],
+         [Define if the <pthread.h> defines PTHREAD_MUTEX_RECURSIVE.])])
+  fi
+  gl_PREREQ_LOCK
+])
+
+# Prerequisites of lib/glthread/lock.c.
+AC_DEFUN([gl_PREREQ_LOCK], [:])
diff --git a/m4/longlong.m4 b/m4/longlong.m4
new file mode 100644
index 0000000..d57bc70
--- /dev/null
+++ b/m4/longlong.m4
@@ -0,0 +1,113 @@
+# longlong.m4 serial 17
+dnl Copyright (C) 1999-2007, 2009-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Paul Eggert.
+
+# Define HAVE_LONG_LONG_INT if 'long long int' works.
+# This fixes a bug in Autoconf 2.61, and can be faster
+# than what's in Autoconf 2.62 through 2.68.
+
+# Note: If the type 'long long int' exists but is only 32 bits large
+# (as on some very old compilers), HAVE_LONG_LONG_INT will not be
+# defined. In this case you can treat 'long long int' like 'long int'.
+
+AC_DEFUN([AC_TYPE_LONG_LONG_INT],
+[
+  AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT])
+  AC_CACHE_CHECK([for long long int], [ac_cv_type_long_long_int],
+     [ac_cv_type_long_long_int=yes
+      if test "x${ac_cv_prog_cc_c99-no}" = xno; then
+        ac_cv_type_long_long_int=$ac_cv_type_unsigned_long_long_int
+        if test $ac_cv_type_long_long_int = yes; then
+          dnl Catch a bug in Tandem NonStop Kernel (OSS) cc -O circa 2004.
+          dnl If cross compiling, assume the bug is not important, since
+          dnl nobody cross compiles for this platform as far as we know.
+          AC_RUN_IFELSE(
+            [AC_LANG_PROGRAM(
+               [[ %:@include <limits.h>
+                 @%:@ifndef LLONG_MAX
+                 @%:@ define HALF \
+                          (1LL << (sizeof (long long int) * CHAR_BIT - 2))
+                 @%:@ define LLONG_MAX (HALF - 1 + HALF)
+                 @%:@endif]],
+               [[long long int n = 1;
+                 int i;
+                 for (i = 0; ; i++)
+                   {
+                     long long int m = n << i;
+                     if (m >> i != n)
+                       return 1;
+                     if (LLONG_MAX / 2 < m)
+                       break;
+                   }
+                 return 0;]])],
+            [],
+            [ac_cv_type_long_long_int=no],
+            [:])
+        fi
+      fi])
+  if test $ac_cv_type_long_long_int = yes; then
+    AC_DEFINE([HAVE_LONG_LONG_INT], [1],
+      [Define to 1 if the system has the type 'long long int'.])
+  fi
+])
+
+# Define HAVE_UNSIGNED_LONG_LONG_INT if 'unsigned long long int' works.
+# This fixes a bug in Autoconf 2.61, and can be faster
+# than what's in Autoconf 2.62 through 2.68.
+
+# Note: If the type 'unsigned long long int' exists but is only 32 bits
+# large (as on some very old compilers), AC_TYPE_UNSIGNED_LONG_LONG_INT
+# will not be defined. In this case you can treat 'unsigned long long int'
+# like 'unsigned long int'.
+
+AC_DEFUN([AC_TYPE_UNSIGNED_LONG_LONG_INT],
+[
+  AC_CACHE_CHECK([for unsigned long long int],
+    [ac_cv_type_unsigned_long_long_int],
+    [ac_cv_type_unsigned_long_long_int=yes
+     if test "x${ac_cv_prog_cc_c99-no}" = xno; then
+       AC_LINK_IFELSE(
+         [_AC_TYPE_LONG_LONG_SNIPPET],
+         [],
+         [ac_cv_type_unsigned_long_long_int=no])
+     fi])
+  if test $ac_cv_type_unsigned_long_long_int = yes; then
+    AC_DEFINE([HAVE_UNSIGNED_LONG_LONG_INT], [1],
+      [Define to 1 if the system has the type 'unsigned long long int'.])
+  fi
+])
+
+# Expands to a C program that can be used to test for simultaneous support
+# of 'long long' and 'unsigned long long'. We don't want to say that
+# 'long long' is available if 'unsigned long long' is not, or vice versa,
+# because too many programs rely on the symmetry between signed and unsigned
+# integer types (excluding 'bool').
+AC_DEFUN([_AC_TYPE_LONG_LONG_SNIPPET],
+[
+  AC_LANG_PROGRAM(
+    [[/* For now, do not test the preprocessor; as of 2007 there are too many
+         implementations with broken preprocessors.  Perhaps this can
+         be revisited in 2012.  In the meantime, code should not expect
+         #if to work with literals wider than 32 bits.  */
+      /* Test literals.  */
+      long long int ll = 9223372036854775807ll;
+      long long int nll = -9223372036854775807LL;
+      unsigned long long int ull = 18446744073709551615ULL;
+      /* Test constant expressions.   */
+      typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll)
+                     ? 1 : -1)];
+      typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1
+                     ? 1 : -1)];
+      int i = 63;]],
+    [[/* Test availability of runtime routines for shift and division.  */
+      long long int llmax = 9223372036854775807ll;
+      unsigned long long int ullmax = 18446744073709551615ull;
+      return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i)
+              | (llmax / ll) | (llmax % ll)
+              | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i)
+              | (ullmax / ull) | (ullmax % ull));]])
+])
diff --git a/m4/ltoptions.m4 b/m4/ltoptions.m4
new file mode 100644
index 0000000..94b0829
--- /dev/null
+++ b/m4/ltoptions.m4
@@ -0,0 +1,437 @@
+# Helper functions for option handling.                    -*- Autoconf -*-
+#
+#   Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software
+#   Foundation, Inc.
+#   Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 8 ltoptions.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
+
+
+# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
+# ------------------------------------------
+m4_define([_LT_MANGLE_OPTION],
+[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
+
+
+# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
+# ---------------------------------------
+# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
+# matching handler defined, dispatch to it.  Other OPTION-NAMEs are
+# saved as a flag.
+m4_define([_LT_SET_OPTION],
+[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
+m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
+        _LT_MANGLE_DEFUN([$1], [$2]),
+    [m4_warning([Unknown $1 option '$2'])])[]dnl
+])
+
+
+# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
+# ------------------------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+m4_define([_LT_IF_OPTION],
+[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
+
+
+# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
+# -------------------------------------------------------
+# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
+# are set.
+m4_define([_LT_UNLESS_OPTIONS],
+[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+           [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
+                     [m4_define([$0_found])])])[]dnl
+m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
+])[]dnl
+])
+
+
+# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
+# ----------------------------------------
+# OPTION-LIST is a space-separated list of Libtool options associated
+# with MACRO-NAME.  If any OPTION has a matching handler declared with
+# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
+# the unknown option and exit.
+m4_defun([_LT_SET_OPTIONS],
+[# Set options
+m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+    [_LT_SET_OPTION([$1], _LT_Option)])
+
+m4_if([$1],[LT_INIT],[
+  dnl
+  dnl Simply set some default values (i.e off) if boolean options were not
+  dnl specified:
+  _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
+  ])
+  _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
+  ])
+  dnl
+  dnl If no reference was made to various pairs of opposing options, then
+  dnl we run the default mode handler for the pair.  For example, if neither
+  dnl 'shared' nor 'disable-shared' was passed, we enable building of shared
+  dnl archives by default:
+  _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
+  _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
+  _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
+  _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
+                  [_LT_ENABLE_FAST_INSTALL])
+  _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4],
+                  [_LT_WITH_AIX_SONAME([aix])])
+  ])
+])# _LT_SET_OPTIONS
+
+
+## --------------------------------- ##
+## Macros to handle LT_INIT options. ##
+## --------------------------------- ##
+
+# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
+# -----------------------------------------
+m4_define([_LT_MANGLE_DEFUN],
+[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
+
+
+# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
+# -----------------------------------------------
+m4_define([LT_OPTION_DEFINE],
+[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
+])# LT_OPTION_DEFINE
+
+
+# dlopen
+# ------
+LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
+])
+
+AU_DEFUN([AC_LIBTOOL_DLOPEN],
+[_LT_SET_OPTION([LT_INIT], [dlopen])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the 'dlopen' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
+
+
+# win32-dll
+# ---------
+# Declare package support for building win32 dll's.
+LT_OPTION_DEFINE([LT_INIT], [win32-dll],
+[enable_win32_dll=yes
+
+case $host in
+*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
+  AC_CHECK_TOOL(AS, as, false)
+  AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+  AC_CHECK_TOOL(OBJDUMP, objdump, false)
+  ;;
+esac
+
+test -z "$AS" && AS=as
+_LT_DECL([], [AS],      [1], [Assembler program])dnl
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
+])# win32-dll
+
+AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+_LT_SET_OPTION([LT_INIT], [win32-dll])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the 'win32-dll' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
+
+
+# _LT_ENABLE_SHARED([DEFAULT])
+# ----------------------------
+# implement the --enable-shared flag, and supports the 'shared' and
+# 'disable-shared' LT_INIT options.
+# DEFAULT is either 'yes' or 'no'.  If omitted, it defaults to 'yes'.
+m4_define([_LT_ENABLE_SHARED],
+[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([shared],
+    [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+       [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+      for pkg in $enableval; do
+       IFS=$lt_save_ifs
+       if test "X$pkg" = "X$p"; then
+         enable_shared=yes
+       fi
+      done
+      IFS=$lt_save_ifs
+      ;;
+    esac],
+    [enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
+
+    _LT_DECL([build_libtool_libs], [enable_shared], [0],
+       [Whether or not to build shared libraries])
+])# _LT_ENABLE_SHARED
+
+LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
+])
+
+AC_DEFUN([AC_DISABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], [disable-shared])
+])
+
+AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
+AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_SHARED], [])
+dnl AC_DEFUN([AM_DISABLE_SHARED], [])
+
+
+
+# _LT_ENABLE_STATIC([DEFAULT])
+# ----------------------------
+# implement the --enable-static flag, and support the 'static' and
+# 'disable-static' LT_INIT options.
+# DEFAULT is either 'yes' or 'no'.  If omitted, it defaults to 'yes'.
+m4_define([_LT_ENABLE_STATIC],
+[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([static],
+    [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+       [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+      for pkg in $enableval; do
+       IFS=$lt_save_ifs
+       if test "X$pkg" = "X$p"; then
+         enable_static=yes
+       fi
+      done
+      IFS=$lt_save_ifs
+      ;;
+    esac],
+    [enable_static=]_LT_ENABLE_STATIC_DEFAULT)
+
+    _LT_DECL([build_old_libs], [enable_static], [0],
+       [Whether or not to build static libraries])
+])# _LT_ENABLE_STATIC
+
+LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
+])
+
+AC_DEFUN([AC_DISABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], [disable-static])
+])
+
+AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
+AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_STATIC], [])
+dnl AC_DEFUN([AM_DISABLE_STATIC], [])
+
+
+
+# _LT_ENABLE_FAST_INSTALL([DEFAULT])
+# ----------------------------------
+# implement the --enable-fast-install flag, and support the 'fast-install'
+# and 'disable-fast-install' LT_INIT options.
+# DEFAULT is either 'yes' or 'no'.  If omitted, it defaults to 'yes'.
+m4_define([_LT_ENABLE_FAST_INSTALL],
+[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([fast-install],
+    [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+    [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+      for pkg in $enableval; do
+       IFS=$lt_save_ifs
+       if test "X$pkg" = "X$p"; then
+         enable_fast_install=yes
+       fi
+      done
+      IFS=$lt_save_ifs
+      ;;
+    esac],
+    [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
+
+_LT_DECL([fast_install], [enable_fast_install], [0],
+        [Whether or not to optimize for fast installation])dnl
+])# _LT_ENABLE_FAST_INSTALL
+
+LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
+
+# Old names:
+AU_DEFUN([AC_ENABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the 'fast-install' option into LT_INIT's first parameter.])
+])
+
+AU_DEFUN([AC_DISABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the 'disable-fast-install' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
+dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
+
+
+# _LT_WITH_AIX_SONAME([DEFAULT])
+# ----------------------------------
+# implement the --with-aix-soname flag, and support the `aix-soname=aix'
+# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT
+# is either `aix', `both' or `svr4'.  If omitted, it defaults to `aix'.
+m4_define([_LT_WITH_AIX_SONAME],
+[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl
+shared_archive_member_spec=
+case $host,$enable_shared in
+power*-*-aix[[5-9]]*,yes)
+  AC_MSG_CHECKING([which variant of shared library versioning to provide])
+  AC_ARG_WITH([aix-soname],
+    [AS_HELP_STRING([--with-aix-soname=aix|svr4|both],
+      [shared library versioning (aka "SONAME") variant to provide on AIX, 
@<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])],
+    [case $withval in
+    aix|svr4|both)
+      ;;
+    *)
+      AC_MSG_ERROR([Unknown argument to --with-aix-soname])
+      ;;
+    esac
+    lt_cv_with_aix_soname=$with_aix_soname],
+    [AC_CACHE_VAL([lt_cv_with_aix_soname],
+      [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT)
+    with_aix_soname=$lt_cv_with_aix_soname])
+  AC_MSG_RESULT([$with_aix_soname])
+  if test aix != "$with_aix_soname"; then
+    # For the AIX way of multilib, we name the shared archive member
+    # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
+    # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
+    # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
+    # the AIX toolchain works better with OBJECT_MODE set (default 32).
+    if test 64 = "${OBJECT_MODE-32}"; then
+      shared_archive_member_spec=shr_64
+    else
+      shared_archive_member_spec=shr
+    fi
+  fi
+  ;;
+*)
+  with_aix_soname=aix
+  ;;
+esac
+
+_LT_DECL([], [shared_archive_member_spec], [0],
+    [Shared archive member basename, for filename based shared library versioning on AIX])dnl
+])# _LT_WITH_AIX_SONAME
+
+LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])])
+LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])])
+LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])])
+
+
+# _LT_WITH_PIC([MODE])
+# --------------------
+# implement the --with-pic flag, and support the 'pic-only' and 'no-pic'
+# LT_INIT options.
+# MODE is either 'yes' or 'no'.  If omitted, it defaults to 'both'.
+m4_define([_LT_WITH_PIC],
+[AC_ARG_WITH([pic],
+    [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@],
+       [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+    [lt_p=${PACKAGE-default}
+    case $withval in
+    yes|no) pic_mode=$withval ;;
+    *)
+      pic_mode=default
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+      for lt_pkg in $withval; do
+       IFS=$lt_save_ifs
+       if test "X$lt_pkg" = "X$lt_p"; then
+         pic_mode=yes
+       fi
+      done
+      IFS=$lt_save_ifs
+      ;;
+    esac],
+    [pic_mode=m4_default([$1], [default])])
+
+_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
+])# _LT_WITH_PIC
+
+LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
+
+# Old name:
+AU_DEFUN([AC_LIBTOOL_PICMODE],
+[_LT_SET_OPTION([LT_INIT], [pic-only])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the 'pic-only' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
+
+## ----------------- ##
+## LTDL_INIT Options ##
+## ----------------- ##
+
+m4_define([_LTDL_MODE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
+                [m4_define([_LTDL_MODE], [nonrecursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [recursive],
+                [m4_define([_LTDL_MODE], [recursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [subproject],
+                [m4_define([_LTDL_MODE], [subproject])])
+
+m4_define([_LTDL_TYPE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [installable],
+                [m4_define([_LTDL_TYPE], [installable])])
+LT_OPTION_DEFINE([LTDL_INIT], [convenience],
+                [m4_define([_LTDL_TYPE], [convenience])])
diff --git a/m4/ltsugar.m4 b/m4/ltsugar.m4
new file mode 100644
index 0000000..48bc934
--- /dev/null
+++ b/m4/ltsugar.m4
@@ -0,0 +1,124 @@
+# ltsugar.m4 -- libtool m4 base layer.                         -*-Autoconf-*-
+#
+# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software
+# Foundation, Inc.
+# Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 6 ltsugar.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
+
+
+# lt_join(SEP, ARG1, [ARG2...])
+# -----------------------------
+# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
+# associated separator.
+# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
+# versions in m4sugar had bugs.
+m4_define([lt_join],
+[m4_if([$#], [1], [],
+       [$#], [2], [[$2]],
+       [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
+m4_define([_lt_join],
+[m4_if([$#$2], [2], [],
+       [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
+
+
+# lt_car(LIST)
+# lt_cdr(LIST)
+# ------------
+# Manipulate m4 lists.
+# These macros are necessary as long as will still need to support
+# Autoconf-2.59, which quotes differently.
+m4_define([lt_car], [[$1]])
+m4_define([lt_cdr],
+[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
+       [$#], 1, [],
+       [m4_dquote(m4_shift($@))])])
+m4_define([lt_unquote], $1)
+
+
+# lt_append(MACRO-NAME, STRING, [SEPARATOR])
+# ------------------------------------------
+# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'.
+# Note that neither SEPARATOR nor STRING are expanded; they are appended
+# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
+# No SEPARATOR is output if MACRO-NAME was previously undefined (different
+# than defined and empty).
+#
+# This macro is needed until we can rely on Autoconf 2.62, since earlier
+# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
+m4_define([lt_append],
+[m4_define([$1],
+          m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
+
+
+
+# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
+# ----------------------------------------------------------
+# Produce a SEP delimited list of all paired combinations of elements of
+# PREFIX-LIST with SUFFIX1 through SUFFIXn.  Each element of the list
+# has the form PREFIXmINFIXSUFFIXn.
+# Needed until we can rely on m4_combine added in Autoconf 2.62.
+m4_define([lt_combine],
+[m4_if(m4_eval([$# > 3]), [1],
+       [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
+[[m4_foreach([_Lt_prefix], [$2],
+            [m4_foreach([_Lt_suffix],
+               ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
+       [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
+
+
+# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
+# -----------------------------------------------------------------------
+# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
+# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
+m4_define([lt_if_append_uniq],
+[m4_ifdef([$1],
+         [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
+                [lt_append([$1], [$2], [$3])$4],
+                [$5])],
+         [lt_append([$1], [$2], [$3])$4])])
+
+
+# lt_dict_add(DICT, KEY, VALUE)
+# -----------------------------
+m4_define([lt_dict_add],
+[m4_define([$1($2)], [$3])])
+
+
+# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
+# --------------------------------------------
+m4_define([lt_dict_add_subkey],
+[m4_define([$1($2:$3)], [$4])])
+
+
+# lt_dict_fetch(DICT, KEY, [SUBKEY])
+# ----------------------------------
+m4_define([lt_dict_fetch],
+[m4_ifval([$3],
+       m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
+    m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
+
+
+# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
+# -----------------------------------------------------------------
+m4_define([lt_if_dict_fetch],
+[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
+       [$5],
+    [$6])])
+
+
+# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
+# --------------------------------------------------------------
+m4_define([lt_dict_filter],
+[m4_if([$5], [], [],
+  [lt_join(m4_quote(m4_default([$4], [[, ]])),
+           lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
+                     [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
+])
diff --git a/m4/ltversion.m4 b/m4/ltversion.m4
new file mode 100644
index 0000000..fa04b52
--- /dev/null
+++ b/m4/ltversion.m4
@@ -0,0 +1,23 @@
+# ltversion.m4 -- version numbers                      -*- Autoconf -*-
+#
+#   Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc.
+#   Written by Scott James Remnant, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# @configure_input@
+
+# serial 4179 ltversion.m4
+# This file is part of GNU Libtool
+
+m4_define([LT_PACKAGE_VERSION], [2.4.6])
+m4_define([LT_PACKAGE_REVISION], [2.4.6])
+
+AC_DEFUN([LTVERSION_VERSION],
+[macro_version='2.4.6'
+macro_revision='2.4.6'
+_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
+_LT_DECL(, macro_revision, 0)
+])
diff --git a/m4/lt~obsolete.m4 b/m4/lt~obsolete.m4
new file mode 100644
index 0000000..c6b26f8
--- /dev/null
+++ b/m4/lt~obsolete.m4
@@ -0,0 +1,99 @@
+# lt~obsolete.m4 -- aclocal satisfying obsolete definitions.    -*-Autoconf-*-
+#
+#   Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software
+#   Foundation, Inc.
+#   Written by Scott James Remnant, 2004.
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 5 lt~obsolete.m4
+
+# These exist entirely to fool aclocal when bootstrapping libtool.
+#
+# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN),
+# which have later been changed to m4_define as they aren't part of the
+# exported API, or moved to Autoconf or Automake where they belong.
+#
+# The trouble is, aclocal is a bit thick.  It'll see the old AC_DEFUN
+# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
+# using a macro with the same name in our local m4/libtool.m4 it'll
+# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
+# and doesn't know about Autoconf macros at all.)
+#
+# So we provide this file, which has a silly filename so it's always
+# included after everything else.  This provides aclocal with the
+# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
+# because those macros already exist, or will be overwritten later.
+# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
+#
+# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
+# Yes, that means every name once taken will need to remain here until
+# we give up compatibility with versions before 1.7, at which point
+# we need to keep only those names which we still refer to.
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
+
+m4_ifndef([AC_LIBTOOL_LINKER_OPTION],  [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
+m4_ifndef([AC_PROG_EGREP],             [AC_DEFUN([AC_PROG_EGREP])])
+m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH],        [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_AC_SHELL_INIT],         [AC_DEFUN([_LT_AC_SHELL_INIT])])
+m4_ifndef([_LT_AC_SYS_LIBPATH_AIX],    [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
+m4_ifndef([_LT_PROG_LTMAIN],           [AC_DEFUN([_LT_PROG_LTMAIN])])
+m4_ifndef([_LT_AC_TAGVAR],             [AC_DEFUN([_LT_AC_TAGVAR])])
+m4_ifndef([AC_LTDL_ENABLE_INSTALL],    [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
+m4_ifndef([AC_LTDL_PREOPEN],           [AC_DEFUN([AC_LTDL_PREOPEN])])
+m4_ifndef([_LT_AC_SYS_COMPILER],       [AC_DEFUN([_LT_AC_SYS_COMPILER])])
+m4_ifndef([_LT_AC_LOCK],               [AC_DEFUN([_LT_AC_LOCK])])
+m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE],        [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
+m4_ifndef([_LT_AC_TRY_DLOPEN_SELF],    [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
+m4_ifndef([AC_LIBTOOL_PROG_CC_C_O],    [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
+m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
+m4_ifndef([AC_LIBTOOL_OBJDIR],         [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
+m4_ifndef([AC_LTDL_OBJDIR],            [AC_DEFUN([AC_LTDL_OBJDIR])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
+m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP],  [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
+m4_ifndef([AC_PATH_MAGIC],             [AC_DEFUN([AC_PATH_MAGIC])])
+m4_ifndef([AC_PROG_LD_GNU],            [AC_DEFUN([AC_PROG_LD_GNU])])
+m4_ifndef([AC_PROG_LD_RELOAD_FLAG],    [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
+m4_ifndef([AC_DEPLIBS_CHECK_METHOD],   [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
+m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
+m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
+m4_ifndef([LT_AC_PROG_EGREP],          [AC_DEFUN([LT_AC_PROG_EGREP])])
+m4_ifndef([LT_AC_PROG_SED],            [AC_DEFUN([LT_AC_PROG_SED])])
+m4_ifndef([_LT_CC_BASENAME],           [AC_DEFUN([_LT_CC_BASENAME])])
+m4_ifndef([_LT_COMPILER_BOILERPLATE],  [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
+m4_ifndef([_LT_LINKER_BOILERPLATE],    [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
+m4_ifndef([_AC_PROG_LIBTOOL],          [AC_DEFUN([_AC_PROG_LIBTOOL])])
+m4_ifndef([AC_LIBTOOL_SETUP],          [AC_DEFUN([AC_LIBTOOL_SETUP])])
+m4_ifndef([_LT_AC_CHECK_DLFCN],                [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
+m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER],     [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
+m4_ifndef([_LT_AC_TAGCONFIG],          [AC_DEFUN([_LT_AC_TAGCONFIG])])
+m4_ifndef([AC_DISABLE_FAST_INSTALL],   [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
+m4_ifndef([_LT_AC_LANG_CXX],           [AC_DEFUN([_LT_AC_LANG_CXX])])
+m4_ifndef([_LT_AC_LANG_F77],           [AC_DEFUN([_LT_AC_LANG_F77])])
+m4_ifndef([_LT_AC_LANG_GCJ],           [AC_DEFUN([_LT_AC_LANG_GCJ])])
+m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG],  [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
+m4_ifndef([_LT_AC_LANG_C_CONFIG],      [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG],        [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
+m4_ifndef([_LT_AC_LANG_CXX_CONFIG],    [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG],        [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
+m4_ifndef([_LT_AC_LANG_F77_CONFIG],    [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG],        [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
+m4_ifndef([_LT_AC_LANG_GCJ_CONFIG],    [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
+m4_ifndef([_LT_AC_LANG_RC_CONFIG],     [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
+m4_ifndef([AC_LIBTOOL_CONFIG],         [AC_DEFUN([AC_LIBTOOL_CONFIG])])
+m4_ifndef([_LT_AC_FILE_LTDLL_C],       [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
+m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS],        [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
+m4_ifndef([_LT_AC_PROG_CXXCPP],                [AC_DEFUN([_LT_AC_PROG_CXXCPP])])
+m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS],        [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
+m4_ifndef([_LT_PROG_ECHO_BACKSLASH],   [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_PROG_F77],              [AC_DEFUN([_LT_PROG_F77])])
+m4_ifndef([_LT_PROG_FC],               [AC_DEFUN([_LT_PROG_FC])])
+m4_ifndef([_LT_PROG_CXX],              [AC_DEFUN([_LT_PROG_CXX])])
diff --git a/m4/nls.m4 b/m4/nls.m4
new file mode 100644
index 0000000..93df8d3
--- /dev/null
+++ b/m4/nls.m4
@@ -0,0 +1,32 @@
+# nls.m4 serial 5 (gettext-0.18)
+dnl Copyright (C) 1995-2003, 2005-2006, 2008-2014 Free Software Foundation,
+dnl Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+dnl
+dnl This file can be used in projects which are not available under
+dnl the GNU General Public License or the GNU Library General Public
+dnl License but which still want to provide support for the GNU gettext
+dnl functionality.
+dnl Please note that the actual code of the GNU gettext library is covered
+dnl by the GNU Library General Public License, and the rest of the GNU
+dnl gettext package is covered by the GNU General Public License.
+dnl They are *not* in the public domain.
+
+dnl Authors:
+dnl   Ulrich Drepper <drepper cygnus com>, 1995-2000.
+dnl   Bruno Haible <haible clisp cons org>, 2000-2003.
+
+AC_PREREQ([2.50])
+
+AC_DEFUN([AM_NLS],
+[
+  AC_MSG_CHECKING([whether NLS is requested])
+  dnl Default is enabled NLS
+  AC_ARG_ENABLE([nls],
+    [  --disable-nls           do not use Native Language Support],
+    USE_NLS=$enableval, USE_NLS=yes)
+  AC_MSG_RESULT([$USE_NLS])
+  AC_SUBST([USE_NLS])
+])
diff --git a/m4/pkg.m4 b/m4/pkg.m4
new file mode 100644
index 0000000..c5b26b5
--- /dev/null
+++ b/m4/pkg.m4
@@ -0,0 +1,214 @@
+# pkg.m4 - Macros to locate and utilise pkg-config.            -*- Autoconf -*-
+# serial 1 (pkg-config-0.24)
+# 
+# Copyright © 2004 Scott James Remnant <scott netsplit com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
+m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
+AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
+AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+       AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+       _pkg_min_version=m4_default([$1], [0.9.0])
+       AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+       if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+               AC_MSG_RESULT([yes])
+       else
+               AC_MSG_RESULT([no])
+               PKG_CONFIG=""
+       fi
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists.  Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+# only at the first occurence in configure.ac, so if the first place
+# it's called might be skipped (such as if it is within an "if", you
+# have to call PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+    AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+  m4_default([$2], [:])
+m4_ifvaln([$3], [else
+  $3])dnl
+fi])
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$$1"; then
+    pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+    PKG_CHECK_EXISTS([$3],
+                     [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes ],
+                    [pkg_failed=yes])
+ else
+    pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+       AC_MSG_RESULT([no])
+        _PKG_SHORT_ERRORS_SUPPORTED
+        if test $_pkg_short_errors_supported = yes; then
+               $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
+        else 
+               $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
+        fi
+       # Put the nasty error message in config.log where it belongs
+       echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+       m4_default([$4], [AC_MSG_ERROR(
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT])[]dnl
+        ])
+elif test $pkg_failed = untried; then
+       AC_MSG_RESULT([no])
+       m4_default([$4], [AC_MSG_FAILURE(
+[The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
+        ])
+else
+       $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+       $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+        AC_MSG_RESULT([yes])
+       $3
+fi[]dnl
+])# PKG_CHECK_MODULES
+
+
+# PKG_INSTALLDIR(DIRECTORY)
+# -------------------------
+# Substitutes the variable pkgconfigdir as the location where a module
+# should install pkg-config .pc files. By default the directory is
+# $libdir/pkgconfig, but the default can be changed by passing
+# DIRECTORY. The user can override through the --with-pkgconfigdir
+# parameter.
+AC_DEFUN([PKG_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+    [pkg-config installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([pkgconfigdir],
+    [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
+    [with_pkgconfigdir=]pkg_default)
+AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+]) dnl PKG_INSTALLDIR
+
+
+# PKG_NOARCH_INSTALLDIR(DIRECTORY)
+# -------------------------
+# Substitutes the variable noarch_pkgconfigdir as the location where a
+# module should install arch-independent pkg-config .pc files. By
+# default the directory is $datadir/pkgconfig, but the default can be
+# changed by passing DIRECTORY. The user can override through the
+# --with-noarch-pkgconfigdir parameter.
+AC_DEFUN([PKG_NOARCH_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+    [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([noarch-pkgconfigdir],
+    [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
+    [with_noarch_pkgconfigdir=]pkg_default)
+AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+]) dnl PKG_NOARCH_INSTALLDIR
+
+
+# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
+# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# -------------------------------------------
+# Retrieves the value of the pkg-config variable for the given module.
+AC_DEFUN([PKG_CHECK_VAR],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
+
+_PKG_CONFIG([$1], [variable="][$3]["], [$2])
+AS_VAR_COPY([$1], [pkg_cv_][$1])
+
+AS_VAR_IF([$1], [""], [$5], [$4])dnl
+])# PKG_CHECK_VAR
diff --git a/m4/po.m4 b/m4/po.m4
new file mode 100644
index 0000000..d4bc262
--- /dev/null
+++ b/m4/po.m4
@@ -0,0 +1,453 @@
+# po.m4 serial 24 (gettext-0.19)
+dnl Copyright (C) 1995-2014 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+dnl
+dnl This file can be used in projects which are not available under
+dnl the GNU General Public License or the GNU Library General Public
+dnl License but which still want to provide support for the GNU gettext
+dnl functionality.
+dnl Please note that the actual code of the GNU gettext library is covered
+dnl by the GNU Library General Public License, and the rest of the GNU
+dnl gettext package is covered by the GNU General Public License.
+dnl They are *not* in the public domain.
+
+dnl Authors:
+dnl   Ulrich Drepper <drepper cygnus com>, 1995-2000.
+dnl   Bruno Haible <haible clisp cons org>, 2000-2003.
+
+AC_PREREQ([2.60])
+
+dnl Checks for all prerequisites of the po subdirectory.
+AC_DEFUN([AM_PO_SUBDIRS],
+[
+  AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+  AC_REQUIRE([AC_PROG_INSTALL])dnl
+  AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+  AC_REQUIRE([AC_PROG_SED])dnl
+  AC_REQUIRE([AM_NLS])dnl
+
+  dnl Release version of the gettext macros. This is used to ensure that
+  dnl the gettext macros and po/Makefile.in.in are in sync.
+  AC_SUBST([GETTEXT_MACRO_VERSION], [0.19])
+
+  dnl Perform the following tests also if --disable-nls has been given,
+  dnl because they are needed for "make dist" to work.
+
+  dnl Search for GNU msgfmt in the PATH.
+  dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions.
+  dnl The second test excludes FreeBSD msgfmt.
+  AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
+    [$ac_dir/$ac_word --statistics /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 &&
+     (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else 
exit 0; fi)],
+    :)
+  AC_PATH_PROG([GMSGFMT], [gmsgfmt], [$MSGFMT])
+
+  dnl Test whether it is GNU msgfmt >= 0.15.
+changequote(,)dnl
+  case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in
+    '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;;
+    *) MSGFMT_015=$MSGFMT ;;
+  esac
+changequote([,])dnl
+  AC_SUBST([MSGFMT_015])
+changequote(,)dnl
+  case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in
+    '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;;
+    *) GMSGFMT_015=$GMSGFMT ;;
+  esac
+changequote([,])dnl
+  AC_SUBST([GMSGFMT_015])
+
+  dnl Search for GNU xgettext 0.12 or newer in the PATH.
+  dnl The first test excludes Solaris xgettext and early GNU xgettext versions.
+  dnl The second test excludes FreeBSD xgettext.
+  AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+    [$ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 
&]AS_MESSAGE_LOG_FD[ 2>&1 &&
+     (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null 
| grep usage >/dev/null; then exit 1; else exit 0; fi)],
+    :)
+  dnl Remove leftover from FreeBSD xgettext call.
+  rm -f messages.po
+
+  dnl Test whether it is GNU xgettext >= 0.15.
+changequote(,)dnl
+  case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in
+    '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;;
+    *) XGETTEXT_015=$XGETTEXT ;;
+  esac
+changequote([,])dnl
+  AC_SUBST([XGETTEXT_015])
+
+  dnl Search for GNU msgmerge 0.11 or newer in the PATH.
+  AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge,
+    [$ac_dir/$ac_word --update -q /dev/null /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1], :)
+
+  dnl Installation directories.
+  dnl Autoconf >= 2.60 defines localedir. For older versions of autoconf, we
+  dnl have to define it here, so that it can be used in po/Makefile.
+  test -n "$localedir" || localedir='${datadir}/locale'
+  AC_SUBST([localedir])
+
+  dnl Support for AM_XGETTEXT_OPTION.
+  test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS=
+  AC_SUBST([XGETTEXT_EXTRA_OPTIONS])
+
+  AC_CONFIG_COMMANDS([po-directories], [[
+    for ac_file in $CONFIG_FILES; do
+      # Support "outfile[:infile[:infile...]]"
+      case "$ac_file" in
+        *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+      esac
+      # PO directories have a Makefile.in generated from Makefile.in.in.
+      case "$ac_file" in */Makefile.in)
+        # Adjust a relative srcdir.
+        ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'`
+        ac_dir_suffix=/`echo "$ac_dir"|sed 's%^\./%%'`
+        ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'`
+        # In autoconf-2.13 it is called $ac_given_srcdir.
+        # In autoconf-2.50 it is called $srcdir.
+        test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir"
+        case "$ac_given_srcdir" in
+          .)  top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;;
+          /*) top_srcdir="$ac_given_srcdir" ;;
+          *)  top_srcdir="$ac_dots$ac_given_srcdir" ;;
+        esac
+        # Treat a directory as a PO directory if and only if it has a
+        # POTFILES.in file. This allows packages to have multiple PO
+        # directories under different names or in different locations.
+        if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then
+          rm -f "$ac_dir/POTFILES"
+          test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES"
+          gt_tab=`printf '\t'`
+          cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ${gt_tab}]*\$/d" -e "s,.*,     
$top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES"
+          POMAKEFILEDEPS="POTFILES.in"
+          # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend
+          # on $ac_dir but don't depend on user-specified configuration
+          # parameters.
+          if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then
+            # The LINGUAS file contains the set of available languages.
+            if test -n "$OBSOLETE_ALL_LINGUAS"; then
+              test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo 
"setting ALL_LINGUAS in configure.in is obsolete"
+            fi
+            ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"`
+            # Hide the ALL_LINGUAS assignment from automake < 1.5.
+            eval 'ALL_LINGUAS''=$ALL_LINGUAS_'
+            POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS"
+          else
+            # The set of available languages was given in configure.in.
+            # Hide the ALL_LINGUAS assignment from automake < 1.5.
+            eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS'
+          fi
+          # Compute POFILES
+          # as      $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po)
+          # Compute UPDATEPOFILES
+          # as      $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
+          # Compute DUMMYPOFILES
+          # as      $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
+          # Compute GMOFILES
+          # as      $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
+          case "$ac_given_srcdir" in
+            .) srcdirpre= ;;
+            *) srcdirpre='$(srcdir)/' ;;
+          esac
+          POFILES=
+          UPDATEPOFILES=
+          DUMMYPOFILES=
+          GMOFILES=
+          for lang in $ALL_LINGUAS; do
+            POFILES="$POFILES $srcdirpre$lang.po"
+            UPDATEPOFILES="$UPDATEPOFILES $lang.po-update"
+            DUMMYPOFILES="$DUMMYPOFILES $lang.nop"
+            GMOFILES="$GMOFILES $srcdirpre$lang.gmo"
+          done
+          # CATALOGS depends on both $ac_dir and the user's LINGUAS
+          # environment variable.
+          INST_LINGUAS=
+          if test -n "$ALL_LINGUAS"; then
+            for presentlang in $ALL_LINGUAS; do
+              useit=no
+              if test "%UNSET%" != "$LINGUAS"; then
+                desiredlanguages="$LINGUAS"
+              else
+                desiredlanguages="$ALL_LINGUAS"
+              fi
+              for desiredlang in $desiredlanguages; do
+                # Use the presentlang catalog if desiredlang is
+                #   a. equal to presentlang, or
+                #   b. a variant of presentlang (because in this case,
+                #      presentlang can be used as a fallback for messages
+                #      which are not translated in the desiredlang catalog).
+                case "$desiredlang" in
+                  "$presentlang"*) useit=yes;;
+                esac
+              done
+              if test $useit = yes; then
+                INST_LINGUAS="$INST_LINGUAS $presentlang"
+              fi
+            done
+          fi
+          CATALOGS=
+          if test -n "$INST_LINGUAS"; then
+            for lang in $INST_LINGUAS; do
+              CATALOGS="$CATALOGS $lang.gmo"
+            done
+          fi
+          test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile"
+          sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e 
"s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e 
"s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" 
"$ac_dir/Makefile.in" > "$ac_dir/Makefile"
+          for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do
+            if test -f "$f"; then
+              case "$f" in
+                *.orig | *.bak | *~) ;;
+                *) cat "$f" >> "$ac_dir/Makefile" ;;
+              esac
+            fi
+          done
+        fi
+        ;;
+      esac
+    done]],
+   [# Capture the value of obsolete ALL_LINGUAS because we need it to compute
+    # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it
+    # from automake < 1.5.
+    eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"'
+    # Capture the value of LINGUAS because we need it to compute CATALOGS.
+    LINGUAS="${LINGUAS-%UNSET%}"
+   ])
+])
+
+dnl Postprocesses a Makefile in a directory containing PO files.
+AC_DEFUN([AM_POSTPROCESS_PO_MAKEFILE],
+[
+  # When this code is run, in config.status, two variables have already been
+  # set:
+  # - OBSOLETE_ALL_LINGUAS is the value of LINGUAS set in configure.in,
+  # - LINGUAS is the value of the environment variable LINGUAS at configure
+  #   time.
+
+changequote(,)dnl
+  # Adjust a relative srcdir.
+  ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'`
+  ac_dir_suffix=/`echo "$ac_dir"|sed 's%^\./%%'`
+  ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'`
+  # In autoconf-2.13 it is called $ac_given_srcdir.
+  # In autoconf-2.50 it is called $srcdir.
+  test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir"
+  case "$ac_given_srcdir" in
+    .)  top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;;
+    /*) top_srcdir="$ac_given_srcdir" ;;
+    *)  top_srcdir="$ac_dots$ac_given_srcdir" ;;
+  esac
+
+  # Find a way to echo strings without interpreting backslash.
+  if test "X`(echo '\t') 2>/dev/null`" = 'X\t'; then
+    gt_echo='echo'
+  else
+    if test "X`(printf '%s\n' '\t') 2>/dev/null`" = 'X\t'; then
+      gt_echo='printf %s\n'
+    else
+      echo_func () {
+        cat <<EOT
+$*
+EOT
+      }
+      gt_echo='echo_func'
+    fi
+  fi
+
+  # A sed script that extracts the value of VARIABLE from a Makefile.
+  tab=`printf '\t'`
+  sed_x_variable='
+# Test if the hold space is empty.
+x
+s/P/P/
+x
+ta
+# Yes it was empty. Look if we have the expected variable definition.
+/^['"${tab}"' ]*VARIABLE['"${tab}"' ]*=/{
+  # Seen the first line of the variable definition.
+  s/^['"${tab}"' ]*VARIABLE['"${tab}"' ]*=//
+  ba
+}
+bd
+:a
+# Here we are processing a line from the variable definition.
+# Remove comment, more precisely replace it with a space.
+s/#.*$/ /
+# See if the line ends in a backslash.
+tb
+:b
+s/\\$//
+# Print the line, without the trailing backslash.
+p
+tc
+# There was no trailing backslash. The end of the variable definition is
+# reached. Clear the hold space.
+s/^.*$//
+x
+bd
+:c
+# A trailing backslash means that the variable definition continues in the
+# next line. Put a nonempty string into the hold space to indicate this.
+s/^.*$/P/
+x
+:d
+'
+changequote([,])dnl
+
+  # Set POTFILES to the value of the Makefile variable POTFILES.
+  sed_x_POTFILES=`$gt_echo "$sed_x_variable" | sed -e '/^ *#/d' -e 's/VARIABLE/POTFILES/g'`
+  POTFILES=`sed -n -e "$sed_x_POTFILES" < "$ac_file"`
+  # Compute POTFILES_DEPS as
+  #   $(foreach file, $(POTFILES), $(top_srcdir)/$(file))
+  POTFILES_DEPS=
+  for file in $POTFILES; do
+    POTFILES_DEPS="$POTFILES_DEPS "'$(top_srcdir)/'"$file"
+  done
+  POMAKEFILEDEPS=""
+
+  if test -n "$OBSOLETE_ALL_LINGUAS"; then
+    test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting 
ALL_LINGUAS in configure.in is obsolete"
+  fi
+  if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then
+    # The LINGUAS file contains the set of available languages.
+    ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"`
+    POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS"
+  else
+    # Set ALL_LINGUAS to the value of the Makefile variable LINGUAS.
+    sed_x_LINGUAS=`$gt_echo "$sed_x_variable" | sed -e '/^ *#/d' -e 's/VARIABLE/LINGUAS/g'`
+    ALL_LINGUAS_=`sed -n -e "$sed_x_LINGUAS" < "$ac_file"`
+  fi
+  # Hide the ALL_LINGUAS assignment from automake < 1.5.
+  eval 'ALL_LINGUAS''=$ALL_LINGUAS_'
+  # Compute POFILES
+  # as      $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po)
+  # Compute UPDATEPOFILES
+  # as      $(foreach lang, $(ALL_LINGUAS), $(lang).po-update)
+  # Compute DUMMYPOFILES
+  # as      $(foreach lang, $(ALL_LINGUAS), $(lang).nop)
+  # Compute GMOFILES
+  # as      $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo)
+  # Compute PROPERTIESFILES
+  # as      $(foreach lang, $(ALL_LINGUAS), $(top_srcdir)/$(DOMAIN)_$(lang).properties)
+  # Compute CLASSFILES
+  # as      $(foreach lang, $(ALL_LINGUAS), $(top_srcdir)/$(DOMAIN)_$(lang).class)
+  # Compute QMFILES
+  # as      $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).qm)
+  # Compute MSGFILES
+  # as      $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(frob $(lang)).msg)
+  # Compute RESOURCESDLLFILES
+  # as      $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(frob $(lang))/$(DOMAIN).resources.dll)
+  case "$ac_given_srcdir" in
+    .) srcdirpre= ;;
+    *) srcdirpre='$(srcdir)/' ;;
+  esac
+  POFILES=
+  UPDATEPOFILES=
+  DUMMYPOFILES=
+  GMOFILES=
+  PROPERTIESFILES=
+  CLASSFILES=
+  QMFILES=
+  MSGFILES=
+  RESOURCESDLLFILES=
+  for lang in $ALL_LINGUAS; do
+    POFILES="$POFILES $srcdirpre$lang.po"
+    UPDATEPOFILES="$UPDATEPOFILES $lang.po-update"
+    DUMMYPOFILES="$DUMMYPOFILES $lang.nop"
+    GMOFILES="$GMOFILES $srcdirpre$lang.gmo"
+    PROPERTIESFILES="$PROPERTIESFILES \$(top_srcdir)/\$(DOMAIN)_$lang.properties"
+    CLASSFILES="$CLASSFILES \$(top_srcdir)/\$(DOMAIN)_$lang.class"
+    QMFILES="$QMFILES $srcdirpre$lang.qm"
+    frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 
'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
+    MSGFILES="$MSGFILES $srcdirpre$frobbedlang.msg"
+    frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 
's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'`
+    RESOURCESDLLFILES="$RESOURCESDLLFILES $srcdirpre$frobbedlang/\$(DOMAIN).resources.dll"
+  done
+  # CATALOGS depends on both $ac_dir and the user's LINGUAS
+  # environment variable.
+  INST_LINGUAS=
+  if test -n "$ALL_LINGUAS"; then
+    for presentlang in $ALL_LINGUAS; do
+      useit=no
+      if test "%UNSET%" != "$LINGUAS"; then
+        desiredlanguages="$LINGUAS"
+      else
+        desiredlanguages="$ALL_LINGUAS"
+      fi
+      for desiredlang in $desiredlanguages; do
+        # Use the presentlang catalog if desiredlang is
+        #   a. equal to presentlang, or
+        #   b. a variant of presentlang (because in this case,
+        #      presentlang can be used as a fallback for messages
+        #      which are not translated in the desiredlang catalog).
+        case "$desiredlang" in
+          "$presentlang"*) useit=yes;;
+        esac
+      done
+      if test $useit = yes; then
+        INST_LINGUAS="$INST_LINGUAS $presentlang"
+      fi
+    done
+  fi
+  CATALOGS=
+  JAVACATALOGS=
+  QTCATALOGS=
+  TCLCATALOGS=
+  CSHARPCATALOGS=
+  if test -n "$INST_LINGUAS"; then
+    for lang in $INST_LINGUAS; do
+      CATALOGS="$CATALOGS $lang.gmo"
+      JAVACATALOGS="$JAVACATALOGS \$(DOMAIN)_$lang.properties"
+      QTCATALOGS="$QTCATALOGS $lang.qm"
+      frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 
'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
+      TCLCATALOGS="$TCLCATALOGS $frobbedlang.msg"
+      frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 
's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'`
+      CSHARPCATALOGS="$CSHARPCATALOGS $frobbedlang/\$(DOMAIN).resources.dll"
+    done
+  fi
+
+  sed -e "s|@POTFILES_DEPS@|$POTFILES_DEPS|g" -e "s|@POFILES@|$POFILES|g" -e 
"s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e 
"s|@PROPERTIESFILES@|$PROPERTIESFILES|g" -e "s|@CLASSFILES@|$CLASSFILES|g" -e "s|@QMFILES@|$QMFILES|g" -e 
"s|@MSGFILES@|$MSGFILES|g" -e "s|@RESOURCESDLLFILES@|$RESOURCESDLLFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e 
"s|@JAVACATALOGS@|$JAVACATALOGS|g" -e "s|@QTCATALOGS@|$QTCATALOGS|g" -e "s|@TCLCATALOGS@|$TCLCATALOGS|g" -e 
"s|@CSHARPCATALOGS@|$CSHARPCATALOGS|g" -e 's,^#distdir:,distdir:,' < "$ac_file" > "$ac_file.tmp"
+  tab=`printf '\t'`
+  if grep -l '@TCLCATALOGS@' "$ac_file" > /dev/null; then
+    # Add dependencies that cannot be formulated as a simple suffix rule.
+    for lang in $ALL_LINGUAS; do
+      frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 
'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
+      cat >> "$ac_file.tmp" <<EOF
+$frobbedlang.msg: $lang.po
+${tab} echo "\$(MSGFMT) -c --tcl -d \$(srcdir) -l $lang $srcdirpre$lang.po"; \
+${tab}\$(MSGFMT) -c --tcl -d "\$(srcdir)" -l $lang $srcdirpre$lang.po || { rm -f 
"\$(srcdir)/$frobbedlang.msg"; exit 1; }
+EOF
+    done
+  fi
+  if grep -l '@CSHARPCATALOGS@' "$ac_file" > /dev/null; then
+    # Add dependencies that cannot be formulated as a simple suffix rule.
+    for lang in $ALL_LINGUAS; do
+      frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 
's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'`
+      cat >> "$ac_file.tmp" <<EOF
+$frobbedlang/\$(DOMAIN).resources.dll: $lang.po
+${tab} echo "\$(MSGFMT) -c --csharp -d \$(srcdir) -l $lang $srcdirpre$lang.po -r \$(DOMAIN)"; \
+${tab}\$(MSGFMT) -c --csharp -d "\$(srcdir)" -l $lang $srcdirpre$lang.po -r "\$(DOMAIN)" || { rm -f 
"\$(srcdir)/$frobbedlang.msg"; exit 1; }
+EOF
+    done
+  fi
+  if test -n "$POMAKEFILEDEPS"; then
+    cat >> "$ac_file.tmp" <<EOF
+Makefile: $POMAKEFILEDEPS
+EOF
+  fi
+  mv "$ac_file.tmp" "$ac_file"
+])
+
+dnl Initializes the accumulator used by AM_XGETTEXT_OPTION.
+AC_DEFUN([AM_XGETTEXT_OPTION_INIT],
+[
+  XGETTEXT_EXTRA_OPTIONS=
+])
+
+dnl Registers an option to be passed to xgettext in the po subdirectory.
+AC_DEFUN([AM_XGETTEXT_OPTION],
+[
+  AC_REQUIRE([AM_XGETTEXT_OPTION_INIT])
+  XGETTEXT_EXTRA_OPTIONS="$XGETTEXT_EXTRA_OPTIONS $1"
+])
diff --git a/m4/printf-posix.m4 b/m4/printf-posix.m4
new file mode 100644
index 0000000..0f85ad6
--- /dev/null
+++ b/m4/printf-posix.m4
@@ -0,0 +1,48 @@
+# printf-posix.m4 serial 6 (gettext-0.18.2)
+dnl Copyright (C) 2003, 2007, 2009-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+dnl Test whether the printf() function supports POSIX/XSI format strings with
+dnl positions.
+
+AC_DEFUN([gt_PRINTF_POSIX],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_CACHE_CHECK([whether printf() supports POSIX/XSI format strings],
+    gt_cv_func_printf_posix,
+    [
+      AC_RUN_IFELSE(
+        [AC_LANG_SOURCE([[
+#include <stdio.h>
+#include <string.h>
+/* The string "%2$d %1$d", with dollar characters protected from the shell's
+   dollar expansion (possibly an autoconf bug).  */
+static char format[] = { '%', '2', '$', 'd', ' ', '%', '1', '$', 'd', '\0' };
+static char buf[100];
+int main ()
+{
+  sprintf (buf, format, 33, 55);
+  return (strcmp (buf, "55 33") != 0);
+}]])],
+        [gt_cv_func_printf_posix=yes],
+        [gt_cv_func_printf_posix=no],
+        [
+          AC_EGREP_CPP([notposix], [
+#if defined __NetBSD__ || defined __BEOS__ || defined _MSC_VER || defined __MINGW32__ || defined __CYGWIN__
+  notposix
+#endif
+            ],
+            [gt_cv_func_printf_posix="guessing no"],
+            [gt_cv_func_printf_posix="guessing yes"])
+        ])
+    ])
+  case $gt_cv_func_printf_posix in
+    *yes)
+      AC_DEFINE([HAVE_POSIX_PRINTF], [1],
+        [Define if your printf() function supports format strings with positions.])
+      ;;
+  esac
+])
diff --git a/m4/progtest.m4 b/m4/progtest.m4
new file mode 100644
index 0000000..0921e1e
--- /dev/null
+++ b/m4/progtest.m4
@@ -0,0 +1,91 @@
+# progtest.m4 serial 7 (gettext-0.18.2)
+dnl Copyright (C) 1996-2003, 2005, 2008-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+dnl
+dnl This file can be used in projects which are not available under
+dnl the GNU General Public License or the GNU Library General Public
+dnl License but which still want to provide support for the GNU gettext
+dnl functionality.
+dnl Please note that the actual code of the GNU gettext library is covered
+dnl by the GNU Library General Public License, and the rest of the GNU
+dnl gettext package is covered by the GNU General Public License.
+dnl They are *not* in the public domain.
+
+dnl Authors:
+dnl   Ulrich Drepper <drepper cygnus com>, 1996.
+
+AC_PREREQ([2.50])
+
+# Search path for a program which passes the given test.
+
+dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR,
+dnl   TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]])
+AC_DEFUN([AM_PATH_PROG_WITH_TEST],
+[
+# Prepare PATH_SEPARATOR.
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which
+  # contains only /bin. Note that ksh looks also at the FPATH variable,
+  # so we have to set that as well for the test.
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \
+    && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \
+           || PATH_SEPARATOR=';'
+       }
+fi
+
+# Find out how to test for executable files. Don't use a zero-byte file,
+# as systems may use methods other than mode bits to determine executability.
+cat >conf$$.file <<_ASEOF
+#! /bin/sh
+exit 0
+_ASEOF
+chmod +x conf$$.file
+if test -x conf$$.file >/dev/null 2>&1; then
+  ac_executable_p="test -x"
+else
+  ac_executable_p="test -f"
+fi
+rm -f conf$$.file
+
+# Extract the first word of "$2", so it can be a program name with args.
+set dummy $2; ac_word=[$]2
+AC_MSG_CHECKING([for $ac_word])
+AC_CACHE_VAL([ac_cv_path_$1],
+[case "[$]$1" in
+  [[\\/]]* | ?:[[\\/]]*)
+    ac_cv_path_$1="[$]$1" # Let the user override the test with a path.
+    ;;
+  *)
+    ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR
+    for ac_dir in ifelse([$5], , $PATH, [$5]); do
+      IFS="$ac_save_IFS"
+      test -z "$ac_dir" && ac_dir=.
+      for ac_exec_ext in '' $ac_executable_extensions; do
+        if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then
+          echo "$as_me: trying $ac_dir/$ac_word..." >&AS_MESSAGE_LOG_FD
+          if [$3]; then
+            ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext"
+            break 2
+          fi
+        fi
+      done
+    done
+    IFS="$ac_save_IFS"
+dnl If no 4th arg is given, leave the cache variable unset,
+dnl so AC_PATH_PROGS will keep looking.
+ifelse([$4], , , [  test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4"
+])dnl
+    ;;
+esac])dnl
+$1="$ac_cv_path_$1"
+if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then
+  AC_MSG_RESULT([$][$1])
+else
+  AC_MSG_RESULT([no])
+fi
+AC_SUBST([$1])dnl
+])
diff --git a/m4/size_max.m4 b/m4/size_max.m4
new file mode 100644
index 0000000..186e3fd
--- /dev/null
+++ b/m4/size_max.m4
@@ -0,0 +1,79 @@
+# size_max.m4 serial 10
+dnl Copyright (C) 2003, 2005-2006, 2008-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_DEFUN([gl_SIZE_MAX],
+[
+  AC_CHECK_HEADERS([stdint.h])
+  dnl First test whether the system already has SIZE_MAX.
+  AC_CACHE_CHECK([for SIZE_MAX], [gl_cv_size_max], [
+    gl_cv_size_max=
+    AC_EGREP_CPP([Found it], [
+#include <limits.h>
+#if HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef SIZE_MAX
+Found it
+#endif
+], [gl_cv_size_max=yes])
+    if test -z "$gl_cv_size_max"; then
+      dnl Define it ourselves. Here we assume that the type 'size_t' is not wider
+      dnl than the type 'unsigned long'. Try hard to find a definition that can
+      dnl be used in a preprocessor #if, i.e. doesn't contain a cast.
+      AC_COMPUTE_INT([size_t_bits_minus_1], [sizeof (size_t) * CHAR_BIT - 1],
+        [#include <stddef.h>
+#include <limits.h>], [size_t_bits_minus_1=])
+      AC_COMPUTE_INT([fits_in_uint], [sizeof (size_t) <= sizeof (unsigned int)],
+        [#include <stddef.h>], [fits_in_uint=])
+      if test -n "$size_t_bits_minus_1" && test -n "$fits_in_uint"; then
+        if test $fits_in_uint = 1; then
+          dnl Even though SIZE_MAX fits in an unsigned int, it must be of type
+          dnl 'unsigned long' if the type 'size_t' is the same as 'unsigned long'.
+          AC_COMPILE_IFELSE(
+            [AC_LANG_PROGRAM(
+               [[#include <stddef.h>
+                 extern size_t foo;
+                 extern unsigned long foo;
+               ]],
+               [[]])],
+            [fits_in_uint=0])
+        fi
+        dnl We cannot use 'expr' to simplify this expression, because 'expr'
+        dnl works only with 'long' integers in the host environment, while we
+        dnl might be cross-compiling from a 32-bit platform to a 64-bit platform.
+        if test $fits_in_uint = 1; then
+          gl_cv_size_max="(((1U << $size_t_bits_minus_1) - 1) * 2 + 1)"
+        else
+          gl_cv_size_max="(((1UL << $size_t_bits_minus_1) - 1) * 2 + 1)"
+        fi
+      else
+        dnl Shouldn't happen, but who knows...
+        gl_cv_size_max='((size_t)~(size_t)0)'
+      fi
+    fi
+  ])
+  if test "$gl_cv_size_max" != yes; then
+    AC_DEFINE_UNQUOTED([SIZE_MAX], [$gl_cv_size_max],
+      [Define as the maximum value of type 'size_t', if the system doesn't define it.])
+  fi
+  dnl Don't redefine SIZE_MAX in config.h if config.h is re-included after
+  dnl <stdint.h>. Remember that the #undef in AH_VERBATIM gets replaced with
+  dnl #define by AC_DEFINE_UNQUOTED.
+  AH_VERBATIM([SIZE_MAX],
+[/* Define as the maximum value of type 'size_t', if the system doesn't define
+   it. */
+#ifndef SIZE_MAX
+# undef SIZE_MAX
+#endif])
+])
+
+dnl Autoconf >= 2.61 has AC_COMPUTE_INT built-in.
+dnl Remove this when we can assume autoconf >= 2.61.
+m4_ifdef([AC_COMPUTE_INT], [], [
+  AC_DEFUN([AC_COMPUTE_INT], [_AC_COMPUTE_INT([$2],[$1],[$3],[$4])])
+])
diff --git a/m4/stdint_h.m4 b/m4/stdint_h.m4
new file mode 100644
index 0000000..5097c0b
--- /dev/null
+++ b/m4/stdint_h.m4
@@ -0,0 +1,27 @@
+# stdint_h.m4 serial 9
+dnl Copyright (C) 1997-2004, 2006, 2008-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Paul Eggert.
+
+# Define HAVE_STDINT_H_WITH_UINTMAX if <stdint.h> exists,
+# doesn't clash with <sys/types.h>, and declares uintmax_t.
+
+AC_DEFUN([gl_AC_HEADER_STDINT_H],
+[
+  AC_CACHE_CHECK([for stdint.h], [gl_cv_header_stdint_h],
+    [AC_COMPILE_IFELSE(
+       [AC_LANG_PROGRAM(
+          [[#include <sys/types.h>
+            #include <stdint.h>]],
+          [[uintmax_t i = (uintmax_t) -1; return !i;]])],
+       [gl_cv_header_stdint_h=yes],
+       [gl_cv_header_stdint_h=no])])
+  if test $gl_cv_header_stdint_h = yes; then
+    AC_DEFINE_UNQUOTED([HAVE_STDINT_H_WITH_UINTMAX], [1],
+      [Define if <stdint.h> exists, doesn't clash with <sys/types.h>,
+       and declares uintmax_t. ])
+  fi
+])
diff --git a/m4/threadlib.m4 b/m4/threadlib.m4
new file mode 100644
index 0000000..8615ac9
--- /dev/null
+++ b/m4/threadlib.m4
@@ -0,0 +1,389 @@
+# threadlib.m4 serial 11 (gettext-0.18.2)
+dnl Copyright (C) 2005-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+dnl gl_THREADLIB
+dnl ------------
+dnl Tests for a multithreading library to be used.
+dnl If the configure.ac contains a definition of the gl_THREADLIB_DEFAULT_NO
+dnl (it must be placed before the invocation of gl_THREADLIB_EARLY!), then the
+dnl default is 'no', otherwise it is system dependent. In both cases, the user
+dnl can change the choice through the options --enable-threads=choice or
+dnl --disable-threads.
+dnl Defines at most one of the macros USE_POSIX_THREADS, USE_SOLARIS_THREADS,
+dnl USE_PTH_THREADS, USE_WINDOWS_THREADS
+dnl Sets the variables LIBTHREAD and LTLIBTHREAD to the linker options for use
+dnl in a Makefile (LIBTHREAD for use without libtool, LTLIBTHREAD for use with
+dnl libtool).
+dnl Sets the variables LIBMULTITHREAD and LTLIBMULTITHREAD similarly, for
+dnl programs that really need multithread functionality. The difference
+dnl between LIBTHREAD and LIBMULTITHREAD is that on platforms supporting weak
+dnl symbols, typically LIBTHREAD is empty whereas LIBMULTITHREAD is not.
+dnl Adds to CPPFLAGS the flag -D_REENTRANT or -D_THREAD_SAFE if needed for
+dnl multithread-safe programs.
+
+AC_DEFUN([gl_THREADLIB_EARLY],
+[
+  AC_REQUIRE([gl_THREADLIB_EARLY_BODY])
+])
+
+dnl The guts of gl_THREADLIB_EARLY. Needs to be expanded only once.
+
+AC_DEFUN([gl_THREADLIB_EARLY_BODY],
+[
+  dnl Ordering constraints: This macro modifies CPPFLAGS in a way that
+  dnl influences the result of the autoconf tests that test for *_unlocked
+  dnl declarations, on AIX 5 at least. Therefore it must come early.
+  AC_BEFORE([$0], [gl_FUNC_GLIBC_UNLOCKED_IO])dnl
+  AC_BEFORE([$0], [gl_ARGP])dnl
+
+  AC_REQUIRE([AC_CANONICAL_HOST])
+  dnl _GNU_SOURCE is needed for pthread_rwlock_t on glibc systems.
+  dnl AC_USE_SYSTEM_EXTENSIONS was introduced in autoconf 2.60 and obsoletes
+  dnl AC_GNU_SOURCE.
+  m4_ifdef([AC_USE_SYSTEM_EXTENSIONS],
+    [AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])],
+    [AC_REQUIRE([AC_GNU_SOURCE])])
+  dnl Check for multithreading.
+  m4_ifdef([gl_THREADLIB_DEFAULT_NO],
+    [m4_divert_text([DEFAULTS], [gl_use_threads_default=no])],
+    [m4_divert_text([DEFAULTS], [gl_use_threads_default=])])
+  AC_ARG_ENABLE([threads],
+AC_HELP_STRING([--enable-threads={posix|solaris|pth|windows}], [specify multithreading 
API])m4_ifdef([gl_THREADLIB_DEFAULT_NO], [], [
+AC_HELP_STRING([--disable-threads], [build without multithread safety])]),
+    [gl_use_threads=$enableval],
+    [if test -n "$gl_use_threads_default"; then
+       gl_use_threads="$gl_use_threads_default"
+     else
+changequote(,)dnl
+       case "$host_os" in
+         dnl Disable multithreading by default on OSF/1, because it interferes
+         dnl with fork()/exec(): When msgexec is linked with -lpthread, its
+         dnl child process gets an endless segmentation fault inside execvp().
+         dnl Disable multithreading by default on Cygwin 1.5.x, because it has
+         dnl bugs that lead to endless loops or crashes. See
+         dnl <http://cygwin.com/ml/cygwin/2009-08/msg00283.html>.
+         osf*) gl_use_threads=no ;;
+         cygwin*)
+               case `uname -r` in
+                 1.[0-5].*) gl_use_threads=no ;;
+                 *)         gl_use_threads=yes ;;
+               esac
+               ;;
+         *)    gl_use_threads=yes ;;
+       esac
+changequote([,])dnl
+     fi
+    ])
+  if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then
+    # For using <pthread.h>:
+    case "$host_os" in
+      osf*)
+        # On OSF/1, the compiler needs the flag -D_REENTRANT so that it
+        # groks <pthread.h>. cc also understands the flag -pthread, but
+        # we don't use it because 1. gcc-2.95 doesn't understand -pthread,
+        # 2. putting a flag into CPPFLAGS that has an effect on the linker
+        # causes the AC_LINK_IFELSE test below to succeed unexpectedly,
+        # leading to wrong values of LIBTHREAD and LTLIBTHREAD.
+        CPPFLAGS="$CPPFLAGS -D_REENTRANT"
+        ;;
+    esac
+    # Some systems optimize for single-threaded programs by default, and
+    # need special flags to disable these optimizations. For example, the
+    # definition of 'errno' in <errno.h>.
+    case "$host_os" in
+      aix* | freebsd*) CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" ;;
+      solaris*) CPPFLAGS="$CPPFLAGS -D_REENTRANT" ;;
+    esac
+  fi
+])
+
+dnl The guts of gl_THREADLIB. Needs to be expanded only once.
+
+AC_DEFUN([gl_THREADLIB_BODY],
+[
+  AC_REQUIRE([gl_THREADLIB_EARLY_BODY])
+  gl_threads_api=none
+  LIBTHREAD=
+  LTLIBTHREAD=
+  LIBMULTITHREAD=
+  LTLIBMULTITHREAD=
+  if test "$gl_use_threads" != no; then
+    dnl Check whether the compiler and linker support weak declarations.
+    AC_CACHE_CHECK([whether imported symbols can be declared weak],
+      [gl_cv_have_weak],
+      [gl_cv_have_weak=no
+       dnl First, test whether the compiler accepts it syntactically.
+       AC_LINK_IFELSE(
+         [AC_LANG_PROGRAM(
+            [[extern void xyzzy ();
+#pragma weak xyzzy]],
+            [[xyzzy();]])],
+         [gl_cv_have_weak=maybe])
+       if test $gl_cv_have_weak = maybe; then
+         dnl Second, test whether it actually works. On Cygwin 1.7.2, with
+         dnl gcc 4.3, symbols declared weak always evaluate to the address 0.
+         AC_RUN_IFELSE(
+           [AC_LANG_SOURCE([[
+#include <stdio.h>
+#pragma weak fputs
+int main ()
+{
+  return (fputs == NULL);
+}]])],
+           [gl_cv_have_weak=yes],
+           [gl_cv_have_weak=no],
+           [dnl When cross-compiling, assume that only ELF platforms support
+            dnl weak symbols.
+            AC_EGREP_CPP([Extensible Linking Format],
+              [#ifdef __ELF__
+               Extensible Linking Format
+               #endif
+              ],
+              [gl_cv_have_weak="guessing yes"],
+              [gl_cv_have_weak="guessing no"])
+           ])
+       fi
+      ])
+    if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then
+      # On OSF/1, the compiler needs the flag -pthread or -D_REENTRANT so that
+      # it groks <pthread.h>. It's added above, in gl_THREADLIB_EARLY_BODY.
+      AC_CHECK_HEADER([pthread.h],
+        [gl_have_pthread_h=yes], [gl_have_pthread_h=no])
+      if test "$gl_have_pthread_h" = yes; then
+        # Other possible tests:
+        #   -lpthreads (FSU threads, PCthreads)
+        #   -lgthreads
+        gl_have_pthread=
+        # Test whether both pthread_mutex_lock and pthread_mutexattr_init exist
+        # in libc. IRIX 6.5 has the first one in both libc and libpthread, but
+        # the second one only in libpthread, and lock.c needs it.
+        #
+        # If -pthread works, prefer it to -lpthread, since Ubuntu 14.04
+        # needs -pthread for some reason.  See:
+        # http://lists.gnu.org/archive/html/bug-gnulib/2014-09/msg00023.html
+        save_LIBS=$LIBS
+        for gl_pthread in '' '-pthread'; do
+          LIBS="$LIBS $gl_pthread"
+          AC_LINK_IFELSE(
+            [AC_LANG_PROGRAM(
+               [[#include <pthread.h>
+                 pthread_mutex_t m;
+                 pthread_mutexattr_t ma;
+               ]],
+               [[pthread_mutex_lock (&m);
+                 pthread_mutexattr_init (&ma);]])],
+            [gl_have_pthread=yes
+             LIBTHREAD=$gl_pthread LTLIBTHREAD=$gl_pthread
+             LIBMULTITHREAD=$gl_pthread LTLIBMULTITHREAD=$gl_pthread])
+          LIBS=$save_LIBS
+          test -n "$gl_have_pthread" && break
+        done
+
+        # Test for libpthread by looking for pthread_kill. (Not pthread_self,
+        # since it is defined as a macro on OSF/1.)
+        if test -n "$gl_have_pthread" && test -z "$LIBTHREAD"; then
+          # The program links fine without libpthread. But it may actually
+          # need to link with libpthread in order to create multiple threads.
+          AC_CHECK_LIB([pthread], [pthread_kill],
+            [LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread
+             # On Solaris and HP-UX, most pthread functions exist also in libc.
+             # Therefore pthread_in_use() needs to actually try to create a
+             # thread: pthread_create from libc will fail, whereas
+             # pthread_create will actually create a thread.
+             case "$host_os" in
+               solaris* | hpux*)
+                 AC_DEFINE([PTHREAD_IN_USE_DETECTION_HARD], [1],
+                   [Define if the pthread_in_use() detection is hard.])
+             esac
+            ])
+        elif test -z "$gl_have_pthread"; then
+          # Some library is needed. Try libpthread and libc_r.
+          AC_CHECK_LIB([pthread], [pthread_kill],
+            [gl_have_pthread=yes
+             LIBTHREAD=-lpthread LTLIBTHREAD=-lpthread
+             LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread])
+          if test -z "$gl_have_pthread"; then
+            # For FreeBSD 4.
+            AC_CHECK_LIB([c_r], [pthread_kill],
+              [gl_have_pthread=yes
+               LIBTHREAD=-lc_r LTLIBTHREAD=-lc_r
+               LIBMULTITHREAD=-lc_r LTLIBMULTITHREAD=-lc_r])
+          fi
+        fi
+        if test -n "$gl_have_pthread"; then
+          gl_threads_api=posix
+          AC_DEFINE([USE_POSIX_THREADS], [1],
+            [Define if the POSIX multithreading library can be used.])
+          if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then
+            if case "$gl_cv_have_weak" in *yes) true;; *) false;; esac; then
+              AC_DEFINE([USE_POSIX_THREADS_WEAK], [1],
+                [Define if references to the POSIX multithreading library should be made weak.])
+              LIBTHREAD=
+              LTLIBTHREAD=
+            fi
+          fi
+        fi
+      fi
+    fi
+    if test -z "$gl_have_pthread"; then
+      if test "$gl_use_threads" = yes || test "$gl_use_threads" = solaris; then
+        gl_have_solaristhread=
+        gl_save_LIBS="$LIBS"
+        LIBS="$LIBS -lthread"
+        AC_LINK_IFELSE(
+          [AC_LANG_PROGRAM(
+             [[
+#include <thread.h>
+#include <synch.h>
+             ]],
+             [[thr_self();]])],
+          [gl_have_solaristhread=yes])
+        LIBS="$gl_save_LIBS"
+        if test -n "$gl_have_solaristhread"; then
+          gl_threads_api=solaris
+          LIBTHREAD=-lthread
+          LTLIBTHREAD=-lthread
+          LIBMULTITHREAD="$LIBTHREAD"
+          LTLIBMULTITHREAD="$LTLIBTHREAD"
+          AC_DEFINE([USE_SOLARIS_THREADS], [1],
+            [Define if the old Solaris multithreading library can be used.])
+          if case "$gl_cv_have_weak" in *yes) true;; *) false;; esac; then
+            AC_DEFINE([USE_SOLARIS_THREADS_WEAK], [1],
+              [Define if references to the old Solaris multithreading library should be made weak.])
+            LIBTHREAD=
+            LTLIBTHREAD=
+          fi
+        fi
+      fi
+    fi
+    if test "$gl_use_threads" = pth; then
+      gl_save_CPPFLAGS="$CPPFLAGS"
+      AC_LIB_LINKFLAGS([pth])
+      gl_have_pth=
+      gl_save_LIBS="$LIBS"
+      LIBS="$LIBS $LIBPTH"
+      AC_LINK_IFELSE(
+        [AC_LANG_PROGRAM([[#include <pth.h>]], [[pth_self();]])],
+        [gl_have_pth=yes])
+      LIBS="$gl_save_LIBS"
+      if test -n "$gl_have_pth"; then
+        gl_threads_api=pth
+        LIBTHREAD="$LIBPTH"
+        LTLIBTHREAD="$LTLIBPTH"
+        LIBMULTITHREAD="$LIBTHREAD"
+        LTLIBMULTITHREAD="$LTLIBTHREAD"
+        AC_DEFINE([USE_PTH_THREADS], [1],
+          [Define if the GNU Pth multithreading library can be used.])
+        if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then
+          if case "$gl_cv_have_weak" in *yes) true;; *) false;; esac; then
+            AC_DEFINE([USE_PTH_THREADS_WEAK], [1],
+              [Define if references to the GNU Pth multithreading library should be made weak.])
+            LIBTHREAD=
+            LTLIBTHREAD=
+          fi
+        fi
+      else
+        CPPFLAGS="$gl_save_CPPFLAGS"
+      fi
+    fi
+    if test -z "$gl_have_pthread"; then
+      case "$gl_use_threads" in
+        yes | windows | win32) # The 'win32' is for backward compatibility.
+          if { case "$host_os" in
+                 mingw*) true;;
+                 *) false;;
+               esac
+             }; then
+            gl_threads_api=windows
+            AC_DEFINE([USE_WINDOWS_THREADS], [1],
+              [Define if the native Windows multithreading API can be used.])
+          fi
+          ;;
+      esac
+    fi
+  fi
+  AC_MSG_CHECKING([for multithread API to use])
+  AC_MSG_RESULT([$gl_threads_api])
+  AC_SUBST([LIBTHREAD])
+  AC_SUBST([LTLIBTHREAD])
+  AC_SUBST([LIBMULTITHREAD])
+  AC_SUBST([LTLIBMULTITHREAD])
+])
+
+AC_DEFUN([gl_THREADLIB],
+[
+  AC_REQUIRE([gl_THREADLIB_EARLY])
+  AC_REQUIRE([gl_THREADLIB_BODY])
+])
+
+
+dnl gl_DISABLE_THREADS
+dnl ------------------
+dnl Sets the gl_THREADLIB default so that threads are not used by default.
+dnl The user can still override it at installation time, by using the
+dnl configure option '--enable-threads'.
+
+AC_DEFUN([gl_DISABLE_THREADS], [
+  m4_divert_text([INIT_PREPARE], [gl_use_threads_default=no])
+])
+
+
+dnl Survey of platforms:
+dnl
+dnl Platform           Available  Compiler    Supports   test-lock
+dnl                    flavours   option      weak       result
+dnl ---------------    ---------  ---------   --------   ---------
+dnl Linux 2.4/glibc    posix      -lpthread       Y      OK
+dnl
+dnl GNU Hurd/glibc     posix
+dnl
+dnl Ubuntu 14.04       posix      -pthread        Y      OK
+dnl
+dnl FreeBSD 5.3        posix      -lc_r           Y
+dnl                    posix      -lkse ?         Y
+dnl                    posix      -lpthread ?     Y
+dnl                    posix      -lthr           Y
+dnl
+dnl FreeBSD 5.2        posix      -lc_r           Y
+dnl                    posix      -lkse           Y
+dnl                    posix      -lthr           Y
+dnl
+dnl FreeBSD 4.0,4.10   posix      -lc_r           Y      OK
+dnl
+dnl NetBSD 1.6         --
+dnl
+dnl OpenBSD 3.4        posix      -lpthread       Y      OK
+dnl
+dnl Mac OS X 10.[123]  posix      -lpthread       Y      OK
+dnl
+dnl Solaris 7,8,9      posix      -lpthread       Y      Sol 7,8: 0.0; Sol 9: OK
+dnl                    solaris    -lthread        Y      Sol 7,8: 0.0; Sol 9: OK
+dnl
+dnl HP-UX 11           posix      -lpthread       N (cc) OK
+dnl                                               Y (gcc)
+dnl
+dnl IRIX 6.5           posix      -lpthread       Y      0.5
+dnl
+dnl AIX 4.3,5.1        posix      -lpthread       N      AIX 4: 0.5; AIX 5: OK
+dnl
+dnl OSF/1 4.0,5.1      posix      -pthread (cc)   N      OK
+dnl                               -lpthread (gcc) Y
+dnl
+dnl Cygwin             posix      -lpthread       Y      OK
+dnl
+dnl Any of the above   pth        -lpth                  0.0
+dnl
+dnl Mingw              windows                    N      OK
+dnl
+dnl BeOS 5             --
+dnl
+dnl The test-lock result shows what happens if in test-lock.c EXPLICIT_YIELD is
+dnl turned off:
+dnl   OK if all three tests terminate OK,
+dnl   0.5 if the first test terminates OK but the second one loops endlessly,
+dnl   0.0 if the first test already loops endlessly.
diff --git a/m4/uintmax_t.m4 b/m4/uintmax_t.m4
new file mode 100644
index 0000000..8a92f58
--- /dev/null
+++ b/m4/uintmax_t.m4
@@ -0,0 +1,30 @@
+# uintmax_t.m4 serial 12
+dnl Copyright (C) 1997-2004, 2007-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Paul Eggert.
+
+AC_PREREQ([2.13])
+
+# Define uintmax_t to 'unsigned long' or 'unsigned long long'
+# if it is not already defined in <stdint.h> or <inttypes.h>.
+
+AC_DEFUN([gl_AC_TYPE_UINTMAX_T],
+[
+  AC_REQUIRE([gl_AC_HEADER_INTTYPES_H])
+  AC_REQUIRE([gl_AC_HEADER_STDINT_H])
+  if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; then
+    AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT])
+    test $ac_cv_type_unsigned_long_long_int = yes \
+      && ac_type='unsigned long long' \
+      || ac_type='unsigned long'
+    AC_DEFINE_UNQUOTED([uintmax_t], [$ac_type],
+      [Define to unsigned long or unsigned long long
+       if <stdint.h> and <inttypes.h> don't define.])
+  else
+    AC_DEFINE([HAVE_UINTMAX_T], [1],
+      [Define if you have the 'uintmax_t' type in <stdint.h> or <inttypes.h>.])
+  fi
+])
diff --git a/m4/vala.m4 b/m4/vala.m4
new file mode 100644
index 0000000..4393866
--- /dev/null
+++ b/m4/vala.m4
@@ -0,0 +1,135 @@
+dnl vala.m4
+dnl
+dnl Copyright 2010 Marc-Andre Lureau
+dnl Copyright 2011 Rodney Dawes <dobey pwns gmail com>
+dnl
+dnl This library is free software; you can redistribute it and/or
+dnl modify it under the terms of the GNU Lesser General Public
+dnl License as published by the Free Software Foundation; either
+dnl version 2.1 of the License, or (at your option) any later version.
+dnl
+dnl This library is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+dnl Lesser General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU Lesser General Public
+dnl License along with this library; if not, write to the Free Software
+dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+
+# _VALA_CHECK_COMPILE_WITH_ARGS(ARGS, [ACTION-IF-TRUE],
+#   [ACTION-IF-FALSE])
+# --------------------------------------
+# Check that Vala compile with ARGS.
+#
+AC_DEFUN([_VALA_CHECK_COMPILE_WITH_ARGS],
+[AC_REQUIRE([AM_PROG_VALAC])[]dnl
+
+  cat <<_ACEOF >conftest.vala
+void main(){}
+_ACEOF
+
+  AS_IF([vala_error=`$VALAC $1 -q --cc="${CC} ${CPPFLAGS} ${CFLAGS} ${LDFLAGS}" -o conftest$ac_exeext 
conftest.vala 2>&1`],
+        [$2], [$3])
+])
+
+])# _VALA_CHECK_COMPILE_WITH_ARGS
+
+# VALA_CHECK_PACKAGES(PKGS, [ACTION-IF-FOUND],
+#   [ACTION-IF-NOT-FOUND])
+# --------------------------------------
+# Check that PKGS Vala bindings are installed and usable.
+#
+AC_DEFUN([VALA_CHECK_PACKAGES],
+[
+  unset vala_pkgs
+  unset vala_bindings
+  ac_save_ifs="$IFS"; unset IFS
+  for vala_pkg in $(echo "$1"); do
+      vala_pkgs="${vala_pkgs:+$vala_pkgs }--pkg $vala_pkg"
+      vala_bindings="${vala_bindings:+$vala_bindings }$vala_pkg"
+  done
+  IFS="$ac_save_ifs"
+  AC_MSG_CHECKING([for $vala_bindings vala bindings])
+  _VALA_CHECK_COMPILE_WITH_ARGS([$vala_pkgs],
+    [vala_pkg_exists=yes],
+    [vala_pkg_exists=no])
+
+AS_IF([test x${vala_pkg_exists} = xno],[
+  ifelse([$3], , [AC_MSG_ERROR([]dnl
+[Package requirements were not met: $1
+
+$vala_error
+
+Consider adjusting the XDG_DATA_DIRS environment variable if you
+installed bindings in a non-standard prefix.
+])],
+  [AC_MSG_RESULT([no])
+$3])],[
+  AC_MSG_RESULT([yes])
+  ifelse([$2], , :, [$2])[]dnl
+])
+
+])# VALA_CHECK_PACKAGES
+
+
+# Check for Vala bindings for a package, as well as the pkg-config
+# CFLAGS and LIBS for the package. The arguments here work the
+# same as those for PKG_CHECK_MODULES, which is called internally.
+# As a result, the _CFLAGS, _LIBS, and _VALAFLAGS variables will
+# all be declared, rather than only _VALAFLAGS.
+#
+# VALA_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+# --------------------------------------------------------------
+AC_DEFUN([VALA_CHECK_MODULES],
+[
+               AC_REQUIRE([AM_PROG_VALAC])dnl
+               AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+        AC_REQUIRE([_VALA_CHECK_COMPILE_WITH_ARGS])dnl
+               AC_ARG_VAR([$1][_VALAFLAGS], [Vala compiler flags for $1])dnl
+
+        VALA_MODULES="`echo $2 | sed -e 's/ [[=<>]]\+ [[0-9.]]\+//g'`"
+        for MODULE in $VALA_MODULES; do
+            $1[]_VALAFLAGS="$[]$1[]_VALAFLAGS --pkg $MODULE"
+        done
+
+        PKG_CHECK_MODULES([$1], [$2], [$3], [$4])
+
+        pkg_failed=no
+               AC_MSG_CHECKING([for $1 vala modules])
+
+        _VALA_CHECK_COMPILE_WITH_ARGS([$1][_VALAFLAGS],
+                                      [pkg_failed=yes],
+                                      [pkg_failed=no])
+
+               if test $pkg_failed = yes; then
+                  AC_MSG_RESULT([no])
+                  m4_default([$4], [AC_MSG_ERROR(
+                                                       [Package requirements ($2) were not met.])dnl
+                  ])
+               else
+                       AC_MSG_RESULT([yes])
+                       m4_default([$3], [:])
+               fi[]dnl
+])
+
+# Check whether the Vala API Generator exists in `PATH'. If it is found,
+# the variable VAPIGEN is set. Optionally a minimum release number of the
+# generator can be requested.
+#
+# VALA_PROG_VAPIGEN([MINIMUM-VERSION])
+# ------------------------------------
+AC_DEFUN([VALA_PROG_VAPIGEN],
+[AC_PATH_PROG([VAPIGEN], [vapigen], [])
+  AS_IF([test -z "$VAPIGEN"],
+    [AC_MSG_WARN([No Vala API Generator found. You will not be able to generate .vapi files.])],
+    [AS_IF([test -n "$1"],
+        [AC_MSG_CHECKING([$VAPIGEN is at least version $1])
+         am__vapigen_version=`$VAPIGEN --version | sed 's/Vala API Generator  *//'`
+         AS_VERSION_COMPARE([$1], ["$am__vapigen_version"],
+           [AC_MSG_RESULT([yes])],
+           [AC_MSG_RESULT([yes])],
+           [AC_MSG_RESULT([no])
+            AC_MSG_ERROR([Vala API Generator $1 not found.])])])])
+])
diff --git a/m4/vapigen.m4 b/m4/vapigen.m4
new file mode 100644
index 0000000..2c435e7
--- /dev/null
+++ b/m4/vapigen.m4
@@ -0,0 +1,101 @@
+dnl vapigen.m4
+dnl
+dnl Copyright 2012 Evan Nemerson
+dnl
+dnl This library is free software; you can redistribute it and/or
+dnl modify it under the terms of the GNU Lesser General Public
+dnl License as published by the Free Software Foundation; either
+dnl version 2.1 of the License, or (at your option) any later version.
+dnl
+dnl This library is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+dnl Lesser General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU Lesser General Public
+dnl License along with this library; if not, write to the Free Software
+dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+
+# VAPIGEN_CHECK([VERSION], [API_VERSION], [FOUND_INTROSPECTION], [DEFAULT])
+# --------------------------------------
+# Check vapigen existence and version
+#
+# See http://live.gnome.org/Vala/UpstreamGuide for detailed documentation
+AC_DEFUN([VAPIGEN_CHECK],
+[
+  AS_IF([test "x$3" != "xyes"], [
+      m4_provide_if([GOBJECT_INTROSPECTION_CHECK], [], [
+          m4_provide_if([GOBJECT_INTROSPECTION_REQUIRE], [], [
+              AC_MSG_ERROR([[You must call GOBJECT_INTROSPECTION_CHECK or GOBJECT_INTROSPECTION_REQUIRE 
before using VAPIGEN_CHECK unless using the FOUND_INTROSPECTION argument is "yes"]])
+            ])
+        ])
+    ])
+
+  AC_ARG_ENABLE([vala],
+    [AS_HELP_STRING([--enable-vala[=@<:@no/auto/yes@:>@]],[build Vala bindings 
@<:@default=]ifelse($4,,auto,$4)[@:>@])],,[
+      AS_IF([test "x$4" = "x"], [
+          enable_vala=auto
+        ], [
+          enable_vala=$4
+        ])
+    ])
+
+  AS_CASE([$enable_vala], [no], [enable_vala=no],
+      [yes], [
+        AS_IF([test "x$3" != "xyes" -a "x$found_introspection" != "xyes"], [
+            AC_MSG_ERROR([Vala bindings require GObject Introspection])
+          ])
+      ], [auto], [
+        AS_IF([test "x$3" != "xyes" -a "x$found_introspection" != "xyes"], [
+            enable_vala=no
+          ])
+      ], [
+        AC_MSG_ERROR([Invalid argument passed to --enable-vala, should be one of @<:@no/auto/yes@:>@])
+      ])
+
+  AS_IF([test "x$2" = "x"], [
+      vapigen_pkg_name=vapigen
+    ], [
+      vapigen_pkg_name=vapigen-$2
+    ])
+  AS_IF([test "x$1" = "x"], [
+      vapigen_pkg="$vapigen_pkg_name"
+    ], [
+      vapigen_pkg="$vapigen_pkg_name >= $1"
+    ])
+
+  PKG_PROG_PKG_CONFIG
+
+  PKG_CHECK_EXISTS([$vapigen_pkg], [
+      AS_IF([test "$enable_vala" = "auto"], [
+          enable_vala=yes
+        ])
+    ], [
+      AS_CASE([$enable_vala], [yes], [
+          AC_MSG_ERROR([$vapigen_pkg not found])
+        ], [auto], [
+          enable_vala=no
+        ])
+    ])
+
+  AC_MSG_CHECKING([for vapigen])
+
+  AS_CASE([$enable_vala],
+    [yes], [
+      VAPIGEN=`$PKG_CONFIG --variable=vapigen $vapigen_pkg_name`
+      VAPIGEN_MAKEFILE=`$PKG_CONFIG --variable=datadir $vapigen_pkg_name`/vala/Makefile.vapigen
+      AS_IF([test "x$2" = "x"], [
+          VAPIGEN_VAPIDIR=`$PKG_CONFIG --variable=vapidir $vapigen_pkg_name`
+        ], [
+          VAPIGEN_VAPIDIR=`$PKG_CONFIG --variable=vapidir_versioned $vapigen_pkg_name`
+        ])
+    ])
+
+  AC_MSG_RESULT([$enable_vala])
+
+  AC_SUBST([VAPIGEN])
+  AC_SUBST([VAPIGEN_VAPIDIR])
+  AC_SUBST([VAPIGEN_MAKEFILE])
+
+  AM_CONDITIONAL(ENABLE_VAPIGEN, test "x$enable_vala" = "xyes")
+])
diff --git a/m4/visibility.m4 b/m4/visibility.m4
new file mode 100644
index 0000000..6fff745
--- /dev/null
+++ b/m4/visibility.m4
@@ -0,0 +1,77 @@
+# visibility.m4 serial 5 (gettext-0.18.2)
+dnl Copyright (C) 2005, 2008, 2010-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+dnl Tests whether the compiler supports the command-line option
+dnl -fvisibility=hidden and the function and variable attributes
+dnl __attribute__((__visibility__("hidden"))) and
+dnl __attribute__((__visibility__("default"))).
+dnl Does *not* test for __visibility__("protected") - which has tricky
+dnl semantics (see the 'vismain' test in glibc) and does not exist e.g. on
+dnl Mac OS X.
+dnl Does *not* test for __visibility__("internal") - which has processor
+dnl dependent semantics.
+dnl Does *not* test for #pragma GCC visibility push(hidden) - which is
+dnl "really only recommended for legacy code".
+dnl Set the variable CFLAG_VISIBILITY.
+dnl Defines and sets the variable HAVE_VISIBILITY.
+
+AC_DEFUN([gl_VISIBILITY],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  CFLAG_VISIBILITY=
+  HAVE_VISIBILITY=0
+  if test -n "$GCC"; then
+    dnl First, check whether -Werror can be added to the command line, or
+    dnl whether it leads to an error because of some other option that the
+    dnl user has put into $CC $CFLAGS $CPPFLAGS.
+    AC_MSG_CHECKING([whether the -Werror option is usable])
+    AC_CACHE_VAL([gl_cv_cc_vis_werror], [
+      gl_save_CFLAGS="$CFLAGS"
+      CFLAGS="$CFLAGS -Werror"
+      AC_COMPILE_IFELSE(
+        [AC_LANG_PROGRAM([[]], [[]])],
+        [gl_cv_cc_vis_werror=yes],
+        [gl_cv_cc_vis_werror=no])
+      CFLAGS="$gl_save_CFLAGS"])
+    AC_MSG_RESULT([$gl_cv_cc_vis_werror])
+    dnl Now check whether visibility declarations are supported.
+    AC_MSG_CHECKING([for simple visibility declarations])
+    AC_CACHE_VAL([gl_cv_cc_visibility], [
+      gl_save_CFLAGS="$CFLAGS"
+      CFLAGS="$CFLAGS -fvisibility=hidden"
+      dnl We use the option -Werror and a function dummyfunc, because on some
+      dnl platforms (Cygwin 1.7) the use of -fvisibility triggers a warning
+      dnl "visibility attribute not supported in this configuration; ignored"
+      dnl at the first function definition in every compilation unit, and we
+      dnl don't want to use the option in this case.
+      if test $gl_cv_cc_vis_werror = yes; then
+        CFLAGS="$CFLAGS -Werror"
+      fi
+      AC_COMPILE_IFELSE(
+        [AC_LANG_PROGRAM(
+           [[extern __attribute__((__visibility__("hidden"))) int hiddenvar;
+             extern __attribute__((__visibility__("default"))) int exportedvar;
+             extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void);
+             extern __attribute__((__visibility__("default"))) int exportedfunc (void);
+             void dummyfunc (void) {}
+           ]],
+           [[]])],
+        [gl_cv_cc_visibility=yes],
+        [gl_cv_cc_visibility=no])
+      CFLAGS="$gl_save_CFLAGS"])
+    AC_MSG_RESULT([$gl_cv_cc_visibility])
+    if test $gl_cv_cc_visibility = yes; then
+      CFLAG_VISIBILITY="-fvisibility=hidden"
+      HAVE_VISIBILITY=1
+    fi
+  fi
+  AC_SUBST([CFLAG_VISIBILITY])
+  AC_SUBST([HAVE_VISIBILITY])
+  AC_DEFINE_UNQUOTED([HAVE_VISIBILITY], [$HAVE_VISIBILITY],
+    [Define to 1 or 0, depending whether the compiler supports simple visibility declarations.])
+])
diff --git a/m4/wchar_t.m4 b/m4/wchar_t.m4
new file mode 100644
index 0000000..dc964e6
--- /dev/null
+++ b/m4/wchar_t.m4
@@ -0,0 +1,24 @@
+# wchar_t.m4 serial 4 (gettext-0.18.2)
+dnl Copyright (C) 2002-2003, 2008-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+dnl Test whether <stddef.h> has the 'wchar_t' type.
+dnl Prerequisite: AC_PROG_CC
+
+AC_DEFUN([gt_TYPE_WCHAR_T],
+[
+  AC_CACHE_CHECK([for wchar_t], [gt_cv_c_wchar_t],
+    [AC_COMPILE_IFELSE(
+       [AC_LANG_PROGRAM(
+          [[#include <stddef.h>
+            wchar_t foo = (wchar_t)'\0';]],
+          [[]])],
+       [gt_cv_c_wchar_t=yes],
+       [gt_cv_c_wchar_t=no])])
+  if test $gt_cv_c_wchar_t = yes; then
+    AC_DEFINE([HAVE_WCHAR_T], [1], [Define if you have the 'wchar_t' type.])
+  fi
+])
diff --git a/m4/wint_t.m4 b/m4/wint_t.m4
new file mode 100644
index 0000000..ca3fd44
--- /dev/null
+++ b/m4/wint_t.m4
@@ -0,0 +1,32 @@
+# wint_t.m4 serial 5 (gettext-0.18.2)
+dnl Copyright (C) 2003, 2007-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+dnl Test whether <wchar.h> has the 'wint_t' type.
+dnl Prerequisite: AC_PROG_CC
+
+AC_DEFUN([gt_TYPE_WINT_T],
+[
+  AC_CACHE_CHECK([for wint_t], [gt_cv_c_wint_t],
+    [AC_COMPILE_IFELSE(
+       [AC_LANG_PROGRAM(
+          [[
+/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
+   <wchar.h>.
+   BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be included
+   before <wchar.h>.  */
+#include <stddef.h>
+#include <stdio.h>
+#include <time.h>
+#include <wchar.h>
+            wint_t foo = (wchar_t)'\0';]],
+          [[]])],
+       [gt_cv_c_wint_t=yes],
+       [gt_cv_c_wint_t=no])])
+  if test $gt_cv_c_wint_t = yes; then
+    AC_DEFINE([HAVE_WINT_T], [1], [Define if you have the 'wint_t' type.])
+  fi
+])
diff --git a/m4/xsize.m4 b/m4/xsize.m4
new file mode 100644
index 0000000..98faf7d
--- /dev/null
+++ b/m4/xsize.m4
@@ -0,0 +1,12 @@
+# xsize.m4 serial 5
+dnl Copyright (C) 2003-2004, 2008-2015 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_XSIZE],
+[
+  dnl Prerequisites of lib/xsize.h.
+  AC_REQUIRE([gl_SIZE_MAX])
+  AC_CHECK_HEADERS([stdint.h])
+])
diff --git a/m4/yelp.m4 b/m4/yelp.m4
new file mode 100644
index 0000000..5db847f
--- /dev/null
+++ b/m4/yelp.m4
@@ -0,0 +1,213 @@
+AC_DEFUN([YELP_HELP_INIT],
+[
+AC_REQUIRE([AC_PROG_LN_S])
+m4_pattern_allow([AM_V_at])
+m4_pattern_allow([AM_V_GEN])
+m4_pattern_allow([AM_DEFAULT_VERBOSITY])
+
+YELP_LC_MEDIA_LINKS=true
+YELP_LC_DIST=true
+
+for yelpopt in [$1]; do
+  case $yelpopt in
+    lc-media-links)    YELP_LC_MEDIA_LINKS=true ;;
+    no-lc-media-links) YELP_LC_MEDIA_LINKS= ;;
+    lc-dist)           YELP_LC_DIST=true ;;
+    no-lc-dist)        YELP_LC_DIST= ;;
+    *) AC_MSG_ERROR([Unrecognized [YELP_HELP_INIT] option $yelpopt"]) ;;
+  esac
+done;
+AC_SUBST([YELP_LC_MEDIA_LINKS])
+AC_SUBST([YELP_LC_DIST])
+
+AC_ARG_WITH([help-dir],
+            AS_HELP_STRING([--with-help-dir=DIR],
+                           [path where help files are installed]),,
+            [with_help_dir='${datadir}/help'])
+HELP_DIR="$with_help_dir"
+AC_SUBST(HELP_DIR)
+
+AC_ARG_VAR([ITSTOOL], [Path to the `itstool` command])
+AC_CHECK_PROG([ITSTOOL], [itstool], [itstool])
+if test x"$ITSTOOL" = x; then
+  AC_MSG_ERROR([itstool not found])
+fi
+
+AC_ARG_VAR([XMLLINT], [Path to the `xmllint` command])
+AC_CHECK_PROG([XMLLINT], [xmllint], [xmllint])
+if test x"$XMLLINT" = x; then
+  AC_MSG_ERROR([xmllint not found])
+fi
+
+YELP_HELP_RULES='
+HELP_ID ?=
+HELP_POT ?=
+HELP_FILES ?=
+HELP_EXTRA ?=
+HELP_MEDIA ?=
+HELP_LINGUAS ?=
+
+_HELP_LINGUAS = $(if $(filter environment,$(origin LINGUAS)),$(filter 
$(LINGUAS),$(HELP_LINGUAS)),$(HELP_LINGUAS))
+_HELP_POTFILE = $(if $(HELP_POT),$(HELP_POT),$(if $(HELP_ID),$(HELP_ID).pot))
+_HELP_POFILES = $(if $(HELP_ID),$(foreach lc,$(_HELP_LINGUAS),$(lc)/$(lc).po))
+_HELP_MOFILES = $(patsubst %.po,%.mo,$(_HELP_POFILES))
+_HELP_C_FILES = $(foreach f,$(HELP_FILES),C/$(f))
+_HELP_C_EXTRA = $(foreach f,$(HELP_EXTRA),C/$(f))
+_HELP_C_MEDIA = $(foreach f,$(HELP_MEDIA),C/$(f))
+_HELP_LC_FILES = $(foreach lc,$(_HELP_LINGUAS),$(foreach f,$(HELP_FILES),$(lc)/$(f)))
+_HELP_LC_STAMPS = $(foreach lc,$(_HELP_LINGUAS),$(lc)/$(lc).stamp)
+
+_HELP_DEFAULT_V = $(if $(AM_DEFAULT_VERBOSITY),$(AM_DEFAULT_VERBOSITY),1)
+_HELP_V = $(if $(V),$(V),$(_HELP_DEFAULT_V))
+_HELP_LC_VERBOSE = $(_HELP_LC_VERBOSE_$(_HELP_V))
+_HELP_LC_VERBOSE_ = $(_HELP_LC_VERBOSE_$(_HELP_DEFAULT_V))
+_HELP_LC_VERBOSE_0 = @echo "  GEN    "$(dir [$]@);
+
+all: $(_HELP_C_FILES) $(_HELP_C_EXTRA) $(_HELP_C_MEDIA) $(_HELP_LC_FILES) $(_HELP_POFILES)
+
+.PHONY: pot
+pot: $(_HELP_POTFILE)
+$(_HELP_POTFILE): $(_HELP_C_FILES) $(_HELP_C_EXTRA) $(_HELP_C_MEDIA)
+       $(AM_V_GEN)if test -d "C"; then d=; else d="$(srcdir)/"; fi; \
+       $(ITSTOOL) -o "[$]@" $(foreach f,$(_HELP_C_FILES),"$${d}$(f)")
+
+.PHONY: repo
+repo: $(_HELP_POTFILE)
+       $(AM_V_at)for po in $(_HELP_POFILES); do \
+         if test "x[$](_HELP_V)" = "x0"; then echo "  GEN    $${po}"; fi; \
+         msgmerge -q -o "$${po}" "$${po}" "$(_HELP_POTFILE)"; \
+       done
+
+$(_HELP_POFILES):
+       $(AM_V_at)if ! test -d "$(dir [$]@)"; then mkdir "$(dir [$]@)"; fi
+       $(AM_V_at)if test ! -f "[$]@" -a -f "$(srcdir)/[$]@"; then cp "$(srcdir)/[$]@" "[$]@"; fi
+       $(AM_V_GEN)if ! test -f "[$]@"; then \
+         (cd "$(dir [$]@)" && \
+           $(ITSTOOL) -o "$(notdir [$]@).tmp" $(_HELP_C_FILES) && \
+           mv "$(notdir [$]@).tmp" "$(notdir [$]@)"); \
+       else \
+         (cd "$(dir [$]@)" && \
+           $(ITSTOOL) -o "$(notdir [$]@).tmp" $(_HELP_C_FILES) && \
+           msgmerge -o "$(notdir [$]@)" "$(notdir [$]@)" "$(notdir [$]@).tmp" && \
+           rm "$(notdir [$]@).tmp"); \
+       fi
+
+$(_HELP_MOFILES): %.mo: %.po
+       $(AM_V_at)if ! test -d "$(dir [$]@)"; then mkdir "$(dir [$]@)"; fi
+       $(AM_V_GEN)msgfmt -o "[$]@" "$<"
+
+$(_HELP_LC_FILES): $(_HELP_LINGUAS)
+$(_HELP_LINGUAS): $(_HELP_LC_STAMPS)
+$(_HELP_LC_STAMPS): %.stamp: %.mo
+$(_HELP_LC_STAMPS): $(_HELP_C_FILES) $(_HELP_C_EXTRA)
+       $(AM_V_at)if ! test -d "$(dir [$]@)"; then mkdir "$(dir [$]@)"; fi
+       $(_HELP_LC_VERBOSE)if test -d "C"; then d="../"; else d="$(abs_srcdir)/"; fi; \
+       mo="$(dir [$]@)$(patsubst %/$(notdir [$]@),%,[$]@).mo"; \
+       if test -f "$${mo}"; then mo="../$${mo}"; else mo="$(abs_srcdir)/$${mo}"; fi; \
+       (cd "$(dir [$]@)" && $(ITSTOOL) -m "$${mo}" $(foreach f,$(_HELP_C_FILES),$${d}/$(f))) && \
+       touch "[$]@"
+
+.PHONY: clean-help
+mostlyclean-am: $(if $(HELP_ID),clean-help)
+clean-help:
+       rm -f $(_HELP_LC_FILES) $(_HELP_LC_STAMPS) $(_HELP_MOFILES)
+
+EXTRA_DIST ?=
+EXTRA_DIST += $(_HELP_C_EXTRA) $(_HELP_C_MEDIA)
+EXTRA_DIST += $(if $(YELP_LC_DIST),$(foreach lc,$(HELP_LINGUAS),$(lc)/$(lc).stamp))
+EXTRA_DIST += $(foreach lc,$(HELP_LINGUAS),$(lc)/$(lc).po)
+EXTRA_DIST += $(foreach f,$(HELP_MEDIA),$(foreach lc,$(HELP_LINGUAS),$(wildcard $(lc)/$(f))))
+
+distdir: distdir-help-files
+distdir-help-files: $(_HELP_LC_FILES)
+       @for lc in C $(if $(YELP_LC_DIST),$(HELP_LINGUAS)) ; do \
+         $(MKDIR_P) "$(distdir)/$$lc"; \
+         for file in $(HELP_FILES); do \
+           if test -f "$$lc/$$file"; then d=./; else d=$(srcdir)/; fi; \
+           cp -p "$$d$$lc/$$file" "$(distdir)/$$lc/" || exit 1; \
+         done; \
+       done; \
+
+.PHONY: check-help
+check: check-help
+check-help:
+       for lc in C $(_HELP_LINGUAS); do \
+         if test -d "$$lc"; \
+           then d=; \
+           xmlpath="$$lc"; \
+         else \
+           d="$(srcdir)/"; \
+           xmlpath="$$lc:$(srcdir)/$$lc"; \
+         fi; \
+         for page in $(HELP_FILES); do \
+           echo "$(XMLLINT) --noout --noent --path $$xmlpath --xinclude $$d$$lc/$$page"; \
+           $(XMLLINT) --noout --noent --path "$$xmlpath" --xinclude "$$d$$lc/$$page"; \
+         done; \
+       done
+
+
+.PHONY: install-help
+install-data-am: $(if $(HELP_ID),install-help)
+install-help: $(_HELP_LC_FILES)
+       @for lc in C $(_HELP_LINGUAS); do \
+         $(mkinstalldirs) "$(DESTDIR)$(HELP_DIR)/$$lc/$(HELP_ID)" || exit 1; \
+       done
+       @for lc in C $(_HELP_LINGUAS); do for f in $(HELP_FILES); do \
+         if test -f "$$lc/$$f"; then d=; else d="$(srcdir)/"; fi; \
+         helpdir="$(DESTDIR)$(HELP_DIR)/$$lc/$(HELP_ID)/"; \
+         if ! test -d "$$helpdir"; then $(mkinstalldirs) "$$helpdir"; fi; \
+         echo "$(INSTALL_DATA) $$d$$lc/$$f $$helpdir`basename $$f`"; \
+         $(INSTALL_DATA) "$$d$$lc/$$f" "$$helpdir`basename $$f`" || exit 1; \
+       done; done
+       @for f in $(_HELP_C_EXTRA); do \
+         lc=`dirname "$$f"`; lc=`basename "$$lc"`; \
+         if test -f "$$f"; then d=; else d="$(srcdir)/"; fi; \
+         helpdir="$(DESTDIR)$(HELP_DIR)/$$lc/$(HELP_ID)/"; \
+         if ! test -d "$$helpdir"; then $(mkinstalldirs) "$$helpdir"; fi; \
+         echo "$(INSTALL_DATA) $$d$$f $$helpdir`basename $$f`"; \
+         $(INSTALL_DATA) "$$d$$f" "$$helpdir`basename $$f`" || exit 1; \
+       done
+       @for f in $(HELP_MEDIA); do \
+         for lc in C $(_HELP_LINGUAS); do \
+           if test -f "$$lc$$f"; then d=; else d="$(srcdir)/"; fi; \
+           helpdir="$(DESTDIR)$(HELP_DIR)/$$lc/$(HELP_ID)/"; \
+           mdir=`dirname "$$f"`; \
+           if test "x$mdir" = "x."; then mdir=""; fi; \
+           if ! test -d "$$helpdir$$mdir"; then $(mkinstalldirs) "$$helpdir$$mdir"; fi; \
+           if test -f "$$d$$lc/$$f"; then \
+             echo "$(INSTALL_DATA) $$d$$lc/$$f $$helpdir$$f"; \
+             $(INSTALL_DATA) "$$d$$lc/$$f" "$$helpdir$$f" || exit 1; \
+           elif test "x$$lc" != "xC"; then \
+             if test "x$(YELP_LC_MEDIA_LINKS)" != "x"; then \
+               echo "$(LN_S) -f $(HELP_DIR)/C/$(HELP_ID)/$$f $$helpdir$$f"; \
+               $(LN_S) -f "$(HELP_DIR)/C/$(HELP_ID)/$$f" "$$helpdir$$f" || exit 1; \
+             fi; \
+           fi; \
+         done; \
+       done
+
+.PHONY: uninstall-help
+uninstall-am: $(if $(HELP_ID),uninstall-help)
+uninstall-help:
+       for lc in C $(_HELP_LINGUAS); do for f in $(HELP_FILES); do \
+         helpdir="$(DESTDIR)$(HELP_DIR)/$$lc/$(HELP_ID)/"; \
+         echo "rm -f $$helpdir`basename $$f`"; \
+         rm -f "$$helpdir`basename $$f`"; \
+       done; done
+       @for f in $(_HELP_C_EXTRA); do \
+         lc=`dirname "$$f"`; lc=`basename "$$lc"`; \
+         helpdir="$(DESTDIR)$(HELP_DIR)/$$lc/$(HELP_ID)/"; \
+         echo "rm -f $$helpdir`basename $$f`"; \
+         rm -f "$$helpdir`basename $$f`"; \
+       done
+       @for f in $(HELP_MEDIA); do \
+         for lc in C $(_HELP_LINGUAS); do \
+           helpdir="$(DESTDIR)$(HELP_DIR)/$$lc/$(HELP_ID)/"; \
+           echo "rm -f $$helpdir$$f"; \
+           rm -f "$$helpdir$$f"; \
+         done; \
+       done;
+'
+AC_SUBST([YELP_HELP_RULES])
+m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([YELP_HELP_RULES])])
+])
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..9973c6f
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,38 @@
+bin_PROGRAMS = sysprof
+
+sysprof_CFLAGS = \
+       $(SYSPROF_CFLAGS) \
+       -I$(top_srcdir)/lib \
+       -I$(top_builddir)/lib
+
+sysprof_SOURCES = \
+       sysprof.c \
+       sp-application.c \
+       sp-application.h \
+       sp-credits.h \
+       sp-window.c \
+       sp-window.h \
+       sp-window-settings.c \
+       sp-window-settings.h \
+       $(NULL)
+
+nodist_sysprof_SOURCES = \
+       sp-resources.c \
+       sp-resources.h
+
+sysprof_LDADD = \
+       $(SYSPROF_LIBS) \
+       $(top_builddir)/lib/libsysprof- API_VERSION@.la
+
+EXTRA_DIST =
+CLEANFILES =
+DISTCLEANFILES =
+BUILT_SOURCES =
+
+glib_resources_xml = resources/sysprof.gresource.xml
+glib_resources_c = sp-resources.c
+glib_resources_h = sp-resources.h
+glib_resources_namespace = sysprof
+include $(top_srcdir)/gresources.mk
+
+-include $(top_srcdir)/git.mk
diff --git a/src/resources/gtk/menus.ui b/src/resources/gtk/menus.ui
new file mode 100644
index 0000000..94b99a0
--- /dev/null
+++ b/src/resources/gtk/menus.ui
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<interface>
+  <menu id="app-menu">
+    <section id="app-menu-new-section">
+      <item>
+        <attribute name="label" translatable="yes">_New Window</attribute>
+        <attribute name="action">app.new-window</attribute>
+      </item>
+    </section>
+    <section id="app-menu-open-section">
+      <item>
+        <attribute name="label" translatable="yes">_Open Capture</attribute>
+        <attribute name="action">app.open-capture</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">About</attribute>
+        <attribute name="action">app.about</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">Help</attribute>
+        <attribute name="action">app.help</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Quit</attribute>
+        <attribute name="action">app.quit</attribute>
+      </item>
+    </section>
+  </menu>
+  <menu id="gear-menu">
+    <section id="gear-menu-open-section">
+      <item>
+        <attribute name="label" translatable="yes">Open</attribute>
+        <attribute name="action">win.open-capture</attribute>
+      </item>
+    </section>
+    <section id="gear-menu-save-section">
+      <item>
+        <attribute name="label" translatable="yes">Save As</attribute>
+        <attribute name="action">win.save-capture</attribute>
+      </item>
+    </section>
+    <section id="gear-menu-close-section">
+      <item>
+        <attribute name="label" translatable="yes">Close</attribute>
+        <attribute name="action">win.close-capture</attribute>
+      </item>
+    </section>
+  </menu>
+</interface>
diff --git a/src/resources/sysprof.gresource.xml b/src/resources/sysprof.gresource.xml
new file mode 100644
index 0000000..b6735f3
--- /dev/null
+++ b/src/resources/sysprof.gresource.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<gresources>
+  <gresource prefix="/org/gnome/sysprof">
+    <!-- Automatic GTK resources -->
+    <file>gtk/menus.ui</file>
+
+    <!-- Application icons -->
+    <file alias="icons/16x16/apps/sysprof.png">../../data/icons/16x16/apps/sysprof.png</file>
+    <file alias="icons/24x24/apps/sysprof.png">../../data/icons/24x24/apps/sysprof.png</file>
+    <file alias="icons/32x32/apps/sysprof.png">../../data/icons/32x32/apps/sysprof.png</file>
+    <file alias="icons/48x48/apps/sysprof.png">../../data/icons/48x48/apps/sysprof.png</file>
+    <file alias="icons/256x256/apps/sysprof.png">../../data/icons/256x256/apps/sysprof.png</file>
+    <file 
alias="icons/scalable/apps/sysprof-symbolic.svg">../../data/icons/scalable/apps/sysprof-symbolic.svg</file>
+
+    <!-- Theme overrides -->
+    <file compressed="true">theme/shared.css</file>
+
+    <!-- UI Files -->
+    <file compressed="true">ui/sp-window.ui</file>
+  </gresource>
+</gresources>
diff --git a/src/resources/theme/shared.css b/src/resources/theme/shared.css
new file mode 100644
index 0000000..3d4da45
--- /dev/null
+++ b/src/resources/theme/shared.css
@@ -0,0 +1,12 @@
+popover list row {
+  padding: 6px 10px 6px 10px;
+  border-bottom: 1px solid alpha(@borders, 0.2);
+}
+
+popover list row:last-child {
+  border-bottom: none;
+}
+
+popover scrolledwindow {
+  border-top: 1px solid alpha(@borders, 0.75);
+}
diff --git a/src/resources/ui/sp-window.ui b/src/resources/ui/sp-window.ui
new file mode 100644
index 0000000..298c464
--- /dev/null
+++ b/src/resources/ui/sp-window.ui
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="utf-8"?>
+<interface>
+  <template class="SpWindow" parent="GtkApplicationWindow">
+    <property name="default-height">700</property>
+    <property name="default-width">1200</property>
+    <property name="icon-name">sysprof</property>
+    <property name="show-menubar">false</property>
+    <property name="title" translatable="yes">Sysprof</property>
+    <child type="titlebar">
+      <object class="GtkHeaderBar">
+        <property name="show-close-button">true</property>
+        <property name="visible">true</property>
+        <child type="title">
+          <object class="GtkBox">
+            <property name="orientation">vertical</property>
+            <property name="visible">true</property>
+            <child>
+              <object class="GtkLabel" id="title">
+                <property name="visible">true</property>
+                <property name="label" translatable="yes">Sysprof</property>
+                <attributes>
+                  <attribute name="weight" value="bold"/>
+                  <attribute name="scale" value="0.8"/>
+                </attributes>
+              </object>
+            </child>
+            <child>
+              <object class="GtkLabel" id="subtitle">
+                <property name="visible">true</property>
+                <property name="label" translatable="yes">Not running</property>
+                <property name="ellipsize">start</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+                <attributes>
+                  <attribute name="scale" value="0.8"/>
+                </attributes>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkButton" id="record_button">
+            <property name="label" translatable="yes">_Record</property>
+            <property name="use-underline">true</property>
+            <property name="visible">true</property>
+            <property name="width-request">100</property>
+            <style>
+              <class name="suggested-action"/>
+            </style>
+          </object>
+        </child>
+        <child>
+          <object class="SpProfilerMenuButton" id="profiler_menu_button">
+            <property name="width-request">200</property>
+            <property name="visible">true</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkLabel" id="stat_label">
+            <property name="margin-end">12</property>
+            <property name="xalign">1</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+          </object>
+          <packing>
+            <property name="pack-type">end</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkMenuButton" id="gear_menu_button">
+            <property name="visible">true</property>
+            <style>
+              <class name="image-button"/>
+            </style>
+            <child>
+              <object class="GtkImage">
+                <property name="icon-name">open-menu-symbolic</property>
+                <property name="visible">true</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="pack-type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <child>
+      <object class="GtkBox">
+        <property name="orientation">vertical</property>
+        <property name="visible">true</property>
+        <child>
+          <object class="GtkRevealer" id="info_bar_revealer">
+            <property name="visible">true</property>
+            <property name="reveal-child">false</property>
+            <child>
+              <object class="GtkInfoBar" id="info_bar">
+                <property name="visible">true</property>
+                <child internal-child="content_area">
+                  <object class="GtkBox">
+                    <child>
+                      <object class="GtkLabel" id="info_bar_label">
+                        <property name="hexpand">true</property>
+                        <property name="label">Failure</property>
+                        <property name="visible">true</property>
+                        <property name="wrap">true</property>
+                        <property name="xalign">0</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkButton" id="close_info_button">
+                        <property name="label" translatable="yes">_Close</property>
+                        <property name="use-underline">true</property>
+                        <property name="visible">true</property>
+                        <property name="width-request">100</property>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <action-widgets>
+                  <action-widget response="0">close_info_button</action-widget>
+                </action-widgets>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkStack" id="view_stack">
+            <property name="expand">true</property>
+            <property name="transition-duration">400</property>
+            <property name="transition-type">crossfade</property>
+            <property name="visible">true</property>
+            <child>
+              <object class="SpEmptyStateView" id="empty_view">
+                <property name="visible">true</property>
+              </object>
+              <packing>
+                <property name="name">empty</property>
+              </packing>
+            </child>
+            <child>
+              <object class="SpFailedStateView" id="failed_view">
+                <property name="visible">true</property>
+              </object>
+              <packing>
+                <property name="name">failed</property>
+              </packing>
+            </child>
+            <child>
+              <object class="SpRecordingStateView" id="recording_view">
+                <property name="visible">true</property>
+              </object>
+              <packing>
+                <property name="name">recording</property>
+              </packing>
+            </child>
+            <child>
+              <object class="SpCallgraphView" id="callgraph_view">
+                <property name="visible">true</property>
+              </object>
+              <packing>
+                <property name="name">browsing</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/sp-application.c b/src/sp-application.c
new file mode 100644
index 0000000..776f57b
--- /dev/null
+++ b/src/sp-application.c
@@ -0,0 +1,271 @@
+/* sp-application.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib/gi18n.h>
+
+#include "sp-application.h"
+#include "sp-credits.h"
+#include "sp-window.h"
+
+struct _SpApplication
+{
+  GtkApplication parent_instance;
+};
+
+G_DEFINE_TYPE (SpApplication, sp_application, GTK_TYPE_APPLICATION)
+
+static void
+sp_application_activate (GApplication *app)
+{
+  SpWindow *window;
+  GList *windows;
+
+  g_assert (GTK_IS_APPLICATION (app));
+
+  windows = gtk_application_get_windows (GTK_APPLICATION (app));
+
+  for (; windows != NULL; windows = windows->next)
+    {
+      if (SP_IS_WINDOW (windows->data))
+        {
+          gtk_window_present (windows->data);
+          return;
+        }
+    }
+
+  window = g_object_new (SP_TYPE_WINDOW,
+                         "application", app,
+                         NULL);
+
+  gtk_window_present (GTK_WINDOW (window));
+}
+
+static void
+sp_application_open (GApplication  *app,
+                     GFile        **files,
+                     gint           n_files,
+                     const gchar   *hint)
+{
+  guint opened = 0;
+  gint i;
+
+  g_assert (SP_IS_APPLICATION (app));
+  g_assert (files != NULL || n_files == 0);
+
+  for (i = 0; i < n_files; i++)
+    {
+      SpWindow *window;
+
+      window = g_object_new (SP_TYPE_WINDOW,
+                             "application", app,
+                             NULL);
+      sp_window_open (window, files [i]);
+      gtk_window_present (GTK_WINDOW (window));
+      opened++;
+    }
+
+  if (opened == 0)
+    sp_application_activate (app);
+}
+
+static void
+sp_application_startup (GApplication *application)
+{
+  GtkCssProvider *provider;
+
+  g_assert (SP_IS_APPLICATION (application));
+
+  G_APPLICATION_CLASS (sp_application_parent_class)->startup (application);
+
+  provider = gtk_css_provider_new ();
+  gtk_css_provider_load_from_resource (provider, "/org/gnome/sysprof/theme/shared.css");
+  gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+                                             GTK_STYLE_PROVIDER (provider),
+                                             GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+  g_clear_object (&provider);
+}
+
+static void
+sp_application_class_init (SpApplicationClass *klass)
+{
+  GApplicationClass *app_class = G_APPLICATION_CLASS (klass);
+
+  app_class->open = sp_application_open;
+  app_class->startup = sp_application_startup;
+  app_class->activate = sp_application_activate;
+}
+
+static void
+sysprof_quit (GSimpleAction *action,
+              GVariant      *variant,
+              gpointer       user_data)
+{
+  GApplication *app = user_data;
+
+  g_assert (G_IS_APPLICATION (app));
+  g_assert (G_IS_SIMPLE_ACTION (action));
+  g_assert (variant == NULL);
+
+  g_application_quit (app);
+}
+
+static void
+sysprof_about (GSimpleAction *action,
+               GVariant      *variant,
+               gpointer       user_data)
+{
+  GtkApplication *app = user_data;
+  GtkWindow *best_toplevel = NULL;
+  GtkWindow *dialog;
+  GList *windows;
+
+  g_assert (G_IS_APPLICATION (app));
+  g_assert (G_IS_SIMPLE_ACTION (action));
+  g_assert (variant == NULL);
+
+  windows = gtk_application_get_windows (app);
+
+  for (; windows != NULL; windows = windows->next)
+    {
+      if (SP_IS_WINDOW (windows->data))
+        {
+          best_toplevel = windows->data;
+          break;
+        }
+    }
+
+  dialog = g_object_new (GTK_TYPE_ABOUT_DIALOG,
+                         "application", app,
+                         "authors", sysprof_authors,
+                         "artists", sysprof_artists,
+                         "comments", _("A system profiler"),
+                         "copyright", "Copyright © 2004-2009 Søren Sandmann Pedersen\n"
+                                      "Copyright © 2016 Christian Hergert",
+                         "transient-for", best_toplevel,
+                         "translator-credits", _("translator-credits"),
+                         "license-type", GTK_LICENSE_GPL_3_0,
+                         "logo-icon-name", "sysprof",
+                         "program-name", _("Sysprof"),
+                         "version", PACKAGE_VERSION,
+                         "website", "https://wiki.gnome.org/Apps/Sysprof";,
+                         "website-label", _("Learn more about Sysprof"),
+                         NULL);
+
+  gtk_window_present (dialog);
+}
+
+static void
+sysprof_help (GSimpleAction *action,
+              GVariant      *param,
+              gpointer       user_data)
+{
+  gtk_show_uri (gdk_screen_get_default (),
+                "help:sysprof",
+                gtk_get_current_event_time (),
+                NULL);
+}
+
+static void
+sysprof_new_window (GSimpleAction *action,
+                    GVariant      *variant,
+                    gpointer       user_data)
+{
+  SpApplication *self = user_data;
+  SpWindow *window;
+
+  g_assert (SP_IS_APPLICATION (self));
+  g_assert (G_IS_SIMPLE_ACTION (action));
+  g_assert (variant == NULL);
+
+  window = g_object_new (SP_TYPE_WINDOW,
+                         "application", self,
+                         NULL);
+  gtk_window_present (GTK_WINDOW (window));
+}
+
+static void
+sysprof_open_capture (GSimpleAction *action,
+                      GVariant      *variant,
+                      gpointer       user_data)
+{
+  GtkApplication *app = user_data;
+  GtkWidget *window;
+  GList *list;
+
+  g_assert (G_IS_APPLICATION (app));
+  g_assert (G_IS_SIMPLE_ACTION (action));
+  g_assert (variant == NULL);
+
+  list = gtk_application_get_windows (app);
+
+  for (; list != NULL; list = list->next)
+    {
+      window = list->data;
+
+      if (SP_IS_WINDOW (window))
+        {
+          SpWindowState state;
+
+          state = sp_window_get_state (SP_WINDOW (window));
+
+          if (state == SP_WINDOW_STATE_EMPTY)
+            {
+              sp_window_open_from_dialog (SP_WINDOW (window));
+              return;
+            }
+        }
+    }
+
+  window = g_object_new (SP_TYPE_WINDOW,
+                         "application", app,
+                         NULL);
+
+  gtk_window_present (GTK_WINDOW (window));
+
+  sp_window_open_from_dialog (SP_WINDOW (window));
+}
+
+static void
+sp_application_init (SpApplication *self)
+{
+  static const GActionEntry actions[] = {
+    { "about",        sysprof_about },
+    { "new-window",   sysprof_new_window },
+    { "open-capture", sysprof_open_capture },
+    { "help",         sysprof_help },
+    { "quit",         sysprof_quit },
+  };
+
+  g_action_map_add_action_entries (G_ACTION_MAP (self), actions, G_N_ELEMENTS (actions), self);
+
+  g_application_set_default (G_APPLICATION (self));
+}
+
+SpApplication *
+sp_application_new (void)
+{
+  return g_object_new (SP_TYPE_APPLICATION,
+                       "application-id", "org.gnome.Sysprof2",
+                       "resource-base-path", "/org/gnome/sysprof",
+                       "flags", G_APPLICATION_HANDLES_OPEN,
+                       NULL);
+}
diff --git a/src/sp-application.h b/src/sp-application.h
new file mode 100644
index 0000000..ab5af6f
--- /dev/null
+++ b/src/sp-application.h
@@ -0,0 +1,34 @@
+/* sp-application.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_APPLICATION_H
+#define SP_APPLICATION_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_APPLICATION (sp_application_get_type())
+
+G_DECLARE_FINAL_TYPE (SpApplication, sp_application, SP, APPLICATION, GtkApplication)
+
+SpApplication *sp_application_new (void);
+
+G_END_DECLS
+
+#endif /* SP_APPLICATION_H */
diff --git a/src/sp-credits.h b/src/sp-credits.h
new file mode 100644
index 0000000..acaf894
--- /dev/null
+++ b/src/sp-credits.h
@@ -0,0 +1,38 @@
+#ifndef SP_CREDITS_H
+#define SP_CREDITS_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+static gchar *sysprof_authors[] = {
+  "Bastien Nocera",
+  "Behdad Esfahbod",
+  "Christian Hergert",
+  "Damien Lespiau",
+  "Geoffrey Keating",
+  "Javier Jardón",
+  "Jeffrey Stedfast",
+  "Kristian Høgsberg",
+  "Kristian Rietvel",
+  "M Joonas Pihlaja",
+  "Matthias Clasen",
+  "Michel Dänzer",
+  "Nix",
+  "Owen Taylor",
+  "Paolo Borelli",
+  "Pascal Terjan",
+  "Pauli Nieminen",
+  "Robert Love",
+  "Søren Sandmann Pedersen",
+  NULL
+};
+
+static gchar *sysprof_artists[] = {
+  "Jakub Steiner",
+  NULL
+};
+
+G_END_DECLS
+
+#endif /* SP_CREDITS_H */
diff --git a/src/sp-window-settings.c b/src/sp-window-settings.c
new file mode 100644
index 0000000..7d60e94
--- /dev/null
+++ b/src/sp-window-settings.c
@@ -0,0 +1,175 @@
+/* sp-window-settings.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#include "sp-window.h"
+#include "sp-window-settings.h"
+
+#define WINDOW_MIN_WIDTH  1200
+#define WINDOW_MIN_HEIGHT  700
+#define SAVE_TIMEOUT_SECS    1
+
+static GSettings *settings;
+
+static gboolean
+sp_window_settings__window_save_settings_cb (gpointer data)
+{
+  GtkWindow *window = data;
+  GdkRectangle geom;
+  gboolean maximized;
+
+  g_assert (GTK_IS_WINDOW (window));
+  g_assert (G_IS_SETTINGS (settings));
+
+  g_object_set_data (G_OBJECT (window), "SETTINGS_HANDLER_ID", NULL);
+
+  gtk_window_get_size (window, &geom.width, &geom.height);
+  gtk_window_get_position (window, &geom.x, &geom.y);
+  maximized = gtk_window_is_maximized (window);
+
+  g_settings_set (settings, "window-size", "(ii)", geom.width, geom.height);
+  g_settings_set (settings, "window-position", "(ii)", geom.x, geom.y);
+  g_settings_set_boolean (settings, "window-maximized", maximized);
+
+  return G_SOURCE_REMOVE;
+}
+
+static gboolean
+sp_window_settings__window_configure_event (GtkWindow         *window,
+                                            GdkEventConfigure *event)
+{
+  guint handler;
+
+  g_assert (GTK_IS_WINDOW (window));
+  g_assert (event != NULL);
+  g_assert (G_IS_SETTINGS (settings));
+
+  handler = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "SETTINGS_HANDLER_ID"));
+
+  if (handler == 0)
+    {
+      handler = g_timeout_add_seconds (SAVE_TIMEOUT_SECS,
+                                       sp_window_settings__window_save_settings_cb,
+                                       window);
+      g_object_set_data (G_OBJECT (window), "SETTINGS_HANDLER_ID", GINT_TO_POINTER (handler));
+    }
+
+  return GDK_EVENT_PROPAGATE;
+}
+
+static void
+sp_window_settings__window_realize (GtkWindow *window)
+{
+  GtkApplication *app;
+  GdkRectangle geom = { 0 };
+  gboolean maximized = FALSE;
+  GList *list;
+  guint count = 0;
+
+  g_assert (GTK_IS_WINDOW (window));
+  g_assert (G_IS_SETTINGS (settings));
+
+  g_settings_get (settings, "window-position", "(ii)", &geom.x, &geom.y);
+  g_settings_get (settings, "window-size", "(ii)", &geom.width, &geom.height);
+  g_settings_get (settings, "window-maximized", "b", &maximized);
+
+  geom.width = MAX (geom.width, WINDOW_MIN_WIDTH);
+  geom.height = MAX (geom.height, WINDOW_MIN_HEIGHT);
+  gtk_window_set_default_size (window, geom.width, geom.height);
+
+  /*
+   * If there are other windows currently visible other than this one,
+   * then ignore positioning and let the window manager decide.
+   */
+  count = 0;
+  app = GTK_APPLICATION (g_application_get_default ());
+  list = gtk_application_get_windows (app);
+  for (; list != NULL; list = list->next)
+    {
+      GtkWindow *ele = list->data;
+
+      if (SP_IS_WINDOW (ele) && (ele != window) &&
+          gtk_widget_get_visible (GTK_WIDGET (window)))
+        count++;
+    }
+
+  if (count == 0)
+    gtk_window_move (window, geom.x, geom.y);
+
+  if (maximized)
+    gtk_window_maximize (window);
+}
+
+static void
+sp_window_settings__window_destroy (GtkWindow *window)
+{
+  guint handler;
+
+  g_assert (GTK_IS_WINDOW (window));
+  g_assert (G_IS_SETTINGS (settings));
+
+  handler = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "SETTINGS_HANDLER_ID"));
+
+  if (handler != 0)
+    {
+      g_source_remove (handler);
+      g_object_set_data (G_OBJECT (window), "SETTINGS_HANDLER_ID", NULL);
+    }
+
+  g_signal_handlers_disconnect_by_func (window,
+                                        G_CALLBACK (sp_window_settings__window_configure_event),
+                                        NULL);
+
+  g_signal_handlers_disconnect_by_func (window,
+                                        G_CALLBACK (sp_window_settings__window_destroy),
+                                        NULL);
+
+  g_signal_handlers_disconnect_by_func (window,
+                                        G_CALLBACK (sp_window_settings__window_realize),
+                                        NULL);
+
+  g_object_unref (settings);
+}
+
+void
+sp_window_settings_register (GtkWindow *window)
+{
+  if (settings == NULL)
+    {
+      settings = g_settings_new ("org.gnome.sysprof2");
+      g_object_add_weak_pointer (G_OBJECT (settings), (gpointer *)&settings);
+    }
+  else
+    {
+      g_object_ref (settings);
+    }
+
+  g_signal_connect (window,
+                    "configure-event",
+                    G_CALLBACK (sp_window_settings__window_configure_event),
+                    NULL);
+
+  g_signal_connect (window,
+                    "destroy",
+                    G_CALLBACK (sp_window_settings__window_destroy),
+                    NULL);
+
+  g_signal_connect (window,
+                    "realize",
+                    G_CALLBACK (sp_window_settings__window_realize),
+                    NULL);
+}
diff --git a/src/sp-window-settings.h b/src/sp-window-settings.h
new file mode 100644
index 0000000..7173e97
--- /dev/null
+++ b/src/sp-window-settings.h
@@ -0,0 +1,30 @@
+/* sp-window-settings.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_WINDOW_SETTINGS_H
+#define SP_WINDOW_SETTINGS_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+void sp_window_settings_register (GtkWindow *window);
+
+G_END_DECLS
+
+#endif /* SP_WINDOW_SETTINGS_H */
diff --git a/src/sp-window.c b/src/sp-window.c
new file mode 100644
index 0000000..6ceb9e6
--- /dev/null
+++ b/src/sp-window.c
@@ -0,0 +1,853 @@
+/* sp-window.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#include <errno.h>
+#include <glib/gi18n.h>
+#include <sysprof.h>
+
+#include "sp-application.h"
+#include "sp-window.h"
+#include "sp-window-settings.h"
+
+struct _SpWindow
+{
+  GtkApplicationWindow  parent_instance;
+
+  SpWindowState         state;
+
+  SpProfiler           *profiler;
+  SpCaptureReader      *reader;
+
+  /* Gtk widget template children */
+  SpCallgraphView      *callgraph_view;
+  SpEmptyStateView     *empty_view;
+  GtkMenuButton        *gear_menu_button;
+  GtkInfoBar           *info_bar;
+  GtkLabel             *info_bar_label;
+  GtkRevealer          *info_bar_revealer;
+  SpProfilerMenuButton *profiler_menu_button;
+  SpRecordingStateView *recording_view;
+  GtkButton            *record_button;
+  GtkLabel             *subtitle;
+  GtkLabel             *stat_label;
+  GtkLabel             *title;
+  GtkStack             *view_stack;
+
+  guint                 stats_handler;
+};
+
+G_DEFINE_TYPE (SpWindow, sp_window, GTK_TYPE_APPLICATION_WINDOW)
+
+static void sp_window_set_state (SpWindow      *self,
+                                 SpWindowState  state);
+
+enum {
+  START_RECORDING,
+  STOP_RECORDING,
+  N_SIGNALS
+};
+
+static guint signals [N_SIGNALS];
+
+static void sp_window_set_profiler (SpWindow   *self,
+                                    SpProfiler *profiler);
+
+static void
+sp_window_notify_user (SpWindow       *self,
+                       GtkMessageType  message_type,
+                       const gchar    *format,
+                       ...)
+{
+  g_autofree gchar *str = NULL;
+  va_list args;
+
+  g_assert (SP_IS_WINDOW (self));
+  g_assert (format != NULL);
+
+  va_start (args, format);
+  str = g_strdup_vprintf (format, args);
+  va_end (args);
+
+  gtk_info_bar_set_message_type (self->info_bar, message_type);
+  gtk_label_set_label (self->info_bar_label, str);
+  gtk_revealer_set_reveal_child (self->info_bar_revealer, TRUE);
+}
+
+static void
+sp_window_action_set (SpWindow    *self,
+                      const gchar *action_name,
+                      const gchar *first_property,
+                      ...)
+{
+  gpointer action;
+  va_list args;
+
+  g_assert (SP_IS_WINDOW (self));
+  g_assert (action_name != NULL);
+
+  action = g_action_map_lookup_action (G_ACTION_MAP (self), action_name);
+
+  if (action == NULL)
+    {
+      g_warning ("Failed to locate action \"%s\"", action_name);
+      return;
+    }
+
+  va_start (args, first_property);
+  g_object_set_valist (action, first_property, args);
+  va_end (args);
+}
+
+static gboolean
+sp_window_update_stats (gpointer data)
+{
+  SpWindow *self = data;
+
+  g_assert (SP_IS_WINDOW (self));
+
+  if (self->profiler != NULL)
+    {
+      SpCaptureWriter *writer;
+
+      if (NULL != (writer = sp_profiler_get_writer (self->profiler)))
+        {
+          g_autofree gchar *str = NULL;
+          SpCaptureStat stbuf;
+          guint count;
+
+          sp_capture_writer_stat (writer, &stbuf);
+
+          count = stbuf.frame_count[SP_CAPTURE_FRAME_SAMPLE];
+          str = g_strdup_printf (_("Samples: %u"), count);
+          gtk_label_set_label (self->stat_label, str);
+        }
+    }
+
+  return G_SOURCE_CONTINUE;
+}
+
+
+static void
+sp_window_update_subtitle (SpWindow *self)
+{
+  g_autofree gchar *relative = NULL;
+  const gchar *filename;
+  const gchar *date;
+  GTimeVal tv;
+
+  g_assert (SP_IS_WINDOW (self));
+  g_assert (self->reader != NULL);
+
+  if (NULL != (filename = sp_capture_reader_get_filename (self->reader)))
+    {
+      g_autoptr(GFile) home = NULL;
+      g_autoptr(GFile) file = NULL;
+
+      file = g_file_new_for_path (filename);
+      home = g_file_new_for_path (g_get_home_dir ());
+
+      if (g_file_has_prefix (file, home))
+        filename = relative = g_file_get_relative_path (home, file);
+    }
+
+  if (filename == NULL)
+    filename = _("[Memory Capture]");
+
+  date = sp_capture_reader_get_time (self->reader);
+
+  if (g_time_val_from_iso8601 (date, &tv))
+    {
+      g_autoptr(GDateTime) dt = NULL;
+      g_autofree gchar *str = NULL;
+      g_autofree gchar *label = NULL;
+
+      dt = g_date_time_new_from_timeval_local (&tv);
+      str = g_date_time_format (dt, "%x %X");
+
+      label = g_strdup_printf (_("%s - %s"), filename, str);
+
+      gtk_label_set_label (self->subtitle, label);
+    }
+  else
+    gtk_label_set_label (self->subtitle, filename);
+}
+
+static void
+sp_window_build_profile_cb (GObject      *object,
+                            GAsyncResult *result,
+                            gpointer      user_data)
+{
+  SpProfile *profile = (SpProfile *)object;
+  g_autoptr(SpWindow) self = user_data;
+  g_autoptr(GError) error = NULL;
+
+  g_assert (SP_IS_CALLGRAPH_PROFILE (profile));
+  g_assert (SP_IS_WINDOW (self));
+  g_assert (G_IS_ASYNC_RESULT (result));
+
+  if (!sp_profile_generate_finish (profile, result, &error))
+    {
+      sp_window_notify_user (self, GTK_MESSAGE_ERROR, "%s", error->message);
+      sp_window_set_state (self, SP_WINDOW_STATE_EMPTY);
+      return;
+    }
+
+  sp_callgraph_view_set_profile (self->callgraph_view, SP_CALLGRAPH_PROFILE (profile));
+  sp_window_set_state (self, SP_WINDOW_STATE_BROWSING);
+}
+
+static void
+sp_window_build_profile (SpWindow *self)
+{
+  g_autoptr(SpProfile) profile = NULL;
+
+  g_assert (SP_IS_WINDOW (self));
+  g_assert (self->reader != NULL);
+
+  profile = sp_callgraph_profile_new ();
+  sp_profile_set_reader (profile, self->reader);
+  sp_profile_generate (profile,
+                       NULL,
+                       sp_window_build_profile_cb,
+                       g_object_ref (self));
+}
+
+static void
+add_class (gpointer     widget,
+           const gchar *name)
+{
+  g_assert (GTK_IS_WIDGET (widget));
+
+  gtk_style_context_add_class (gtk_widget_get_style_context (widget), name);
+}
+
+static void
+remove_class (gpointer     widget,
+              const gchar *name)
+{
+  g_assert (GTK_IS_WIDGET (widget));
+
+  gtk_style_context_remove_class (gtk_widget_get_style_context (widget), name);
+}
+
+static void
+sp_window_set_state (SpWindow      *self,
+                     SpWindowState  state)
+{
+  g_autoptr(SpProfiler) profiler = NULL;
+
+  g_assert (SP_IS_WINDOW (self));
+
+  if (self->state == state)
+    return;
+
+  self->state = state;
+
+  switch (state)
+    {
+    case SP_WINDOW_STATE_EMPTY:
+    case SP_WINDOW_STATE_FAILED:
+      profiler = sp_profiler_new ();
+
+      gtk_button_set_label (self->record_button, _("Record"));
+      gtk_widget_set_sensitive (GTK_WIDGET (self->record_button), TRUE);
+      add_class (self->record_button, "suggsted-action");
+      remove_class (self->record_button, "destructive-action");
+      if (state == SP_WINDOW_STATE_FAILED)
+        gtk_stack_set_visible_child_name (self->view_stack, "failed");
+      else
+        gtk_stack_set_visible_child_name (self->view_stack, "empty");
+      gtk_label_set_label (self->subtitle, _("Not running"));
+      sp_callgraph_view_set_profile (self->callgraph_view, NULL);
+      gtk_widget_set_visible (GTK_WIDGET (self->stat_label), FALSE);
+      g_clear_pointer (&self->reader, sp_capture_reader_unref);
+      sp_window_set_profiler (self, profiler);
+      sp_window_action_set (self, "close-capture", "enabled", FALSE, NULL);
+      sp_window_action_set (self, "save-capture", "enabled", FALSE, NULL);
+      break;
+
+    case SP_WINDOW_STATE_RECORDING:
+      gtk_button_set_label (self->record_button, _("Stop"));
+      gtk_widget_set_sensitive (GTK_WIDGET (self->record_button), TRUE);
+      remove_class (self->record_button, "suggsted-action");
+      add_class (self->record_button, "destructive-action");
+      gtk_stack_set_visible_child_name (self->view_stack, "recording");
+      gtk_label_set_label (self->subtitle, _("Recording…"));
+      gtk_widget_set_visible (GTK_WIDGET (self->stat_label), TRUE);
+      g_clear_pointer (&self->reader, sp_capture_reader_unref);
+      sp_callgraph_view_set_profile (self->callgraph_view, NULL);
+      sp_window_action_set (self, "close-capture", "enabled", FALSE, NULL);
+      sp_window_action_set (self, "save-capture", "enabled", FALSE, NULL);
+      break;
+
+    case SP_WINDOW_STATE_PROCESSING:
+      gtk_widget_set_sensitive (GTK_WIDGET (self->record_button), FALSE);
+      gtk_label_set_label (self->subtitle, _("Building profile…"));
+      sp_window_action_set (self, "close-capture", "enabled", FALSE, NULL);
+      sp_window_action_set (self, "save-capture", "enabled", FALSE, NULL);
+      sp_window_build_profile (self);
+      break;
+
+    case SP_WINDOW_STATE_BROWSING:
+      gtk_button_set_label (self->record_button, _("Record"));
+      gtk_widget_set_sensitive (GTK_WIDGET (self->record_button), TRUE);
+      add_class (self->record_button, "suggsted-action");
+      remove_class (self->record_button, "destructive-action");
+      gtk_widget_set_visible (GTK_WIDGET (self->stat_label), TRUE);
+      gtk_stack_set_visible_child_name (self->view_stack, "browsing");
+      sp_window_update_stats (self);
+      sp_window_update_subtitle (self);
+      sp_window_action_set (self, "close-capture", "enabled", TRUE, NULL);
+      sp_window_action_set (self, "save-capture", "enabled", TRUE, NULL);
+
+      break;
+
+    default:
+      g_warning ("Unknown state: %0d", state);
+      break;
+    }
+}
+
+static void
+sp_window_enable_stats (SpWindow *self)
+{
+  g_assert (SP_IS_WINDOW (self));
+
+  if (self->stats_handler == 0)
+    self->stats_handler =
+      g_timeout_add_seconds (1, sp_window_update_stats, self);
+}
+
+static void
+sp_window_disable_stats (SpWindow *self)
+{
+  g_assert (SP_IS_WINDOW (self));
+
+  if (self->stats_handler != 0)
+    {
+      g_source_remove (self->stats_handler);
+      self->stats_handler = 0;
+    }
+}
+
+static void
+sp_window_add_sources (SpWindow   *window,
+                       SpProfiler *profiler)
+{
+  g_autoptr(SpSource) proc_source = NULL;
+  g_autoptr(SpSource) perf_source = NULL;
+
+  g_assert (SP_IS_WINDOW (window));
+  g_assert (SP_IS_PROFILER (profiler));
+
+  proc_source = sp_proc_source_new ();
+  sp_profiler_add_source (profiler, proc_source);
+
+  perf_source = sp_perf_source_new ();
+  sp_profiler_add_source (profiler, perf_source);
+}
+
+static void
+sp_window_start_recording (SpWindow *self)
+{
+  g_assert (SP_IS_WINDOW (self));
+
+  if (self->state == SP_WINDOW_STATE_RECORDING)
+    {
+      /* SpProfiler::stopped will move us to generating */
+      gtk_label_set_label (self->subtitle, _("Stopping…"));
+      sp_profiler_stop (self->profiler);
+      return;
+    }
+
+  if ((self->state == SP_WINDOW_STATE_EMPTY) ||
+      (self->state == SP_WINDOW_STATE_FAILED) ||
+      (self->state == SP_WINDOW_STATE_BROWSING))
+    {
+      sp_window_add_sources (self, self->profiler);
+      sp_window_set_state (self, SP_WINDOW_STATE_RECORDING);
+      sp_window_enable_stats (self);
+      sp_profiler_start (self->profiler);
+      return;
+    }
+}
+
+static void
+sp_window_stop_recording (SpWindow *self)
+{
+  g_assert (SP_IS_WINDOW (self));
+
+  if (self->state == SP_WINDOW_STATE_RECORDING)
+    {
+      if (self->profiler != NULL)
+        sp_profiler_stop (self->profiler);
+    }
+}
+
+static void
+sp_window_hide_info_bar_revealer (SpWindow *self)
+{
+  g_assert (SP_IS_WINDOW (self));
+
+  gtk_revealer_set_reveal_child (self->info_bar_revealer, FALSE);
+}
+
+static void
+sp_window_profiler_stopped (SpWindow   *self,
+                            SpProfiler *profiler)
+{
+  g_autoptr(SpCaptureReader) reader = NULL;
+  g_autoptr(GError) error = NULL;
+  SpCaptureWriter *writer;
+
+  g_assert (SP_IS_WINDOW (self));
+  g_assert (SP_IS_PROFILER (profiler));
+
+  sp_window_disable_stats (self);
+
+  if (self->state == SP_WINDOW_STATE_FAILED)
+    return;
+
+  writer = sp_profiler_get_writer (profiler);
+  reader = sp_capture_writer_create_reader (writer, &error);
+
+  if (reader == NULL)
+    {
+      sp_window_notify_user (self, GTK_MESSAGE_ERROR, "%s", error->message);
+      sp_window_set_state (self, SP_WINDOW_STATE_EMPTY);
+      return;
+    }
+
+  g_clear_pointer (&self->reader, sp_capture_reader_unref);
+  self->reader = g_steal_pointer (&reader);
+
+  sp_window_build_profile (self);
+}
+
+static void
+sp_window_profiler_failed (SpWindow     *self,
+                           const GError *reason,
+                           SpProfiler   *profiler)
+{
+  g_assert (SP_IS_WINDOW (self));
+  g_assert (reason != NULL);
+  g_assert (SP_IS_PROFILER (profiler));
+
+  sp_window_notify_user (self, GTK_MESSAGE_ERROR, "%s", reason->message);
+  sp_window_set_state (self, SP_WINDOW_STATE_FAILED);
+}
+
+static void
+sp_window_set_profiler (SpWindow   *self,
+                        SpProfiler *profiler)
+{
+  g_assert (SP_IS_WINDOW (self));
+  g_assert (SP_IS_PROFILER (profiler));
+
+  if (self->profiler != profiler)
+    {
+      if (self->profiler != NULL)
+        {
+          if (sp_profiler_get_is_running (self->profiler))
+            sp_profiler_stop (self->profiler);
+          sp_profiler_menu_button_set_profiler (self->profiler_menu_button, NULL);
+          sp_recording_state_view_set_profiler (self->recording_view, NULL);
+          g_clear_object (&self->profiler);
+        }
+
+      if (profiler != NULL)
+        {
+          if (!sp_profiler_get_is_mutable (profiler))
+            {
+              g_warning ("Ignoring attempt to set profiler to an already running session!");
+              return;
+            }
+
+          self->profiler = g_object_ref (profiler);
+
+          g_signal_connect_object (profiler,
+                                   "stopped",
+                                   G_CALLBACK (sp_window_profiler_stopped),
+                                   self,
+                                   G_CONNECT_SWAPPED);
+
+          g_signal_connect_object (profiler,
+                                   "failed",
+                                   G_CALLBACK (sp_window_profiler_failed),
+                                   self,
+                                   G_CONNECT_SWAPPED);
+
+          sp_profiler_menu_button_set_profiler (self->profiler_menu_button, profiler);
+          sp_recording_state_view_set_profiler (self->recording_view, profiler);
+        }
+    }
+}
+
+static void
+sp_window_open_capture (GSimpleAction *action,
+                        GVariant      *variant,
+                        gpointer       user_data)
+{
+  SpWindow *self = user_data;
+
+  g_assert (G_IS_SIMPLE_ACTION (action));
+  g_assert (variant == NULL);
+  g_assert (SP_IS_WINDOW (self));
+
+  sp_window_open_from_dialog (self);
+}
+
+static void
+sp_window_save_capture (GSimpleAction *action,
+                        GVariant      *variant,
+                        gpointer       user_data)
+{
+  g_autoptr(SpCaptureReader) reader = NULL;
+  SpWindow *self = user_data;
+  GtkWidget *dialog;
+  GtkResponseType response;
+
+  g_assert (G_IS_SIMPLE_ACTION (action));
+  g_assert (variant == NULL);
+  g_assert (SP_IS_WINDOW (self));
+
+  if (self->reader == NULL)
+    return;
+
+  reader = sp_capture_reader_ref (self->reader);
+
+  dialog = gtk_file_chooser_dialog_new (_("Save Capture As"),
+                                        GTK_WINDOW (self),
+                                        GTK_FILE_CHOOSER_ACTION_SAVE,
+                                        _("Cancel"), GTK_RESPONSE_CANCEL,
+                                        _("Save"), GTK_RESPONSE_OK,
+                                        NULL);
+
+  gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE);
+  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+  response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+  if (response == GTK_RESPONSE_OK)
+    {
+      g_autofree gchar *filename = NULL;
+      g_autoptr(GError) error = NULL;
+
+      filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+
+      /* this should really be done outside the main loop. */
+      if (!sp_capture_reader_save_as (reader, filename, &error))
+        {
+          sp_window_notify_user (self,
+                                 GTK_MESSAGE_ERROR,
+                                 _("An error occurred while attempting to save your capture: %s"),
+                                 error->message);
+          goto failure;
+        }
+    }
+
+failure:
+  gtk_widget_destroy (dialog);
+}
+
+static void
+sp_window_close_capture (GSimpleAction *action,
+                         GVariant      *variant,
+                         gpointer       user_data)
+{
+  SpWindow *self = user_data;
+
+  g_assert (G_IS_SIMPLE_ACTION (action));
+  g_assert (variant == NULL);
+  g_assert (SP_IS_WINDOW (self));
+
+  sp_window_set_state (self, SP_WINDOW_STATE_EMPTY);
+}
+
+static void
+sp_window_record_button_clicked (SpWindow  *self,
+                                 GtkButton *button)
+{
+  g_assert (SP_IS_WINDOW (self));
+  g_assert (GTK_IS_BUTTON (button));
+
+  sp_window_start_recording (self);
+}
+
+static void
+sp_window_destroy (GtkWidget *widget)
+{
+  SpWindow *self = (SpWindow *)widget;
+
+  g_clear_object (&self->profiler);
+  g_clear_pointer (&self->reader, sp_capture_reader_unref);
+  sp_window_disable_stats (self);
+
+  GTK_WIDGET_CLASS (sp_window_parent_class)->destroy (widget);
+}
+
+static void
+sp_window_constructed (GObject *object)
+{
+  SpWindow *self = (SpWindow *)object;
+  g_autoptr(SpProfiler) profiler = NULL;
+
+  G_OBJECT_CLASS (sp_window_parent_class)->constructed (object);
+
+  profiler = sp_profiler_new ();
+  sp_window_set_profiler (self, profiler);
+
+  sp_window_set_state (self, SP_WINDOW_STATE_EMPTY);
+}
+
+static void
+sp_window_class_init (SpWindowClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GtkBindingSet *binding_set;
+
+  object_class->constructed = sp_window_constructed;
+
+  widget_class->destroy = sp_window_destroy;
+
+  signals [START_RECORDING] =
+    g_signal_new_class_handler ("start-recording",
+                                G_TYPE_FROM_CLASS (klass),
+                                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                                G_CALLBACK (sp_window_start_recording),
+                                NULL, NULL, NULL, G_TYPE_NONE, 0);
+
+  signals [STOP_RECORDING] =
+    g_signal_new_class_handler ("stop-recording",
+                                G_TYPE_FROM_CLASS (klass),
+                                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                                G_CALLBACK (sp_window_stop_recording),
+                                NULL, NULL, NULL, G_TYPE_NONE, 0);
+
+  binding_set = gtk_binding_set_by_class (klass);
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0, "stop-recording", 0);
+
+  gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sp-window.ui");
+  gtk_widget_class_bind_template_child (widget_class, SpWindow, callgraph_view);
+  gtk_widget_class_bind_template_child (widget_class, SpWindow, empty_view);
+  gtk_widget_class_bind_template_child (widget_class, SpWindow, gear_menu_button);
+  gtk_widget_class_bind_template_child (widget_class, SpWindow, info_bar);
+  gtk_widget_class_bind_template_child (widget_class, SpWindow, info_bar_label);
+  gtk_widget_class_bind_template_child (widget_class, SpWindow, info_bar_revealer);
+  gtk_widget_class_bind_template_child (widget_class, SpWindow, profiler_menu_button);
+  gtk_widget_class_bind_template_child (widget_class, SpWindow, record_button);
+  gtk_widget_class_bind_template_child (widget_class, SpWindow, recording_view);
+  gtk_widget_class_bind_template_child (widget_class, SpWindow, stat_label);
+  gtk_widget_class_bind_template_child (widget_class, SpWindow, subtitle);
+  gtk_widget_class_bind_template_child (widget_class, SpWindow, title);
+  gtk_widget_class_bind_template_child (widget_class, SpWindow, view_stack);
+}
+
+static void
+sp_window_init (SpWindow *self)
+{
+  GAction *action;
+  static GActionEntry action_entries[] = {
+    { "close-capture", sp_window_close_capture },
+    { "open-capture",  sp_window_open_capture },
+    { "save-capture",  sp_window_save_capture },
+  };
+  GtkApplication *app;
+  GMenu *menu;
+
+  gtk_widget_init_template (GTK_WIDGET (self));
+
+  /*
+   * Hookup widget signals.
+   */
+
+  g_signal_connect_object (self->info_bar,
+                           "response",
+                           G_CALLBACK (sp_window_hide_info_bar_revealer),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (self->info_bar,
+                           "close",
+                           G_CALLBACK (sp_window_hide_info_bar_revealer),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (self->record_button,
+                           "clicked",
+                           G_CALLBACK (sp_window_record_button_clicked),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  /*
+   * Setup actions for the window.
+   */
+
+  g_action_map_add_action_entries (G_ACTION_MAP (self),
+                                   action_entries,
+                                   G_N_ELEMENTS (action_entries),
+                                   self);
+
+  /*
+   * Setup our gear (hamburger) menu.
+   */
+
+  app = GTK_APPLICATION (g_application_get_default ());
+  menu = gtk_application_get_menu_by_id (app, "gear-menu");
+  gtk_menu_button_set_menu_model (self->gear_menu_button, G_MENU_MODEL (menu));
+
+  /*
+   * Restore previous window settings.
+   */
+
+  sp_window_settings_register (GTK_WINDOW (self));
+
+  /*
+   * Set default focus to the record button for quick workflow of
+   * launch, enter, escape, view.
+   */
+  gtk_window_set_focus (GTK_WINDOW (self), GTK_WIDGET (self->record_button));
+}
+
+static void
+sp_window_open_cb (GObject      *object,
+                   GAsyncResult *result,
+                   gpointer      user_data)
+{
+  SpWindow *self = (SpWindow *)object;
+  g_autoptr(SpCaptureReader) reader = NULL;
+  g_autoptr(GError) error = NULL;
+
+  g_assert (SP_IS_WINDOW (self));
+  g_assert (G_IS_TASK (result));
+
+  reader = g_task_propagate_pointer (G_TASK (result), &error);
+
+  if (reader == NULL)
+    {
+      sp_window_notify_user (self,
+                             GTK_MESSAGE_ERROR,
+                             "%s", error->message);
+      return;
+    }
+
+  g_clear_pointer (&self->reader, sp_capture_reader_unref);
+  self->reader = g_steal_pointer (&reader);
+
+  sp_window_set_state (self, SP_WINDOW_STATE_PROCESSING);
+}
+
+static void
+sp_window_open_worker (GTask        *task,
+                       gpointer      source_object,
+                       gpointer      task_data,
+                       GCancellable *cancellable)
+{
+  g_autofree gchar *path = NULL;
+  SpCaptureReader *reader;
+  GFile *file = task_data;
+  GError *error = NULL;
+
+  g_assert (G_IS_TASK (task));
+  g_assert (SP_IS_WINDOW (source_object));
+  g_assert (G_IS_FILE (file));
+
+  path = g_file_get_path (file);
+
+  if (NULL == (reader = sp_capture_reader_new (path, &error)))
+    {
+      g_task_return_error (task, error);
+      return;
+    }
+
+  g_task_return_pointer (task, reader, (GDestroyNotify)sp_capture_reader_unref);
+}
+
+void
+sp_window_open (SpWindow *self,
+                GFile    *file)
+{
+  g_autoptr(GTask) task = NULL;
+
+  g_return_if_fail (SP_IS_WINDOW (self));
+  g_return_if_fail (G_IS_FILE (file));
+
+  if (!g_file_is_native (file))
+    {
+      sp_window_notify_user (self,
+                             GTK_MESSAGE_ERROR,
+                             _("The file \"%s\" could not be opened. Only local files are supported."),
+                             g_file_get_uri (file));
+      return;
+    }
+
+  task = g_task_new (self, NULL, sp_window_open_cb, NULL);
+  g_task_set_task_data (task, g_object_ref (file), g_object_unref);
+  g_task_run_in_thread (task, sp_window_open_worker);
+}
+
+SpWindowState
+sp_window_get_state (SpWindow *self)
+{
+  g_return_val_if_fail (SP_IS_WINDOW (self), SP_WINDOW_STATE_0);
+
+  return self->state;
+}
+
+void
+sp_window_open_from_dialog (SpWindow *self)
+{
+  GtkFileFilter *filter;
+  GtkDialog *dialog;
+
+  g_assert (SP_IS_WINDOW (self));
+
+  dialog = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG,
+                         "action", GTK_FILE_CHOOSER_ACTION_OPEN,
+                         "title", _("Open Capture"),
+                         "transient-for", self,
+                         NULL);
+
+  gtk_dialog_add_buttons (dialog,
+                          _("Cancel"), GTK_RESPONSE_CANCEL,
+                          _("Open"), GTK_RESPONSE_OK,
+                          NULL);
+
+  gtk_dialog_set_default_response (dialog, GTK_RESPONSE_OK);
+
+  filter = gtk_file_filter_new ();
+  gtk_file_filter_set_name (filter, _("Sysprof Captures"));
+  gtk_file_filter_add_pattern (filter, "*.syscap");
+  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
+
+  filter = gtk_file_filter_new ();
+  gtk_file_filter_set_name (filter, _("All Files"));
+  gtk_file_filter_add_pattern (filter, "*");
+  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
+
+  if (gtk_dialog_run (dialog) == GTK_RESPONSE_OK)
+    {
+      g_autoptr(GFile) file = NULL;
+
+      file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+      sp_window_open (self, file);
+    }
+
+  gtk_widget_destroy (GTK_WIDGET (dialog));
+}
diff --git a/src/sp-window.h b/src/sp-window.h
new file mode 100644
index 0000000..5f6bcb3
--- /dev/null
+++ b/src/sp-window.h
@@ -0,0 +1,52 @@
+/* sp-window.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef SP_WINDOW_H
+#define SP_WINDOW_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define SP_TYPE_WINDOW (sp_window_get_type())
+
+G_DECLARE_FINAL_TYPE (SpWindow, sp_window, SP, WINDOW, GtkApplicationWindow)
+
+typedef enum
+{
+  SP_WINDOW_STATE_0,
+  SP_WINDOW_STATE_EMPTY,
+  SP_WINDOW_STATE_FAILED,
+  SP_WINDOW_STATE_RECORDING,
+  SP_WINDOW_STATE_PROCESSING,
+  SP_WINDOW_STATE_BROWSING,
+} SpWindowState;
+
+SpWindowState  sp_window_get_state          (SpWindow  *self);
+gboolean       sp_window_get_recording      (SpWindow  *self);
+GFile         *sp_window_get_capture_file   (SpWindow  *self);
+void           sp_window_set_capture_file   (SpWindow  *self,
+                                             GFile     *capture_file);
+void           sp_window_open               (SpWindow  *self,
+                                             GFile     *file);
+void           sp_window_open_from_dialog   (SpWindow  *self);
+
+G_END_DECLS
+
+#endif /* SP_WINDOW_H */
+
diff --git a/src/sysprof.c b/src/sysprof.c
index 8fec7f7..1ad8158 100644
--- a/src/sysprof.c
+++ b/src/sysprof.c
@@ -1,10 +1,10 @@
-/* Sysprof -- Sampling, systemwide CPU profiler
- * Copyright 2004, Red Hat, Inc.
- * Copyright 2004, 2005, 2006, 2007, 2008, Soeren Sandmann
+/* main.c
  *
- * This program is free software; you can redistribute it and/or modify
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * 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,
@@ -13,1723 +13,26 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-#include <config.h>
 
+#include <glib/gi18n.h>
 #include <gtk/gtk.h>
-#include <glade/glade.h>
-#include <errno.h>
-#include <glib/gprintf.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "footreestore.h"
-#include "treeviewutils.h"
-#include "profile.h"
-#include "collector.h"
-
-/* FIXME - not10 */
-#define _(a) a
-
-#define APPLICATION_NAME "System Profiler"
-
-typedef struct Application Application;
-
-typedef enum
-{
-    INITIAL,
-    DISPLAYING,
-    PROFILING
-} State;
-
-struct Application
-{
-    Collector *                collector;
-
-    State              state;
-    GdkPixbuf *                icon;
-
-    GtkWidget *                main_window;
-
-    GtkTreeView *      object_view;
-    GtkTreeView *      callers_view;
-    GtkTreeView *      descendants_view;
-
-    GtkWidget *                start_button;
-    GtkWidget *                profile_button;
-    GtkWidget *                reset_button;
-    GtkWidget *                save_as_button;
-    GtkWidget *                dummy_button;
-
-    GtkWidget *                start_item;
-    GtkWidget *                profile_item;
-    GtkWidget *                reset_item;
-    GtkWidget *                save_as_item;
-    GtkWidget *                open_item;
-    GtkWidget *                screenshot_item;
-    GtkWidget *                about_item;
-    GtkWidget *                quit_item;
-    GtkWidget *                hpaned;
-    GtkWidget *                vpaned;
-
-    GtkTreeSelection * object_selection;
-
-    GtkWidget *                samples_label;
-    GtkWidget *                samples_hbox;
-
-    gboolean           screenshot_window_visible;
-    GtkWidget *                screenshot_textview;
-    GtkWidget *                screenshot_close_button;
-    GtkWidget *         screenshot_window;
-
-    Profile *          profile;
-    ProfileDescendant * descendants;
-    ProfileCaller *    callers;
-
-    int                        timeout_id;
-    int                        update_screenshot_id;
-
-    char *             loaded_profile;
-
-    gboolean           inhibit_forced_redraw;
-};
-
-static void update_screenshot_window (Application *app);
-
-static void
-show_samples (Application *app)
-{
-    char *label;
-    int n_samples;
-
-    switch (app->state)
-    {
-    case INITIAL:
-       n_samples = 0;
-       break;
-
-    case PROFILING:
-       n_samples = collector_get_n_samples (app->collector);
-       break;
-
-    case DISPLAYING:
-       n_samples = profile_get_size (app->profile);
-       break;
-
-    default:
-       g_assert_not_reached();
-       break;
-    }
-
-    label = g_strdup_printf ("%d", n_samples);
-
-    gtk_label_set_label (GTK_LABEL (app->samples_label), label);
-
-    g_free (label);
-}
-
-static gboolean
-show_samples_timeout (gpointer data)
-{
-    Application *app = data;
-
-    show_samples (app);
-
-    app->timeout_id = 0;
-
-    return FALSE;
-}
-
-static void
-queue_show_samples (Application *app)
-{
-    if (!app->timeout_id)
-       app->timeout_id = g_timeout_add (225, show_samples_timeout, app);
-}
-
-static void
-update_sensitivity (Application *app)
-{
-    gboolean sensitive_profile_button;
-    gboolean sensitive_save_as_button;
-    gboolean sensitive_start_button;
-    gboolean sensitive_tree_views;
-    gboolean sensitive_samples_hbox;
-    gboolean sensitive_reset_button;
-
-    GtkWidget *active_radio_button;
-
-    gboolean has_samples;
-
-    switch (app->state)
-    {
-    case INITIAL:
-       sensitive_profile_button = FALSE;
-       sensitive_save_as_button = FALSE;
-       sensitive_start_button = TRUE;
-       sensitive_reset_button = FALSE;
-       sensitive_tree_views = FALSE;
-       sensitive_samples_hbox = FALSE;
-       active_radio_button = app->dummy_button;
-       break;
-
-    case PROFILING:
-       has_samples = (collector_get_n_samples (app->collector) > 0);
-
-       sensitive_profile_button = has_samples;
-       sensitive_save_as_button = has_samples;
-       sensitive_reset_button = has_samples;
-       sensitive_start_button = TRUE;
-       sensitive_tree_views = FALSE;
-       sensitive_samples_hbox = TRUE;
-       active_radio_button = app->start_button;
-       break;
-
-    case DISPLAYING:
-       sensitive_profile_button = TRUE;
-       sensitive_save_as_button = TRUE;
-       sensitive_start_button = TRUE;
-       sensitive_tree_views = TRUE;
-       sensitive_reset_button = TRUE;
-       sensitive_samples_hbox = FALSE;
-       active_radio_button = app->profile_button;
-       break;
-
-    default:
-       g_assert_not_reached();
-       break;
-    }
-
-    gtk_toggle_tool_button_set_active (
-       GTK_TOGGLE_TOOL_BUTTON (active_radio_button), TRUE);
-
-    /* "profile" widgets */
-    gtk_widget_set_sensitive (GTK_WIDGET (app->profile_button),
-                             sensitive_profile_button);
-    gtk_widget_set_sensitive (GTK_WIDGET (app->profile_item),
-                             sensitive_profile_button);
-
-    /* "save as" widgets */
-    gtk_widget_set_sensitive (GTK_WIDGET (app->save_as_button),
-                             sensitive_save_as_button);
-    gtk_widget_set_sensitive (app->save_as_item,
-                             sensitive_save_as_button);
-
-    /* "start" widgets */
-    gtk_widget_set_sensitive (GTK_WIDGET (app->start_button),
-                             sensitive_start_button);
-    gtk_widget_set_sensitive (GTK_WIDGET (app->start_item),
-                             sensitive_start_button);
-
-#if 0
-    /* FIXME - not10: gtk+ doesn't handle changes in sensitivity in response
-     * to a click on the same button very well
-     */
-    gtk_widget_set_sensitive (GTK_WIDGET (app->reset_button),
-                             sensitive_reset_button);
-    gtk_widget_set_sensitive (GTK_WIDGET (app->reset_item),
-                             sensitive_reset_button);
-#endif
-
-    gtk_widget_set_sensitive (GTK_WIDGET (app->object_view), sensitive_tree_views);
-    gtk_widget_set_sensitive (GTK_WIDGET (app->callers_view), sensitive_tree_views);
-    gtk_widget_set_sensitive (GTK_WIDGET (app->descendants_view), sensitive_tree_views);
-    gtk_widget_set_sensitive (GTK_WIDGET (app->samples_hbox), sensitive_samples_hbox);
-
-    if (app->screenshot_window_visible)
-       gtk_widget_show (app->screenshot_window);
-    else
-       gtk_widget_hide (app->screenshot_window);
-
-    gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (app->screenshot_item),
-                                   app->screenshot_window_visible);
-
-    show_samples (app);
-}
-
-static void
-set_busy (GtkWidget *widget,
-         gboolean   busy)
-{
-    GdkCursor *cursor;
-    GdkWindow *window;
-
-    if (busy)
-       cursor = gdk_cursor_new (GDK_WATCH);
-    else
-       cursor = NULL;
-
-    if (GTK_IS_TEXT_VIEW (widget))
-       window = gtk_text_view_get_window (GTK_TEXT_VIEW (widget), GTK_TEXT_WINDOW_TEXT);
-    else
-       window = widget->window;
-
-    gdk_window_set_cursor (window, cursor);
-
-    if (cursor)
-       gdk_cursor_unref (cursor);
-
-    gdk_flush();
-}
-
-static void
-set_application_title (Application *app,
-                      const char * name)
-{
-    char *new_name;
-    if (name)
-       new_name = g_path_get_basename (name);
-    else
-       new_name = NULL;
-
-    if (app->loaded_profile)
-       g_free (app->loaded_profile);
-
-    app->loaded_profile = new_name;
-
-    if (app->loaded_profile)
-    {
-       gtk_window_set_title (GTK_WINDOW (app->main_window),
-                             app->loaded_profile);
-    }
-    else
-    {
-       gtk_window_set_title (GTK_WINDOW (app->main_window),
-                             APPLICATION_NAME);
-    }
-}
-
-static void
-delete_data (Application *app)
-{
-    if (app->profile)
-    {
-       profile_free (app->profile);
-       app->profile = NULL;
-
-       gtk_tree_view_set_model (GTK_TREE_VIEW (app->object_view), NULL);
-       gtk_tree_view_set_model (GTK_TREE_VIEW (app->callers_view), NULL);
-       gtk_tree_view_set_model (GTK_TREE_VIEW (app->descendants_view), NULL);
-    }
-
-    collector_reset (app->collector);
-
-    set_application_title (app, NULL);
-}
-
-static void
-sorry (GtkWidget *parent_window,
-       const gchar *format,
-       ...)
-{
-    va_list args;
-    char *message;
-    GtkWidget *dialog;
-
-    va_start (args, format);
-    g_vasprintf (&message, format, args);
-    va_end (args);
-
-    dialog = gtk_message_dialog_new (parent_window ? GTK_WINDOW (parent_window) : NULL,
-                                    GTK_DIALOG_DESTROY_WITH_PARENT,
-                                    GTK_MESSAGE_WARNING,
-                                    GTK_BUTTONS_OK, "%s", message);
-    g_free (message);
-
-    gtk_window_set_title (GTK_WINDOW (dialog), APPLICATION_NAME " Warning");
-
-    gtk_dialog_run (GTK_DIALOG (dialog));
-    gtk_widget_destroy (dialog);
-}
-
-static void
-on_menu_item_activated (GtkWidget *menu_item, GtkWidget *tool_button)
-{
-    GtkToggleToolButton *button = GTK_TOGGLE_TOOL_BUTTON (tool_button);
-
-    if (!gtk_toggle_tool_button_get_active (button))
-       gtk_toggle_tool_button_set_active (button, TRUE);
-}
-
-static void
-on_start_toggled (GtkWidget *widget, gpointer data)
-{
-    Application *app = data;
-    GError *err = NULL;
-
-    if (!gtk_toggle_tool_button_get_active (
-           GTK_TOGGLE_TOOL_BUTTON (app->start_button)))
-    {
-       return;
-    }
-
-    if (collector_start (app->collector, -1, &err))
-    {
-       delete_data (app);
-
-       app->state = PROFILING;
-    }
-    else
-    {
-       sorry (app->main_window, err->message); 
-
-       g_error_free (err);
-    }
-
-    update_screenshot_window (app);
-    update_sensitivity (app);
-}
-
-enum
-{
-    OBJECT_NAME,
-    OBJECT_SELF,
-    OBJECT_TOTAL,
-    OBJECT_OBJECT
-};
-
-enum
-{
-    CALLERS_NAME,
-    CALLERS_SELF,
-    CALLERS_TOTAL,
-    CALLERS_OBJECT
-};
-
-enum
-{
-    DESCENDANTS_NAME,
-    DESCENDANTS_SELF,
-    DESCENDANTS_CUMULATIVE,
-    DESCENDANTS_OBJECT
-};
-
-static char *
-get_current_object (Application *app)
-{
-    GtkTreeModel *model;
-    GtkTreeIter selected;
-    char *object;
-
-    if (gtk_tree_selection_get_selected (app->object_selection, &model, &selected))
-    {
-       gtk_tree_model_get (model, &selected,
-                           OBJECT_OBJECT, &object,
-                           -1);
-       return object;
-    }
-    else
-    {
-       return NULL;
-    }
-}
-
-static void
-fill_main_list (Application *app)
-{
-    GList *list;
-    GtkListStore *list_store;
-    Profile *profile = app->profile;
-    GList *objects;
-
-    if (profile)
-    {
-       list_store = gtk_list_store_new (4,
-                                        G_TYPE_STRING,
-                                        G_TYPE_DOUBLE,
-                                        G_TYPE_DOUBLE,
-                                        G_TYPE_POINTER);
-
-       objects = profile_get_objects (profile);
-       for (list = objects; list != NULL; list = list->next)
-       {
-           ProfileObject *object = list->data;
-           GtkTreeIter iter;
-           double profile_size = profile_get_size (profile);
-
-           gtk_list_store_append (list_store, &iter);
-
-           gtk_list_store_set (list_store, &iter,
-                               OBJECT_NAME, object->name,
-                               OBJECT_SELF, 100.0 * object->self / profile_size,
-                               OBJECT_TOTAL, 100.0 * object->total / profile_size,
-#if 0
-                               OBJECT_SELF, (double)object->self,
-                               OBJECT_TOTAL, (double)object->total,
-#endif
-                               OBJECT_OBJECT, object->name,
-                               -1);
-       }
-       g_list_foreach (objects, (GFunc)g_free, NULL);
-       g_list_free (objects);
-
-       tree_view_set_model_with_default_sort (app->object_view, GTK_TREE_MODEL (list_store),
-                                              OBJECT_TOTAL, GTK_SORT_DESCENDING);
+#include <sysprof.h>
 
-       g_object_unref (G_OBJECT (list_store));
-    }
+#include "sp-application.h"
 
-    gtk_tree_view_columns_autosize (app->object_view);
-}
-
-static void
-add_node (FooTreeStore      *store,
-         int                size,
-         const GtkTreeIter *parent,
-         ProfileDescendant *node)
-{
-    GtkTreeIter iter;
-
-    if (!node)
-       return;
-    
-    foo_tree_store_insert (store, &iter, (GtkTreeIter *)parent, 0);
-    
-    foo_tree_store_set (store, &iter,
-                       DESCENDANTS_NAME, node->name,
-                       DESCENDANTS_SELF, 100 * (node->self)/(double)size,
-                       DESCENDANTS_CUMULATIVE, 100 * (node->cumulative)/(double)size,
-#if 0
-                       DESCENDANTS_SELF, (double)node->self,
-                       DESCENDANTS_CUMULATIVE, (double)node->non_recursion,
-#endif
-                       DESCENDANTS_OBJECT, node->name,
-                       -1);
-
-    add_node (store, size, parent, node->siblings);
-    add_node (store, size, &iter, node->children);
-}
-
-static void
-fill_descendants_tree (Application *app)
-{
-    FooTreeStore *tree_store;
-
-    if (app->descendants)
-    {
-       profile_descendant_free (app->descendants);
-       app->descendants = NULL;
-    }
-
-    tree_store =
-       foo_tree_store_new (4,
-                           G_TYPE_STRING,
-                           G_TYPE_DOUBLE,
-                           G_TYPE_DOUBLE,
-                           G_TYPE_POINTER);
-
-    if (app->profile)
-    {
-       char *object = get_current_object (app);
-       if (object)
-       {
-           app->descendants =
-               profile_create_descendants (app->profile, object);
-           add_node (tree_store,
-                     profile_get_size (app->profile), NULL, app->descendants);
-       }
-    }
-
-    tree_view_set_model_with_default_sort (app->descendants_view, GTK_TREE_MODEL (tree_store),
-                                          DESCENDANTS_CUMULATIVE, GTK_SORT_DESCENDING);
-
-    g_object_unref (G_OBJECT (tree_store));
-
-    gtk_tree_view_columns_autosize (app->descendants_view);
-}
-
-static void
-add_callers (GtkListStore  *list_store,
-            Profile       *profile,
-            ProfileCaller *callers)
-{
-    while (callers)
-    {
-       gchar *name;
-       GtkTreeIter iter;
-       double profile_size = profile_get_size (profile);
-
-       if (callers->name)
-           name = callers->name;
-       else
-           name = "<spontaneous>";
-
-       gtk_list_store_append (list_store, &iter);
-       gtk_list_store_set (
-           list_store, &iter,
-           CALLERS_NAME, name,
-           CALLERS_SELF, 100.0 * callers->self / profile_size,
-           CALLERS_TOTAL, 100.0 * callers->total / profile_size,
-#if 0
-           CALLERS_SELF, (double)callers->self,
-           CALLERS_TOTAL, (double)callers->total,
-#endif
-           CALLERS_OBJECT, callers->name,
-           -1);
-
-       callers = callers->next;
-    }
-}
-
-static void
-fill_callers_list (Application *app)
-{
-    GtkListStore *list_store;
-
-    if (app->callers)
-    {
-       profile_caller_free (app->callers);
-       app->callers = NULL;
-    }
-
-    list_store =
-       gtk_list_store_new (4,
-                           G_TYPE_STRING,
-                           G_TYPE_DOUBLE,
-                           G_TYPE_DOUBLE,
-                           G_TYPE_POINTER);
-
-    if (app->profile)
-    {
-       char *object = get_current_object (app);
-       if (object)
-       {
-           app->callers = profile_list_callers (app->profile, object);
-           add_callers (list_store, app->profile, app->callers);
-       }
-    }
-
-    tree_view_set_model_with_default_sort (app->callers_view, GTK_TREE_MODEL (list_store),
-                                          CALLERS_TOTAL, GTK_SORT_DESCENDING);
-
-    g_object_unref (G_OBJECT (list_store));
-
-    gtk_tree_view_columns_autosize (app->callers_view);
-}
-
-static void
-enter_display_mode (Application *app)
-{
-    app->state = DISPLAYING;
-
-    update_sensitivity (app);
-
-    app->inhibit_forced_redraw = TRUE;
-
-    fill_main_list (app);
-
-    /* This has the side effect of selecting the first row, which in turn causes
-     * the other lists to be filled out
-     */
-    gtk_widget_grab_focus (GTK_WIDGET (app->object_view));
-
-    app->inhibit_forced_redraw = FALSE;
-}
-
-static void
-ensure_profile (Application *app)
-{
-    if (app->profile)
-       return;
-
-    collector_stop (app->collector);
-
-    app->profile = collector_create_profile (app->collector);
-
-    collector_reset (app->collector);
-
-    enter_display_mode (app);
-}
-
-static void
-on_about_activated (GtkWidget *widget, gpointer data)
-{
-#define OSLASH "\303\270"
-    Application *app = data;
-    char *name_property;
-
-    if (gtk_minor_version >= 12)
-       name_property = "program-name";
-    else
-       name_property = "name";
-
-    gtk_show_about_dialog (GTK_WINDOW (app->main_window),
-                          "logo", app->icon,
-                          name_property, APPLICATION_NAME,
-                          "copyright", "Copyright 2004-2009, S"OSLASH"ren Sandmann",
-                          "version", PACKAGE_VERSION,
-                          NULL);
-}
-
-static void
-on_profile_toggled (GtkWidget *widget, gpointer data)
-{
-    Application *app = data;
-
-    if (gtk_toggle_tool_button_get_active (GTK_TOGGLE_TOOL_BUTTON (app->profile_button)))
-    {
-       set_busy (app->main_window, TRUE);
-       ensure_profile (app);
-       set_busy (app->main_window, FALSE);
-    }
-}
-
-static void
-on_reset_clicked (gpointer widget, gpointer data)
-{
-    Application *app = data;
-
-    set_busy (app->main_window, TRUE);
-
-    delete_data (app);
-
-    if (app->state == DISPLAYING)
-    {
-       app->state = INITIAL;
-       collector_stop (app->collector);
-    }
-
-    update_sensitivity (app);
-
-    set_busy (app->main_window, FALSE);
-}
-
-static gboolean
-overwrite_file (GtkWindow *window,
-               const char *filename)
-{
-    GtkWidget *msgbox;
-    gchar *utf8_file_name;
-    AtkObject *obj;
-    gint ret;
-
-    utf8_file_name = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
-    msgbox = gtk_message_dialog_new (window,
-                                    (GtkDialogFlags)GTK_DIALOG_DESTROY_WITH_PARENT,
-                                    GTK_MESSAGE_QUESTION,
-                                    GTK_BUTTONS_NONE,
-                                    _("A file named \"%s\" already exists."),
-                                    utf8_file_name);
-    g_free (utf8_file_name);
-
-    gtk_message_dialog_format_secondary_text (
-       GTK_MESSAGE_DIALOG (msgbox),
-       _("Do you want to replace it with the one you are saving?"));
-
-    gtk_dialog_add_button (GTK_DIALOG (msgbox),
-                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
-
-    gtk_dialog_add_button (GTK_DIALOG (msgbox),
-                          _("_Replace"), GTK_RESPONSE_YES);
-
-    gtk_dialog_set_default_response (GTK_DIALOG (msgbox),
-                                    GTK_RESPONSE_CANCEL);
-
-    obj = gtk_widget_get_accessible (msgbox);
-
-    if (GTK_IS_ACCESSIBLE (obj))
-       atk_object_set_name (obj, _("Question"));
-
-    ret = gtk_dialog_run (GTK_DIALOG (msgbox));
-    gtk_widget_destroy (msgbox);
-
-    return (ret == GTK_RESPONSE_YES);
-}
-
-static void
-on_save_as_clicked (gpointer widget,
-                   gpointer data)
-{
-    Application *app = data;
-    GtkWidget *dialog;
-
-    ensure_profile (app);
-
-    set_busy (app->main_window, TRUE);
-
-    dialog = gtk_file_chooser_dialog_new ("Save As",
-                                         GTK_WINDOW (app->main_window),
-                                         GTK_FILE_CHOOSER_ACTION_SAVE,
-                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                                         GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
-                                         NULL);
-
-    gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
-    gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
-
-    set_busy (app->main_window, FALSE);
-
-retry:
-    if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
-    {
-       GError *err = NULL;
-       gchar *filename;
-
-       filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
-
-       if (g_file_test (filename, G_FILE_TEST_EXISTS)          &&
-           !overwrite_file (GTK_WINDOW (app->main_window), filename))
-       {
-           g_free (filename);
-           goto retry;
-       }
-
-       set_busy (dialog, TRUE);
-       if (!profile_save (app->profile, filename, &err))
-       {
-           sorry (app->main_window, "Could not save %s: %s",
-                  filename, err->message);
-
-           set_busy (dialog, FALSE);
-           g_free (filename);
-           goto retry;
-       }
-       set_application_title (app, filename);
-       set_busy (dialog, FALSE);
-       g_free (filename);
-    }
-
-    gtk_widget_destroy (dialog);
-}
-
-static void
-set_loaded_profile (Application *app,
-                   const char  *name,
-                   Profile     *profile)
+gint
+main (gint argc,
+      gchar *argv[])
 {
-    g_return_if_fail (name != NULL);
-    g_return_if_fail (profile != NULL);
-
-    collector_stop (app->collector);
-
-    delete_data (app);
-
-    app->profile = profile;
-
-    set_application_title (app, name);
-
-    enter_display_mode (app);
-}
-
-static void
-show_could_not_open (Application *app,
-                    const char *filename,
-                    GError *err)
-{
-    sorry (app->main_window,
-          "Could not open %s: %s",
-          filename,
-          err->message);
-}
-
-static void
-on_open_clicked (gpointer widget,
-                gpointer data)
-{
-    Application *app = data;
-    gchar *filename = NULL;
-    Profile *profile = NULL;
-    GtkWidget *dialog;
-
-    set_busy (app->main_window, TRUE);
-
-    dialog = gtk_file_chooser_dialog_new ("Open",
-                                         GTK_WINDOW (app->main_window),
-                                         GTK_FILE_CHOOSER_ACTION_OPEN,
-                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                                         GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
-                                         NULL);
-
-    gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
-
-    set_busy (app->main_window, FALSE);
-
-retry:
-    if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
-    {
-       GError *err = NULL;
-
-       filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
-
-       set_busy (dialog, TRUE);
-
-       profile = profile_load (filename, &err);
-
-       if (!profile)
-       {
-           set_busy (dialog, FALSE);
-
-           show_could_not_open (app, filename, err);
-           g_error_free (err);
-           g_free (filename);
-
-           filename = NULL;
-           goto retry;
-       }
-
-       set_busy (dialog, FALSE);
-    }
-
-    gtk_widget_destroy (dialog);
-
-    if (profile)
-    {
-       g_assert (filename);
-       set_loaded_profile (app, filename, profile);
-
-       g_free (filename);
-    }
-}
-
-static void
-on_delete (GtkWidget *window,
-          Application *app)
-{
-    /* Workaround for http://bugzilla.gnome.org/show_bug.cgi?id=317775
-     *
-     * Without it, the read callbacks can fire _after_ gtk_main_quit()
-     * has been called and cause stuff to be called on destroyed widgets.
-     */
-    while (gtk_main_iteration ())
-       ;
-
-    gtk_main_quit ();
-}
-
-static void
-expand_descendants_tree (Application *app)
-{
-    GtkTreeModel *model = gtk_tree_view_get_model (app->descendants_view);
-    GtkTreeIter iter;
-    GList *all_paths = NULL;
-    int n_rows;
-    int max_rows = 40; /* FIXME */
-    double top_value = 0.0;
-    GtkTreePath *first_path;
-    GList *list;
-
-    first_path = gtk_tree_path_new_first();
-
-    all_paths = g_list_prepend (all_paths, first_path);
-
-    n_rows = 1;
-
-    gtk_tree_model_get_iter (model, &iter, first_path);
-    gtk_tree_model_get (model, &iter,
-                       OBJECT_TOTAL, &top_value,
-                       -1);
-
-    while (all_paths && n_rows < max_rows)
-    {
-       GtkTreeIter best_iter;
-       GtkTreePath *best_path;
-       double best_value;
-       int n_children;
-       int i;
-
-       best_value = 0.0;
-       best_path = NULL;
-
-       for (list = all_paths; list != NULL; list = list->next)
-       {
-           GtkTreePath *path = list->data;
-           GtkTreeIter iter;
-
-           g_assert (path != NULL);
-
-           if (gtk_tree_model_get_iter (model, &iter, path))
-           {
-               double value;
-               gtk_tree_model_get (model, &iter,
-                                   OBJECT_TOTAL, &value,
-                                   -1);
-
-               if (value >= best_value)
-               {
-                   best_value = value;
-                   best_path = path;
-                   best_iter = iter;
-               }
-           }
-       }
-
-       n_children = gtk_tree_model_iter_n_children (model, &best_iter);
-
-       if (n_children && (best_value / top_value) > 0.04 &&
-           (n_children + gtk_tree_path_get_depth (best_path)) /
-           (double)max_rows < (best_value / top_value) )
-       {
-           gtk_tree_view_expand_row (
-               GTK_TREE_VIEW (app->descendants_view), best_path, FALSE);
-           n_rows += n_children;
-
-           if (gtk_tree_path_get_depth (best_path) < 4)
-           {
-               GtkTreePath *path = gtk_tree_path_copy (best_path);
-               gtk_tree_path_down (path);
-
-               for (i = 0; i < n_children; ++i)
-               {
-                   all_paths = g_list_prepend (all_paths, path);
-
-                   path = gtk_tree_path_copy (path);
-                   gtk_tree_path_next (path);
-               }
-
-               gtk_tree_path_free (path);
-           }
-       }
-
-       all_paths = g_list_remove (all_paths, best_path);
-
-       if (!all_paths && n_rows == 1)
-       {
-           /* Always expand at least once */
-           gtk_tree_view_expand_row (GTK_TREE_VIEW (app->descendants_view),
-                                     best_path, FALSE);
-       }
-
-       gtk_tree_path_free (best_path);
-    }
-
-    for (list = all_paths; list != NULL; list = list->next)
-       gtk_tree_path_free (list->data);
-
-    g_list_free (all_paths);
-}
-
-static void
-get_data (GtkTreeView *view,
-         GtkTreeIter *iter,
-         gchar **name,
-         double *self,
-         double *cumulative)
-{
-    char *dummy1;
-    double dummy2;
-    double dummy3;
-
-    GtkTreeModel *model = gtk_tree_view_get_model (view);
-    gtk_tree_model_get (
-       model, iter,
-       DESCENDANTS_NAME, name? name : &dummy1,
-       DESCENDANTS_SELF, self? self : &dummy2,
-       DESCENDANTS_CUMULATIVE, cumulative? cumulative : &dummy3,
-       -1);
-}
-
-static int
-get_indent (GtkTreePath *path)
-{
-    return 2 * (gtk_tree_path_get_depth (path) - 1);
-}
-
-static void
-compute_text_width (GtkTreeView  *view,
-                   GtkTreePath  *path,
-                   GtkTreeIter  *iter,
-                   gpointer      data)
-{
-    int *width = data;
-    char *name;
-
-    get_data (view, iter, &name, NULL, NULL);
-
-    *width = MAX (g_utf8_strlen (name, -1) + get_indent (path), *width);
-
-    g_free (name);
-}
-
-typedef struct
-{
-    int max_width;
-    GString *text;
-} AddTextInfo;
-
-static void
-set_monospace (GtkWidget *widget)
-{
-    PangoFontDescription *desc =
-       pango_font_description_from_string ("monospace");
-
-    gtk_widget_modify_font (widget, desc);
-
-    pango_font_description_free (desc);
-}
-
-static void
-add_text (GtkTreeView *view,
-         GtkTreePath *path,
-         GtkTreeIter *iter,
-         gpointer     data)
-{
-    AddTextInfo *info = data;
-    char *name;
-    double self;
-    double cumulative;
-    int indent;
-    int i;
-
-    get_data (view, iter, &name, &self, &cumulative);
-
-    indent = get_indent (path);
-
-    for (i = 0; i < indent; ++i)
-       g_string_append_c (info->text, ' ');
-
-    g_string_append_printf (info->text, "%-*s %6.2f%% %6.2f%%\n",
-                           info->max_width - indent, name, self, cumulative);
-
-    g_free (name);
-}
-
-static gboolean
-update_screenshot_window_idle (gpointer data)
-{
-    Application *app = data;
-    GtkTextBuffer *text_buffer;
-
-    if (!app->screenshot_window_visible)
-       return FALSE;
-
-    text_buffer =
-       gtk_text_view_get_buffer (GTK_TEXT_VIEW (app->screenshot_textview));
-
-    gtk_text_buffer_set_text (text_buffer, "", -1);
-
-    if (app->descendants)
-    {
-       AddTextInfo info;
-
-       info.max_width = 0;
-       info.text = g_string_new ("");
-
-       tree_view_foreach_visible (app->descendants_view,
-                                  compute_text_width,
-                                  &info.max_width);
-
-       tree_view_foreach_visible (app->descendants_view,
-                                  add_text,
-                                  &info);
-
-       gtk_text_buffer_set_text (text_buffer, info.text->str, -1);
-
-       set_monospace (app->screenshot_textview);
-
-       g_string_free (info.text, TRUE);
-    }
-
-    app->update_screenshot_id = 0;
-
-    if (app->screenshot_window_visible)
-    {
-       set_busy (app->screenshot_window, FALSE);
-       set_busy (app->screenshot_textview, FALSE);
-    }
-
-    return FALSE;
-}
-
-static void
-update_screenshot_window (Application *app)
-{
-    /* We do this in an idle handler to deal with the case where
-     * someone presses Shift-RightArrow on the root of a huge
-     * profile. This causes a ton of 'expanded' notifications,
-     * each of which would cause us to traverse the tree and
-     * update the screenshot window.
-     */
-    if (app->update_screenshot_id)
-       g_source_remove (app->update_screenshot_id);
-
-    if (app->screenshot_window_visible)
-    {
-       /* don't swamp the X server with cursor change requests */
-       if (!app->update_screenshot_id)
-       {
-           set_busy (app->screenshot_window, TRUE);
-           set_busy (app->screenshot_textview, TRUE);
-       }
-    }
-
-    app->update_screenshot_id = g_idle_add (
-       update_screenshot_window_idle, app);
-}
-
-static void
-on_descendants_row_expanded_or_collapsed (GtkTreeView *tree,
-                                         GtkTreeIter *iter,
-                                         GtkTreePath *path,
-                                         Application *app)
-{
-    update_screenshot_window (app);
-}
-
-static void
-on_object_selection_changed (GtkTreeSelection *selection,
-                            gpointer          data)
-{
-    Application *app = data;
-
-    set_busy (app->main_window, TRUE);
-
-    update_screenshot_window (app);
-
-    if (!app->inhibit_forced_redraw)
-       gdk_window_process_all_updates (); /* Display updated selection */
-
-    fill_descendants_tree (app);
-    fill_callers_list (app);
-
-    if (get_current_object (app))
-       expand_descendants_tree (app);
-
-    set_busy (app->main_window, FALSE);
-}
-
-static void
-really_goto_object (Application *app,
-                   char *object)
-{
-    GtkTreeModel *profile_objects;
-    GtkTreeIter iter;
-    gboolean found = FALSE;
-
-    profile_objects = gtk_tree_view_get_model (app->object_view);
-
-    if (gtk_tree_model_get_iter_first (profile_objects, &iter))
-    {
-       do
-       {
-           char *list_object;
-
-           gtk_tree_model_get (profile_objects, &iter,
-                               OBJECT_OBJECT, &list_object,
-                               -1);
-
-           if (list_object == object)
-           {
-               found = TRUE;
-               break;
-           }
-       }
-       while (gtk_tree_model_iter_next (profile_objects, &iter));
-    }
-
-    if (found)
-    {
-       GtkTreePath *path =
-           gtk_tree_model_get_path (profile_objects, &iter);
-
-       gtk_tree_view_set_cursor (app->object_view, path, 0, FALSE);
-    }
-}
-
-static void
-goto_object (Application *app,
-            GtkTreeView *tree_view,
-            GtkTreePath *path,
-            gint         column)
-{
-    GtkTreeIter iter;
-    GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
-    char *object;
-
-    if (!gtk_tree_model_get_iter (model, &iter, path))
-       return;
-
-    gtk_tree_model_get (model, &iter, column, &object, -1);
-
-    if (!object)
-       return;
-
-    really_goto_object (app, object);
-}
-
-static void
-on_descendants_row_activated (GtkTreeView *tree_view,
-                             GtkTreePath *path,
-                             GtkTreeViewColumn *column,
-                             gpointer data)
-{
-    Application *app = data;
-
-    goto_object (app, tree_view, path, DESCENDANTS_OBJECT);
-
-    gtk_widget_grab_focus (GTK_WIDGET (app->descendants_view));
-}
-
-static void
-on_callers_row_activated (GtkTreeView *tree_view,
-                         GtkTreePath *path,
-                         GtkTreeViewColumn *column,
-                         gpointer data)
-{
-    Application *app = data;
-
-    goto_object (app, tree_view, path, CALLERS_OBJECT);
-
-    gtk_widget_grab_focus (GTK_WIDGET (app->callers_view));
-}
-
-static void
-on_screenshot_activated (GtkCheckMenuItem *menu_item,
-                        Application      *app)
-{
-    app->screenshot_window_visible = gtk_check_menu_item_get_active (menu_item);
-
-    update_screenshot_window (app);
-
-    update_sensitivity (app);
-}
-
-static void
-on_screenshot_window_delete (GtkWidget   *window,
-                            GdkEvent    *event,
-                            Application *app)
-{
-    app->screenshot_window_visible = FALSE;
-
-    update_sensitivity (app);
-}
-
-static void
-on_screenshot_close_button_clicked (GtkWidget *widget,
-                                   Application *app)
-{
-    app->screenshot_window_visible = FALSE;
-
-    update_sensitivity (app);
-}
-
-static void
-set_sizes (GtkWindow *window,
-          GtkWindow *screenshot_window,
-          GtkWidget *hpaned,
-          GtkWidget *vpaned)
-{
-    GdkScreen *screen;
-    int monitor_num;
-    GdkRectangle monitor;
-    int width, height;
-    GtkWidget *widget = GTK_WIDGET (window);
-
-    screen = gtk_widget_get_screen (widget);
-    monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window);
-
-    gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
-
-    width = monitor.width * 3 / 4;
-    height = monitor.height * 3 / 4;
-
-    gtk_window_resize (window, width, height);
-
-    gtk_paned_set_position (GTK_PANED (vpaned), height / 2);
-    gtk_paned_set_position (GTK_PANED (hpaned), width * 3 / 8);
-
-    width = monitor.width * 5 / 8;
-    height = monitor.height * 5 / 8;
-
-    gtk_window_resize (screenshot_window, width, height);
-}
-
-#define GLADE_FILE DATADIR "/sysprof.glade"
-
-static void
-gather_widgets (Application *app)
-{
-    typedef struct
-    {
-       void *location;
-       const char *name;
-    } WidgetInfo;
-
-    const WidgetInfo widgets[] =
-       {
-           { &app->main_window, "main_window" },
-           { &app->start_button, "start_button" },
-           { &app->profile_button, "profile_button" },
-           { &app->reset_button, "reset_button" },
-           { &app->save_as_button, "save_as_button" },
-           { &app->dummy_button, "dummy_button" },
-           { &app->samples_label, "samples_label" },
-           { &app->samples_hbox, "samples_hbox" },
-           { &app->start_item, "start_item" },
-           { &app->profile_item, "profile_item" },
-           { &app->reset_item, "reset_item" },
-           { &app->open_item, "open_item" },
-           { &app->save_as_item, "save_as_item" },
-           { &app->screenshot_item, "screenshot_item" },
-           { &app->quit_item, "quit" },
-           { &app->about_item, "about" },
-           { &app->object_view, "object_view" },
-           { &app->callers_view, "callers_view" },
-           { &app->descendants_view, "descendants_view" },
-           { &app->screenshot_window, "screenshot_window" },
-           { &app->screenshot_textview, "screenshot_textview" },
-           { &app->screenshot_close_button, "screenshot_close_button" },
-           { &app->vpaned, "vpaned" },
-           { &app->hpaned, "hpaned" },
-       };
-
-    GladeXML *xml = glade_xml_new (GLADE_FILE, NULL, NULL);
-    int i;
-
-    for (i = 0; i < G_N_ELEMENTS (widgets); ++i)
-    {
-       const WidgetInfo *info = &(widgets[i]);
-
-       *(GtkWidget **)(info->location) = glade_xml_get_widget (xml, info->name);
-
-       g_assert (GTK_IS_WIDGET (*(GtkWidget **)info->location));
-    }
-
-    g_object_unref (xml);
-}
-
-static void
-connect_signals (Application *app)
-{
-    typedef struct
-    {
-       gpointer object;
-       const char *signal;
-       gpointer callback;
-       gpointer data;
-    } SignalInfo;
-
-    const SignalInfo signals[] =
-       {
-           { app->main_window, "delete_event", on_delete, NULL },
-           { app->start_button, "toggled", on_start_toggled, app },
-           { app->profile_button, "toggled", on_profile_toggled, app },
-           { app->reset_button, "clicked", on_reset_clicked, app },
-           { app->save_as_button, "clicked", on_save_as_clicked, app },
-           { app->start_item, "activate", on_menu_item_activated, app->start_button },
-           { app->profile_item, "activate", on_menu_item_activated, app->profile_button },
-           { app->reset_item, "activate", on_reset_clicked, app },
-           { app->open_item, "activate", on_open_clicked, app },
-           { app->save_as_item, "activate", on_save_as_clicked, app },
-           { app->screenshot_item, "activate", on_screenshot_activated, app },
-           { app->quit_item, "activate", on_delete, NULL },
-           { app->about_item, "activate", on_about_activated, app },
-           { app->object_selection, "changed", on_object_selection_changed, app },
-           { app->callers_view, "row-activated", on_callers_row_activated, app },
-           { app->descendants_view, "row-activated", on_descendants_row_activated, app },
-           { app->descendants_view, "row-expanded", on_descendants_row_expanded_or_collapsed, app },
-           { app->descendants_view, "row-collapsed", on_descendants_row_expanded_or_collapsed, app },
-           { app->screenshot_window, "delete_event", on_screenshot_window_delete, app },
-           { app->screenshot_close_button, "clicked", on_screenshot_close_button_clicked, app },
-       };
-
-    int i;
-
-    for (i = 0; i < G_N_ELEMENTS (signals); ++i)
-    {
-       const SignalInfo *info = &(signals[i]);
-
-       g_signal_connect (info->object, info->signal, info->callback, info->data);
-    }
-}
-
-static void
-set_shadows (void)
-{
-    /* Get rid of motif out-bevels */
-    gtk_rc_parse_string (
-       "style \"blah\" "
-       "{ "
-       "   GtkToolbar::shadow_type = none "
-       "   GtkMenuBar::shadow_type = none "
-       "   GtkMenuBar::internal_padding = 2 "
-       "} "
-       "widget \"*toolbar\" style : rc \"blah\"\n"
-       "widget \"*menubar\" style : rc \"blah\"\n"
-       );
-}
-
-static void
-set_icons (Application *app)
-{
-    const char *icon_files [] = {
-       PIXMAPDIR "/sysprof-icon-16.png",
-       PIXMAPDIR "/sysprof-icon-24.png",
-       PIXMAPDIR "/sysprof-icon-32.png",
-       PIXMAPDIR "/sysprof-icon-48.png",
-       PIXMAPDIR "/sysprof-icon-256.png",
-       NULL
-    };
-    GList *pixbufs = NULL;
-    int i;
-
-    for (i = 0; icon_files[i] != NULL; ++i)
-    {
-       const char *file = icon_files[i];
-       GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (file, NULL);
-
-       if (pixbuf)
-       {
-           pixbufs = g_list_prepend (pixbufs, pixbuf);
-
-           if (i == 3) /* 48 x 48 */
-               app->icon = g_object_ref (pixbuf);
-       }
-       else
-       {
-           g_warning ("Could not open %s\n", file);
-       }
-    }
-
-    gtk_window_set_icon_list (GTK_WINDOW (app->main_window), pixbufs);
-
-    g_list_foreach (pixbufs, (GFunc)g_object_unref, NULL);
-    g_list_free (pixbufs);
-}
-
-#define PCT_FORMAT "%.2f<span size='smaller'><span size='smaller'> </span>%%</span>"
-
-static gboolean
-build_gui (Application *app)
-{
-    GtkTreeViewColumn *col;
-
-    set_shadows ();
-
-    if (!g_file_test (GLADE_FILE, G_FILE_TEST_EXISTS))
-    {
-       sorry (NULL,
-              "Sysprof was not compiled or installed correctly.\n"
-              "\n"
-              "Running \"make install\" may solve this problem.\n");
-
-       return FALSE;
-    }
-
-    gather_widgets (app);
-
-    g_assert (app->main_window);
-
-    /* Main Window */
-    set_icons (app);
-
-    gtk_widget_realize (GTK_WIDGET (app->main_window));
-
-    /* Tool items */
-    gtk_toggle_tool_button_set_active (
-       GTK_TOGGLE_TOOL_BUTTON (app->profile_button), FALSE);
-
-    /* TreeViews */
-
-    /* object view */
-    gtk_tree_view_set_enable_search (app->object_view, FALSE);
-    col = add_plain_text_column (app->object_view, _("Functions"),
-                                OBJECT_NAME);
-    add_double_format_column (app->object_view, _("Self"),
-                             OBJECT_SELF, PCT_FORMAT);
-    add_double_format_column (app->object_view, _("Total"),
-                             OBJECT_TOTAL, PCT_FORMAT);
-    app->object_selection = gtk_tree_view_get_selection (app->object_view);
-    gtk_tree_view_column_set_expand (col, TRUE);
-
-    /* callers view */
-    gtk_tree_view_set_enable_search (app->callers_view, FALSE);
-    col = add_plain_text_column (app->callers_view, _("Callers"),
-                                CALLERS_NAME);
-    add_double_format_column (app->callers_view, _("Self"),
-                             CALLERS_SELF, PCT_FORMAT);
-    add_double_format_column (app->callers_view, _("Total"),
-                             CALLERS_TOTAL, PCT_FORMAT);
-    gtk_tree_view_column_set_expand (col, TRUE);
-
-    /* descendants view */
-    gtk_tree_view_set_enable_search (app->descendants_view, FALSE);
-    col = add_plain_text_column (app->descendants_view, _("Descendants"),
-                                DESCENDANTS_NAME);
-    add_double_format_column (app->descendants_view, _("Self"),
-                             DESCENDANTS_SELF, PCT_FORMAT);
-    add_double_format_column (app->descendants_view, _("Cumulative"),
-                             DESCENDANTS_CUMULATIVE, PCT_FORMAT);
-    gtk_tree_view_column_set_expand (col, TRUE);
-
-    /* screenshot window */
-
-    /* set sizes */
-    set_sizes (GTK_WINDOW (app->main_window),
-              GTK_WINDOW (app->screenshot_window),
-              app->hpaned, app->vpaned);
-
-    /* hide/show widgets */
-    gtk_widget_show_all (app->main_window);
-    gtk_widget_hide (app->dummy_button);
-    gtk_widget_hide (app->screenshot_window);
-
-    gtk_widget_grab_focus (GTK_WIDGET (app->object_view));
-    queue_show_samples (app);
-
-    connect_signals (app);
-
-    return TRUE;
-}
-
-static void
-on_new_sample (gboolean first_sample,
-              gpointer data)
-{
-    Application *app = data;
-
-    if (app->state == PROFILING && first_sample)
-       update_sensitivity (app);
-    else
-       queue_show_samples (app);
-}
-
-static Application *
-application_new (void)
-{
-    Application *app = g_new0 (Application, 1);
-
-    app->collector = collector_new (FALSE, on_new_sample, app);
-    app->state = INITIAL;
-
-    return app;
-}
-
-typedef struct
-{
-    const char *filename;
-    Application *app;
-} FileOpenData;
-
-static gboolean
-load_file (gpointer data)
-{
-    FileOpenData *file_open_data = data;
-    const char *filename = file_open_data->filename;
-    Application *app = file_open_data->app;
-    GError *err = NULL;
-    Profile *profile;
-
-    set_busy (app->main_window, TRUE);
-
-    profile = profile_load (filename, &err);
-
-    if (profile)
-    {
-       set_loaded_profile (app, filename, profile);
-
-       gdk_window_process_all_updates ();
-       set_busy (app->main_window, FALSE);
-    }
-    else
-    {
-       set_busy (app->main_window, FALSE);
-
-       show_could_not_open (app, filename, err);
-       g_error_free (err);
-    }
-
-    g_free (file_open_data);
-
-    return FALSE;
-}
-
-static const char *
-process_options (int           argc,
-                char        **argv)
-{
-    int i;
-    gboolean show_version = FALSE;
-    const char *filename = NULL;
-
-    for (i = 1; i < argc; ++i)
-    {
-       char *option = argv[i];
-
-       if (strcmp (option, "--version") == 0)
-       {
-           show_version = TRUE;
-       }
-       else if (!filename)
-       {
-           filename = argv[i];
-       }
-    }
-
-    if (show_version)
-    {
-       g_print ("%s %s\n", APPLICATION_NAME, PACKAGE_VERSION);
-
-       exit (1);
-    }
-
-    return filename;
-}
-
-static void
-apply_workarounds (void)
-{
-
-    /* Disable gslice, since it
-     *
-     *  - confuses valgrind
-     *  - caches too much memory
-     *  - hides memory access bugs
-     *  - is not faster than malloc
-     *
-     * Note that g_slice_set_config() is broken in some versions of
-     * GLib (and 'declared internal' according to Tim), so we use the
-     * environment variable instead.
-     */
-    if (!getenv ("G_SLICE"))
-       putenv ("G_SLICE=always_malloc");
-
-    /* Accessibility prevents sysprof from working reliably, so
-     * disable it. Specifically, it
-     *
-     *  - causes large amounts of time to be spent in sysprof itself
-     *    whenever the label is updated.
-     *  - sometimes hangs at shutdown
-     *  - does long-running roundtrip requests that prevents
-     *    reading the event buffers, resulting in lost events.
-     */
-    putenv ("NO_GAIL=1");
-    putenv ("NO_AT_BRIDGE=1");
-}
-
-int
-main (int    argc,
-      char **argv)
-{
-    Application *app;
-    const char *filename;
-
-    apply_workarounds();
-
-    filename = process_options (argc, argv);
-
-    gtk_init (&argc, &argv);
-
-    app = application_new ();
-
-    if (!build_gui (app))
-       return -1;
-
-    update_sensitivity (app);
-
-    if (filename)
-    {
-       FileOpenData *file_open_data = g_new0 (FileOpenData, 1);
-       file_open_data->filename = filename;
-       file_open_data->app = app;
+  g_autoptr(SpApplication) app = NULL;
+  gint ret;
 
-       /* This has to run at G_PRIORITY_LOW because of bug 350517
-        */
-       g_idle_add_full (G_PRIORITY_LOW, load_file, file_open_data, NULL);
-    }
+  sp_clock_init ();
 
-    gtk_main ();
+  app = sp_application_new ();
+  ret = g_application_run (G_APPLICATION (app), argc, argv);
 
-    return 0;
+  return ret;
 }
diff --git a/sysprof.doap b/sysprof.doap
index 92d2a99..d989e5d 100644
--- a/sysprof.doap
+++ b/sysprof.doap
@@ -19,6 +19,11 @@
 
   <maintainer>
     <foaf:Person>
+      <foaf:name>Christian Hergert</foaf:name>
+      <foaf:mbox rdf:resource="mailto:chergert gnome org" />
+      <gnome:userid>chergert</gnome:userid>
+    </foaf:Person>
+    <foaf:Person>
       <foaf:name>Søren Sandmann Pedersen</foaf:name>
       <foaf:mbox rdf:resource="mailto:sandmann cs au dk" />
       <gnome:userid>ssp</gnome:userid>
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644
index 0000000..c37727a
--- /dev/null
+++ b/tests/Makefile.am
@@ -0,0 +1,37 @@
+TESTS =
+
+test_cflags = \
+       $(SYSPROF_CFLAGS) \
+       -I$(top_srcdir)/lib \
+       -I$(top_builddir)/lib
+
+test_libs = \
+       $(SYSPROF_LIBS) \
+       $(top_builddir)/lib/libsysprof- API_VERSION@.la
+
+
+TESTS += test-model-filter
+test_model_filter_SOURCES = test-model-filter.c
+test_model_filter_CFLAGS = $(test_cflags)
+test_model_filter_LDADD = $(test_libs)
+
+TESTS += test-capture
+test_capture_SOURCES = test-capture.c
+test_capture_CFLAGS = $(test_cflags)
+test_capture_LDADD = $(test_libs)
+
+TEST_ENVIRONMENT = \
+       G_TEST_SRCDIR="$(abs_srcdir)" \
+       G_TEST_BUILDDIR="$(abs_builddir)" \
+       G_DEBUG=gc-friendly \
+       GSETTINGS_BACKEND=memory \
+       MALLOC_CHECK_=2 \
+       MALLOC_PERTURB_=$$(($${RANDOM:-256} % 256))
+
+TEST_PROGS = test-model-filter
+LOG_COMPILER = $(top_srcdir)/build-aux/tap-test
+
+noinst_PROGRAMS = $(TESTS)
+check_PROGRAMS = $(TESTS)
+
+-include $(top_srcdir)/git.mk
diff --git a/tests/test-capture.c b/tests/test-capture.c
new file mode 100644
index 0000000..7ddb956
--- /dev/null
+++ b/tests/test-capture.c
@@ -0,0 +1,455 @@
+/* test-capture.c
+ *
+ * Copyright (C) 2016 Christian Hergert <christian hergert me>
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This file 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
+ * Lesser 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/>.
+ */
+
+#include <glib/gstdio.h>
+
+#include "sp-capture-reader.h"
+#include "sp-capture-writer.h"
+
+static void
+test_reader_basic (void)
+{
+  SpCaptureReader *reader;
+  SpCaptureWriter *writer;
+  GError *error = NULL;
+  gint64 t = g_get_monotonic_time ();
+  guint i;
+  gint r;
+
+  writer = sp_capture_writer_new ("capture-file", 0);
+  g_assert (writer != NULL);
+
+  reader = sp_capture_reader_new ("capture-file", &error);
+  g_assert_no_error (error);
+  g_assert (reader != NULL);
+
+  for (i = 0; i < 100; i++)
+    {
+      gchar str[16];
+
+      g_snprintf (str, sizeof str, "%d", i);
+
+      r = sp_capture_writer_add_map (writer, t, -1, -1, i, i + 1, i + 2, i + 3, str);
+      g_assert_cmpint (r, ==, TRUE);
+    }
+
+  sp_capture_writer_flush (writer);
+
+  for (i = 0; i < 100; i++)
+    {
+      SpCaptureFrameType type = -1;
+      const SpCaptureMap *map;
+      gchar str[16];
+
+      g_snprintf (str, sizeof str, "%d", i);
+
+      if (!sp_capture_reader_peek_type (reader, &type))
+        g_assert_not_reached ();
+
+      g_assert_cmpint (type, ==, SP_CAPTURE_FRAME_MAP);
+
+      map = sp_capture_reader_read_map (reader);
+
+      g_assert (map != NULL);
+      g_assert_cmpint (map->frame.pid, ==, -1);
+      g_assert_cmpint (map->frame.cpu, ==, -1);
+      g_assert_cmpint (map->start, ==, i);
+      g_assert_cmpint (map->end, ==, i + 1);
+      g_assert_cmpint (map->offset, ==, i + 2);
+      g_assert_cmpint (map->inode, ==, i + 3);
+      g_assert_cmpstr (map->filename, ==, str);
+    }
+
+  for (i = 0; i < 100; i++)
+    {
+      r = sp_capture_writer_add_timestamp (writer, t, i, -1);
+      g_assert_cmpint (r, ==, TRUE);
+    }
+
+  sp_capture_writer_flush (writer);
+
+  for (i = 0; i < 100; i++)
+    {
+      SpCaptureFrameType type = -1;
+      const SpCaptureTimestamp *ts;
+
+      if (!sp_capture_reader_peek_type (reader, &type))
+        g_assert_not_reached ();
+
+      g_assert_cmpint (type, ==, SP_CAPTURE_FRAME_TIMESTAMP);
+
+      ts = sp_capture_reader_read_timestamp (reader);
+
+      g_assert (ts != NULL);
+      g_assert_cmpint (ts->frame.cpu, ==, i);
+      g_assert_cmpint (ts->frame.pid, ==, -1);
+    }
+
+  for (i = 0; i < 100; i++)
+    {
+      r = sp_capture_writer_add_exit (writer, t, i, -1);
+      g_assert_cmpint (r, ==, TRUE);
+    }
+
+  sp_capture_writer_flush (writer);
+
+  for (i = 0; i < 100; i++)
+    {
+      SpCaptureFrameType type = -1;
+      const SpCaptureExit *ex;
+
+      if (!sp_capture_reader_peek_type (reader, &type))
+        g_assert_not_reached ();
+
+      g_assert_cmpint (type, ==, SP_CAPTURE_FRAME_EXIT);
+
+      ex = sp_capture_reader_read_exit (reader);
+
+      g_assert (ex != NULL);
+      g_assert_cmpint (ex->frame.cpu, ==, i);
+      g_assert_cmpint (ex->frame.pid, ==, -1);
+    }
+
+  for (i = 0; i < 100; i++)
+    {
+      char cmdline[32];
+
+      g_snprintf (cmdline, sizeof cmdline, "program-%d", i);
+      r = sp_capture_writer_add_process (writer, t, -1, i, cmdline);
+      g_assert_cmpint (r, ==, TRUE);
+    }
+
+  sp_capture_writer_flush (writer);
+
+  for (i = 0; i < 100; i++)
+    {
+      SpCaptureFrameType type = -1;
+      const SpCaptureProcess *pr;
+      char str[32];
+
+      g_snprintf (str, sizeof str, "program-%d", i);
+
+      if (!sp_capture_reader_peek_type (reader, &type))
+        g_assert_not_reached ();
+
+      g_assert_cmpint (type, ==, SP_CAPTURE_FRAME_PROCESS);
+
+      pr = sp_capture_reader_read_process (reader);
+
+      g_assert (pr != NULL);
+      g_assert_cmpint (pr->frame.cpu, ==, -1);
+      g_assert_cmpint (pr->frame.pid, ==, i);
+      g_assert_cmpstr (pr->cmdline, ==, str);
+    }
+
+  for (i = 0; i < 100; i++)
+    {
+      r = sp_capture_writer_add_fork (writer, t, i, -1, i);
+      g_assert_cmpint (r, ==, TRUE);
+    }
+
+  sp_capture_writer_flush (writer);
+
+  for (i = 0; i < 100; i++)
+    {
+      SpCaptureFrameType type = -1;
+      const SpCaptureFork *ex;
+
+      if (!sp_capture_reader_peek_type (reader, &type))
+        g_assert_not_reached ();
+
+      g_assert_cmpint (type, ==, SP_CAPTURE_FRAME_FORK);
+
+      ex = sp_capture_reader_read_fork (reader);
+
+      g_assert (ex != NULL);
+      g_assert_cmpint (ex->frame.cpu, ==, i);
+      g_assert_cmpint (ex->frame.pid, ==, -1);
+      g_assert_cmpint (ex->child_pid, ==, i);
+    }
+
+  for (i = 0; i < 1000; i++)
+    {
+      SpCaptureAddress addr;
+      gchar str[32];
+
+      g_snprintf (str, sizeof str, "jitstring-%d", i);
+
+      addr = sp_capture_writer_add_jitmap (writer, str);
+      g_assert_cmpint (addr, ==, (i + 1) | SP_CAPTURE_JITMAP_MARK);
+    }
+
+  sp_capture_writer_flush (writer);
+
+  i = 0;
+
+  for (;;)
+    {
+      SpCaptureFrameType type = -1;
+      g_autoptr(GHashTable) ret = NULL;
+
+      if (sp_capture_reader_peek_type (reader, &type))
+        g_assert_cmpint (type, ==, SP_CAPTURE_FRAME_JITMAP);
+      else
+        break;
+
+      ret = sp_capture_reader_read_jitmap (reader);
+      g_assert (ret != NULL);
+
+      i += g_hash_table_size (ret);
+    }
+
+  g_assert_cmpint (1000, ==, i);
+
+  {
+    SpCaptureFrameType type = -1;
+
+    if (sp_capture_reader_peek_type (reader, &type))
+      g_assert_not_reached ();
+  }
+
+  for (i = 1; i <= 1000; i++)
+    {
+      SpCaptureAddress *addrs;
+      guint j;
+
+      addrs = alloca (i * sizeof *addrs);
+
+      for (j = 0; j < i; j++)
+        addrs[j] = i;
+
+      if (!sp_capture_writer_add_sample (writer, t, -1, -1, addrs, i))
+        g_assert_not_reached ();
+    }
+
+  sp_capture_writer_flush (writer);
+
+  for (i = 1; i <= 1000; i++)
+    {
+      SpCaptureFrameType type = -1;
+      const SpCaptureSample *sample;
+      guint j;
+
+      if (!sp_capture_reader_peek_type (reader, &type))
+        g_assert_not_reached ();
+
+      g_assert_cmpint (type, ==, SP_CAPTURE_FRAME_SAMPLE);
+
+      sample = sp_capture_reader_read_sample (reader);
+
+      g_assert (sample != NULL);
+      g_assert_cmpint (sample->frame.time, ==, t);
+      g_assert_cmpint (sample->frame.cpu, ==, -1);
+      g_assert_cmpint (sample->frame.pid, ==, -1);
+      g_assert_cmpint (sample->n_addrs, ==, i);
+
+      for (j = 0; j < i; j++)
+        g_assert_cmpint (sample->addrs[j], ==, i);
+    }
+
+  {
+    SpCaptureFrameType type = -1;
+
+    if (sp_capture_reader_peek_type (reader, &type))
+      g_assert_not_reached ();
+  }
+
+  r = sp_capture_writer_save_as (writer, "capture-file.bak", &error);
+  g_assert_no_error (error);
+  g_assert (r);
+  g_assert (g_file_test ("capture-file.bak", G_FILE_TEST_IS_REGULAR));
+
+  g_clear_pointer (&writer, sp_capture_writer_unref);
+  g_clear_pointer (&reader, sp_capture_reader_unref);
+
+  reader = sp_capture_reader_new ("capture-file.bak", &error);
+  g_assert_no_error (error);
+  g_assert (reader != NULL);
+
+  for (i = 0; i < 2; i++)
+    {
+      SpCaptureFrameType type = -1;
+      guint count = 0;
+
+      while (sp_capture_reader_peek_type (reader, &type))
+        {
+          count++;
+          if (!sp_capture_reader_skip (reader))
+            g_assert_not_reached ();
+        }
+
+      g_assert_cmpint (count, >, 1500);
+
+      sp_capture_reader_reset (reader);
+    }
+
+  sp_capture_reader_unref (reader);
+
+  g_unlink ("capture-file");
+  g_unlink ("capture-file.bak");
+}
+
+static void
+test_writer_splice (void)
+{
+  SpCaptureWriter *writer1;
+  SpCaptureWriter *writer2;
+  SpCaptureReader *reader;
+  SpCaptureFrameType type;
+  GError *error = NULL;
+  guint i;
+  gint r;
+
+  writer1 = sp_capture_writer_new ("writer1.syscap", 0);
+  writer2 = sp_capture_writer_new ("writer2.syscap", 0);
+
+  for (i = 0; i < 1000; i++)
+    sp_capture_writer_add_timestamp (writer1, SP_CAPTURE_CURRENT_TIME, -1, -1);
+
+  r = sp_capture_writer_splice (writer1, writer2, &error);
+  g_assert_no_error (error);
+  g_assert (r == TRUE);
+
+  g_clear_pointer (&writer1, sp_capture_writer_unref);
+  g_clear_pointer (&writer2, sp_capture_writer_unref);
+
+  reader = sp_capture_reader_new ("writer2.syscap", &error);
+  g_assert_no_error (error);
+  g_assert (reader != NULL);
+
+  for (i = 0; i < 1000; i++)
+    {
+      const SpCaptureTimestamp *ts = sp_capture_reader_read_timestamp (reader);
+
+      g_assert (ts != NULL);
+      g_assert_cmpint (ts->frame.cpu, ==, -1);
+      g_assert_cmpint (ts->frame.pid, ==, -1);
+      g_assert_cmpint (ts->frame.time, >, 0);
+    }
+
+  r = sp_capture_reader_peek_type (reader, &type);
+  g_assert_cmpint (r, ==, FALSE);
+
+  g_clear_pointer (&reader, sp_capture_reader_unref);
+
+  g_unlink ("writer1.syscap");
+  g_unlink ("writer2.syscap");
+}
+
+static void
+test_reader_splice (void)
+{
+  SpCaptureWriter *writer1;
+  SpCaptureWriter *writer2;
+  SpCaptureReader *reader;
+  SpCaptureFrameType type;
+  GError *error = NULL;
+  guint i;
+  guint count;
+  gint r;
+
+  writer1 = sp_capture_writer_new ("writer1.syscap", 0);
+  writer2 = sp_capture_writer_new ("writer2.syscap", 0);
+
+  for (i = 0; i < 1000; i++)
+    sp_capture_writer_add_timestamp (writer1, SP_CAPTURE_CURRENT_TIME, -1, -1);
+
+  r = sp_capture_writer_flush (writer1);
+  g_assert_cmpint (r, ==, TRUE);
+
+  g_clear_pointer (&writer1, sp_capture_writer_unref);
+
+  reader = sp_capture_reader_new ("writer1.syscap", &error);
+  g_assert_no_error (error);
+  g_assert (reader != NULL);
+
+  /* advance to the end of the reader to non-start boundary for fd */
+
+  for (i = 0; i < 1000; i++)
+    {
+      const SpCaptureTimestamp *ts = sp_capture_reader_read_timestamp (reader);
+
+      g_assert (ts != NULL);
+      g_assert_cmpint (ts->frame.cpu, ==, -1);
+      g_assert_cmpint (ts->frame.pid, ==, -1);
+      g_assert_cmpint (ts->frame.time, >, 0);
+    }
+
+  r = sp_capture_reader_peek_type (reader, &type);
+  g_assert_cmpint (r, ==, FALSE);
+
+  r = sp_capture_reader_splice (reader, writer2, &error);
+  g_assert_no_error (error);
+  g_assert_cmpint (r, ==, TRUE);
+
+  g_clear_pointer (&reader, sp_capture_reader_unref);
+  g_clear_pointer (&writer2, sp_capture_writer_unref);
+
+  reader = sp_capture_reader_new ("writer2.syscap", 0);
+
+  for (i = 0; i < 1000; i++)
+    {
+      const SpCaptureTimestamp *ts = sp_capture_reader_read_timestamp (reader);
+
+      g_assert (ts != NULL);
+      g_assert_cmpint (ts->frame.cpu, ==, -1);
+      g_assert_cmpint (ts->frame.pid, ==, -1);
+      g_assert_cmpint (ts->frame.time, >, 0);
+    }
+
+  r = sp_capture_reader_peek_type (reader, &type);
+  g_assert_cmpint (r, ==, FALSE);
+
+  g_clear_pointer (&reader, sp_capture_reader_unref);
+
+  reader = sp_capture_reader_new ("writer2.syscap", &error);
+  g_assert_no_error (error);
+  g_assert (reader != NULL);
+
+  r = sp_capture_reader_save_as (reader, "writer3.syscap", &error);
+  g_assert_no_error (error);
+  g_assert_cmpint (r, ==, TRUE);
+
+  g_clear_pointer (&reader, sp_capture_reader_unref);
+
+  reader = sp_capture_reader_new ("writer3.syscap", &error);
+  g_assert_no_error (error);
+  g_assert (reader != NULL);
+
+  count = 0;
+  while (sp_capture_reader_skip (reader))
+    count++;
+  g_assert_cmpint (count, ==, 1000);
+
+  g_clear_pointer (&reader, sp_capture_reader_unref);
+
+  g_unlink ("writer1.syscap");
+  g_unlink ("writer2.syscap");
+  g_unlink ("writer3.syscap");
+}
+
+int
+main (int argc,
+      char *argv[])
+{
+  g_test_init (&argc, &argv, NULL);
+  g_test_add_func ("/SpCapture/ReaderWriter", test_reader_basic);
+  g_test_add_func ("/SpCapture/Writer/splice", test_writer_splice);
+  g_test_add_func ("/SpCapture/Reader/splice", test_reader_splice);
+  return g_test_run ();
+}
diff --git a/tests/test-model-filter.c b/tests/test-model-filter.c
new file mode 100644
index 0000000..8923084
--- /dev/null
+++ b/tests/test-model-filter.c
@@ -0,0 +1,119 @@
+#include <sysprof.h>
+
+#include "sp-model-filter.h"
+
+#define TEST_TYPE_ITEM (test_item_get_type())
+
+struct _TestItem
+{
+  GObject p;
+  guint n;
+};
+
+G_DECLARE_FINAL_TYPE (TestItem, test_item, TEST, ITEM, GObject)
+G_DEFINE_TYPE (TestItem, test_item, G_TYPE_OBJECT)
+
+static void
+test_item_class_init (TestItemClass *klass)
+{
+}
+
+static void
+test_item_init (TestItem *self)
+{
+}
+
+static TestItem *
+test_item_new (guint n)
+{
+  TestItem *item;
+
+  item = g_object_new (TEST_TYPE_ITEM, NULL);
+  item->n = n;
+
+  return item;
+}
+
+static gboolean
+filter_func1 (GObject  *object,
+              gpointer  user_data)
+{
+  return (TEST_ITEM (object)->n & 1) == 0;
+}
+
+static gboolean
+filter_func2 (GObject  *object,
+              gpointer  user_data)
+{
+  return (TEST_ITEM (object)->n & 1) == 1;
+}
+
+static void
+test_basic (void)
+{
+  GListStore *model;
+  SpModelFilter *filter;
+  TestItem *item;
+  guint i;
+
+  model = g_list_store_new (TEST_TYPE_ITEM);
+  g_assert (model);
+
+  for (i = 0; i < 1000; i++)
+    {
+      g_autoptr(TestItem) val = test_item_new (i);
+
+      g_list_store_append (model, val);
+    }
+
+  g_assert_cmpint (1000, ==, g_list_model_get_n_items (G_LIST_MODEL (model)));
+
+  filter = sp_model_filter_new (G_LIST_MODEL (model));
+  g_assert (filter);
+
+  g_assert_cmpint (1000, ==, g_list_model_get_n_items (G_LIST_MODEL (filter)));
+  sp_model_filter_set_filter_func (filter, filter_func1, NULL, NULL);
+  g_assert_cmpint (500, ==, g_list_model_get_n_items (G_LIST_MODEL (filter)));
+
+  for (i = 0; i < 1000; i += 2)
+    g_list_store_remove (model, 998 - i);
+
+  g_assert_cmpint (500, ==, g_list_model_get_n_items (G_LIST_MODEL (model)));
+  g_assert_cmpint (0, ==, g_list_model_get_n_items (G_LIST_MODEL (filter)));
+
+  sp_model_filter_set_filter_func (filter, NULL, NULL, NULL);
+  g_assert_cmpint (500, ==, g_list_model_get_n_items (G_LIST_MODEL (filter)));
+
+  sp_model_filter_set_filter_func (filter, filter_func2, NULL, NULL);
+  g_assert_cmpint (500, ==, g_list_model_get_n_items (G_LIST_MODEL (filter)));
+
+  g_list_store_append (model, test_item_new (1001));
+
+  for (i = 0; i < 500; i++)
+    g_list_store_remove (model, 0);
+
+  g_assert_cmpint (1, ==, g_list_model_get_n_items (G_LIST_MODEL (model)));
+  g_assert_cmpint (1, ==, g_list_model_get_n_items (G_LIST_MODEL (filter)));
+
+  sp_model_filter_set_filter_func (filter, NULL, NULL, NULL);
+  g_assert_cmpint (1, ==, g_list_model_get_n_items (G_LIST_MODEL (model)));
+  g_assert_cmpint (1, ==, g_list_model_get_n_items (G_LIST_MODEL (filter)));
+
+  item = g_list_model_get_item (G_LIST_MODEL (filter), 0);
+  g_assert (item);
+  g_assert (TEST_IS_ITEM (item));
+  g_assert_cmpint (item->n, ==, 1001);
+  g_clear_object (&item);
+
+  g_clear_object (&model);
+  g_clear_object (&filter);
+}
+
+gint
+main (gint argc,
+      gchar *argv[])
+{
+  g_test_init (&argc, &argv, NULL);
+  g_test_add_func ("/SpModelFilter/basic", test_basic);
+  return g_test_run ();
+}
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644
index 0000000..0b1522a
--- /dev/null
+++ b/tools/Makefile.am
@@ -0,0 +1,19 @@
+bin_PROGRAMS = sysprof-cli
+noinst_PROGRAMS = sysprof-dump
+
+AM_CPPFLAGS = \
+       $(SYSPROF_CFLAGS) \
+       -I$(top_srcdir)/lib \
+       -I$(top_builddir)/lib
+
+sysprof_cli_SOURCES = sysprof-cli.c
+sysprof_cli_LDADD = \
+       $(SYSPROF_LIBS) \
+       $(top_builddir)/lib/libsysprof- API_VERSION@.la
+
+sysprof_dump_SOURCES = sysprof-dump.c
+sysprof_dump_LDADD = \
+       $(SYSPROF_LIBS) \
+       $(top_builddir)/lib/libsysprof- API_VERSION@.la
+
+-include $(top_srcdir)/git.mk
diff --git a/tools/sysprof-cli.c b/tools/sysprof-cli.c
index e8d26ee..f94ca41 100644
--- a/tools/sysprof-cli.c
+++ b/tools/sysprof-cli.c
@@ -1,10 +1,10 @@
-/* Sysprof -- Sampling, systemwide CPU profiler
- * Copyright 2005, Lorenzo Colitti
- * Copyright 2005, Soren Sandmann 
+/* sysprof-cli.c
  *
- * This program is free software; you can redistribute it and/or modify
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * 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,
@@ -13,158 +13,208 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <config.h>
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
 #include <fcntl.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
 #include <signal.h>
-#include <glib.h>
-#include <stdio.h>
-
-#include "stackstash.h"
-#include "profile.h"
-#include "watch.h"
-#include "signal-handler.h"
-#include "collector.h"
+#include <stdlib.h>
+#include <sys/eventfd.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <sysprof.h>
 
-typedef struct Application Application;
-struct Application
-{
-    Collector *        collector;
-    char *     outfile;
-    GMainLoop * main_loop;
-};
+static GMainLoop  *main_loop;
+static SpProfiler *profiler;
+static int efd = -1;
+static int exit_code = EXIT_SUCCESS;
 
 static void
-dump_data (Application *app)
+signal_handler (int signum)
 {
-    GError *err = NULL;
-    Profile *profile;
-
-    printf ("Saving profile (%d samples) in %s ... ",
-           collector_get_n_samples (app->collector),
-           app->outfile);
-    fflush (stdout);
-
-    collector_stop (app->collector);
-    
-    profile = collector_create_profile (app->collector);
-    profile_save (profile, app->outfile, &err);
-    
-    if (err)
-    {
-       printf ("failed\n");
-        fprintf (stderr, "Error saving %s: %s\n", app->outfile, err->message);
-        exit (1);
-    }
-    else
-    {
-       printf ("done\n\n");
-    }
-}
+  gint64 val = 1;
 
-static void
-signal_handler (int      signo,
-               gpointer data)
-{
-    Application *app = data;
-    
-    dump_data (app);
-    
-    while (g_main_context_iteration (NULL, FALSE))
-       ;
-    
-    g_main_loop_quit (app->main_loop);
+  write (efd, &val, sizeof val);
 }
 
-static char *
-usage_msg (const char *name)
+static gboolean
+dispatch (GSource     *source,
+          GSourceFunc  callback,
+          gpointer     callback_data)
 {
-    return g_strdup_printf (
-       "Usage: \n"
-       "    %s <outfile>\n"
-       "\n"
-       "On SIGTERM or SIGINT (Ctrl-C) the profile will be written to <outfile>",
-       name);
+  sp_profiler_stop (profiler);
+  g_main_loop_quit (main_loop);
+  return G_SOURCE_REMOVE;
 }
 
-static gboolean
-file_exists_and_is_dir (const char *name)
+static GSourceFuncs source_funcs = {
+  NULL, NULL, dispatch, NULL
+};
+
+static void
+profiler_stopped (SpProfiler *profiler,
+                  GMainLoop  *main_loop)
 {
-    return
-       g_file_test (name, G_FILE_TEST_EXISTS) &&
-       g_file_test (name, G_FILE_TEST_IS_DIR);
+  g_main_loop_quit (main_loop);
 }
 
 static void
-die (const char *err_msg)
+profiler_failed (SpProfiler   *profiler,
+                 const GError *reason,
+                 GMainLoop    *main_loop)
 {
-    if (err_msg)
-       fprintf (stderr, "\n%s\n\n", err_msg);
-    
-    exit (-1);
-}
+  g_assert (SP_IS_PROFILER (profiler));
+  g_assert (reason != NULL);
 
-static int opt_pid = -1;
+  g_printerr ("Failure: %s\n", reason->message);
+  exit_code = EXIT_FAILURE;
+}
 
-static GOptionEntry entries[] =
+gint
+main (gint   argc,
+      gchar *argv[])
 {
-  { "pid", 'p', 0, G_OPTION_ARG_INT, &opt_pid,
-    "Make sysprof specific to a task", NULL },
-  { NULL }
-};
+  SpCaptureWriter *writer;
+  SpSource *source;
+  GMainContext *main_context;
+  GOptionContext *context;
+  const gchar *filename = "capture.syscap";
+  GError *error = NULL;
+  GSource *gsource;
+  gchar *command = NULL;
+  int pid = -1;
+  int fd;
+  GOptionEntry entries[] = {
+    { "pid", 'p', 0, G_OPTION_ARG_INT, &pid, N_("Make sysprof specific to a task"), N_("PID") },
+    { "command", 'c', 0, G_OPTION_ARG_STRING, &command, N_("Run a command and profile the process"), 
N_("COMMAND") },
+    { NULL }
+  };
+
+  sp_clock_init ();
+
+  context = g_option_context_new (_("[CAPTURE_FILE] - Sysprof"));
+  g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
+
+  if (!g_option_context_parse (context, &argc, &argv, &error))
+    {
+      g_printerr ("%s\n", error->message);
+      return EXIT_FAILURE;
+    }
 
-int
-main (int argc, char *argv[])
-{
-    Application *app;
-    GOptionContext *context;
-    GError *err;
-    
-    err = NULL;
-
-    context = g_option_context_new ("- Sysprof");
-    g_option_context_add_main_entries (context, entries, NULL);
-    if (!g_option_context_parse (context, &argc, &argv, &err))
+  if (argc > 2)
+    {
+      gint i;
+
+      g_printerr (_("Too many arguments were passed to sysprof-cli:"));
+
+      for (i = 2; i < argc; i++)
+        g_printerr (" %s", argv [i]);
+      g_printerr ("\n");
+
+      return EXIT_FAILURE;
+    }
+
+  efd = eventfd (0, O_CLOEXEC);
+
+  main_loop = g_main_loop_new (NULL, FALSE);
+
+  gsource = g_source_new (&source_funcs, sizeof (GSource));
+  g_source_add_unix_fd (gsource, efd, G_IO_IN);
+  g_source_attach (gsource, NULL);
+
+  profiler = sp_profiler_new ();
+
+  g_signal_connect (profiler,
+                    "failed",
+                    G_CALLBACK (profiler_failed),
+                    main_loop);
+
+  g_signal_connect (profiler,
+                    "stopped",
+                    G_CALLBACK (profiler_stopped),
+                    main_loop);
+
+  if (argc == 2)
+    filename = argv[1];
+
+  if (-1 == (fd = g_open (filename, O_CREAT | O_RDWR | O_CLOEXEC, 0640)))
     {
-           g_print ("Failed to parse options: %s\n", err->message);
-           return 1;
+      g_printerr ("Failed to open %s\n", filename);
+      return EXIT_FAILURE;
     }
 
-    app = g_new0 (Application, 1);
-    app->collector = collector_new (FALSE, NULL, NULL);
-    app->outfile = g_strdup (argv[1]);
-    app->main_loop = g_main_loop_new (NULL, 0);
-    
-    if (!collector_start (app->collector, (pid_t) opt_pid, &err))
-       die (err->message);
-    
-    if (argc < 2)
-       die (usage_msg (argv[0]));
-    
-    if (!signal_set_handler (SIGTERM, signal_handler, app, &err))
-       die (err->message);
-    
-    if (!signal_set_handler (SIGINT, signal_handler, app, &err))
-       die (err->message);
-
-    if (file_exists_and_is_dir (app->outfile))
+  if (command != NULL)
     {
-       char *msg = g_strdup_printf ("Can't write to %s: is a directory\n",
-                                    app->outfile);
-       die (msg);
+      g_auto(GStrv) child_argv = NULL;
+      gint child_argc;
+
+      if (!g_shell_parse_argv (command, &child_argc, &child_argv, &error))
+        {
+          g_printerr ("Invalid command: %s\n", error->message);
+          return EXIT_FAILURE;
+        }
+
+      if (!g_spawn_async (NULL, child_argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &pid, &error))
+        {
+          g_printerr ("Invalid command: %s\n", error->message);
+          return EXIT_FAILURE;
+        }
+
+      /* Stop the process until we are setup */
+      if (0 != kill (pid, SIGSTOP))
+        {
+          g_printerr ("Failed to pause inferior during setup\n");
+          return EXIT_FAILURE;
+        }
     }
-    
-    g_main_loop_run (app->main_loop);
-    
-    signal_unset_handler (SIGTERM);
-    signal_unset_handler (SIGINT);
-    
-    return 0;
+
+  writer = sp_capture_writer_new_from_fd (fd, 0);
+  sp_profiler_set_writer (profiler, writer);
+
+  source = sp_proc_source_new ();
+  sp_profiler_add_source (profiler, source);
+  g_object_unref (source);
+
+  source = sp_perf_source_new ();
+
+  sp_profiler_add_source (profiler, source);
+  g_object_unref (source);
+
+  if (pid != -1)
+    {
+      sp_profiler_set_whole_system (profiler, FALSE);
+      sp_profiler_add_pid (profiler, pid);
+    }
+
+  signal (SIGINT, signal_handler);
+  signal (SIGTERM, signal_handler);
+
+  sp_profiler_start (profiler);
+
+  /* Restore the process if we stopped it */
+  if (command)
+    kill (pid, SIGCONT);
+
+  g_printerr ("Recording, press ^C to exit\n");
+
+  g_main_loop_run (main_loop);
+
+  main_context = g_main_loop_get_context (main_loop);
+  while (g_main_context_pending (main_context))
+    g_main_context_iteration (main_context, FALSE);
+
+  close (efd);
+
+  g_clear_pointer (&writer, sp_capture_writer_unref);
+  g_clear_object (&profiler);
+  g_clear_pointer (&main_loop, g_main_loop_unref);
+  g_clear_pointer (&context, g_option_context_free);
+
+  return EXIT_SUCCESS;
 }
diff --git a/tools/sysprof-dump.c b/tools/sysprof-dump.c
new file mode 100644
index 0000000..3e7b46d
--- /dev/null
+++ b/tools/sysprof-dump.c
@@ -0,0 +1,153 @@
+/* sysprof-dump.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "sp-capture-reader.h"
+
+gint
+main (gint argc,
+      gchar *argv[])
+{
+  SpCaptureReader *reader;
+  SpCaptureFrameType type;
+  GError *error = NULL;
+
+  if (argc != 2)
+    {
+      g_printerr ("usage: %s FILENAME\n", argv[0]);
+      return EXIT_FAILURE;
+    }
+
+  reader = sp_capture_reader_new (argv[1], &error);
+
+  if (reader == NULL)
+    {
+      g_printerr ("%s\n", error->message);
+      return EXIT_FAILURE;
+    }
+
+  while (sp_capture_reader_peek_type (reader, &type))
+    {
+      switch (type)
+        {
+        case SP_CAPTURE_FRAME_EXIT:
+          {
+            const SpCaptureExit *ex = sp_capture_reader_read_exit (reader);
+
+            if (ex == NULL)
+              return EXIT_FAILURE;
+
+            g_print ("EXIT: pid=%d\n", ex->frame.pid);
+
+            break;
+          }
+
+        case SP_CAPTURE_FRAME_FORK:
+          {
+            const SpCaptureFork *fk = sp_capture_reader_read_fork (reader);
+
+            if (fk == NULL)
+              return EXIT_FAILURE;
+
+            g_print ("FORK: pid=%d child_pid=%d\n", fk->frame.pid, fk->child_pid);
+
+            break;
+          }
+
+        case SP_CAPTURE_FRAME_JITMAP:
+          {
+            g_autoptr(GHashTable) ret = sp_capture_reader_read_jitmap (reader);
+            GHashTableIter iter;
+            SpCaptureAddress addr;
+            const gchar *str;
+
+            if (ret == NULL)
+              return EXIT_FAILURE;
+
+            g_print ("JITMAP:\n");
+
+            g_hash_table_iter_init (&iter, ret);
+            while (g_hash_table_iter_next (&iter, (gpointer *)&addr, (gpointer *)&str))
+              g_print ("  "SP_CAPTURE_ADDRESS_FORMAT" : %s\n", addr, str);
+
+            break;
+          }
+
+        case SP_CAPTURE_FRAME_MAP:
+          {
+            const SpCaptureMap *map = sp_capture_reader_read_map (reader);
+
+            g_print ("MAP: pid=%d\n"
+                     "   start  = %"G_GUINT64_FORMAT"\n"
+                     "     end  = %"G_GUINT64_FORMAT"\n"
+                     "   offset = %"G_GUINT64_FORMAT"\n"
+                     "    inode = %"G_GUINT64_FORMAT"\n"
+                     " filename = %s\n",
+                     map->frame.pid,
+                     map->start, map->end, map->offset, map->inode, map->filename);
+
+            break;
+          }
+
+        case SP_CAPTURE_FRAME_PROCESS:
+          {
+            const SpCaptureProcess *pr = sp_capture_reader_read_process (reader);
+
+            if (pr == NULL)
+              perror ("Failed to read process");
+
+            g_print ("PROCESS: pid=%d cmdline=%s\n", pr->frame.pid, pr->cmdline);
+            break;
+          }
+
+        case SP_CAPTURE_FRAME_SAMPLE:
+          {
+            const SpCaptureSample *s =  sp_capture_reader_read_sample (reader);
+            guint i;
+
+            g_print ("SAMPLE: pid=%d\n", s->frame.pid);
+
+            for (i = 0; i < s->n_addrs; i++)
+              g_print ("  "SP_CAPTURE_ADDRESS_FORMAT"\n", s->addrs[i]);
+
+            break;
+          }
+
+        case SP_CAPTURE_FRAME_TIMESTAMP:
+          {
+            const SpCaptureTimestamp *ts =  sp_capture_reader_read_timestamp (reader);
+            g_print ("TIMESTAMP: pid=%d time=%"G_GINT64_FORMAT"\n", ts->frame.pid, ts->frame.time);
+            break;
+          }
+
+        default:
+          g_print ("Skipping unknown frame type: (%d): ", type);
+          if (!sp_capture_reader_skip (reader))
+            {
+              g_print ("Failed\n");
+              return EXIT_FAILURE;
+            }
+          g_print ("Success\n");
+          break;
+        }
+    }
+
+  return EXIT_SUCCESS;
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]