diff --git a/.travis.yml b/.travis.yml
index 8c5af523ada62766b6fdc18fb47fd92f7a613964..cb81ea8340b0d463b4180f637aadd4f14cc57968 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,15 +8,42 @@ matrix:
   include:
     - compiler: gcc
       language: python
-      python: 2.7
+      python: "2.7"
       env: BINDINGS=python
     - compiler: clang
       language: python
-      python: 2.7
-      env: BINDINGS=python
+      python: "2.7"
+      env: BINDINGS=python CC=clang
+    - compiler: gcc
+      language: perl
+      perl: "5.18"
+      env: BINDINGS=perl
+    - compiler: clang
+      language: perl
+      perl: "5.18"
+      env: BINDINGS=perl CC=clang
+    - compiler: gcc
+      language: perl
+      perl: "5.14"
+      env: BINDINGS=perl
+    - compiler: clang
+      language: perl
+      perl: "5.14"
+      env: BINDINGS=perl CC=clang
+    - compiler: gcc
+      language: perl
+      perl: "5.10"
+      env: BINDINGS=perl
+    - compiler: clang
+      language: perl
+      perl: "5.10"
+      env: BINDINGS=perl CC=clang
 before_install:
   - sudo apt-get update -qq
-  - if [ "$BINDINGS" == "python" ]; then sudo apt-get install -qq swig python-dev; fi
+  - if [ "$BINDINGS" != "none" ]; then sudo add-apt-repository ppa:dns/irc -y; sudo apt-get update -qq; sudo apt-get install -qq swig=2.0.8-1irc1~12.04; swig -version; fi
+  - if [ "$BINDINGS" == "python" ]; then sudo apt-get install -qq python-dev; fi
+
+install: true
 script: 
   - scons bindings=$BINDINGS test
 notifications:
diff --git a/README.md b/README.md
index 6f087c624057f2a541abbb8f7500238988b79fc5..f0faf2863354f9b8a0ab0d44f143ff9679236607 100644
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@ Features
   * Java (not currently building; give us a few days)
   * Python
   * Ruby (not yet implemented)
-  * Perl (not yet implemented)
+  * Perl
   * [Go](https://github.com/prevoty/hammer)
   * PHP (not yet implemented)
   * .NET (not yet implemented)
@@ -30,18 +30,18 @@ Installing
 ==========
 ### Prerequisites
 * SCons
-* a JDK
 
 ### Optional Dependencies
-* pkg-config (for `make test`)
-* glib-2.0 (>= 2.29) (for `make test`)
-* glib-2.0-dev (for `make test`)
-* swig (for Python bindings)
+* pkg-config (for `scons test`)
+* glib-2.0 (>= 2.29) (for `scons test`)
+* glib-2.0-dev (for `scons test`)
+* swig (for Python/Perl bindings; Perl requires >= 2.0.8)
 * python2.7-dev (for Python bindings)
+* a JDK (for Java bindings)
 
 To build, type `scons`. To run the built-in test suite, type `scons test`. For a debug build, add `--variant=debug`
 
-To build bindings, pass a "bindings" argument to scons, e.g. `scons bindings=python`. `scons bindings=python test` will build Python bindings and run tests for both C and Python. `--variant=debug` is valid here too.
+To build bindings, pass a "bindings" argument to scons, e.g. `scons bindings=python`. `scons bindings=python test` will build Python bindings and run tests for both C and Python. `--variant=debug` is valid here too. You can build more than one set of bindings at a time; just separate them with commas, e.g. `scons bindings=python,perl`.
 
 For Java, if jni.h and jni_md.h aren't already somewhere on your include path, prepend
 `C_INCLUDE_PATH=/path/to/jdk/include` to that.
@@ -66,6 +66,8 @@ Known Issues
 ============
 The Python bindings only work with Python 2.7. SCons doesn't work with Python 3, and PyCapsule isn't available in 2.6 and below, so 2.7 is all you get. Sorry about that.
 
+The requirement for SWIG >= 2.0.8 for Perl bindings is due to a [known bug](http://sourceforge.net/p/swig/patches/324/) in SWIG. [ppa:dns/irc](https://launchpad.net/~dns/+archive/irc) has backports of SWIG 2.0.8 for Ubuntu versions 10.04-12.10; you can also [build SWIG from source](http://www.swig.org/download.html).
+
 Community
 =========
 Please join us at `#hammer` on `irc.upstandinghackers.com` if you have any questions or just want to talk about parsing.
diff --git a/src/bindings/perl/Makefile.PL b/src/bindings/perl/Makefile.PL
index c9bf9db947a5cd9637de62b816574b7fb0e77009..68b6782980e2174071658865af4e7489ef4847f3 100644
--- a/src/bindings/perl/Makefile.PL
+++ b/src/bindings/perl/Makefile.PL
@@ -7,9 +7,9 @@ chdir(dirname($0));
 
 WriteMakefile(
     NAME => "hammer",
-    LIBS => ["-lhammer"],
+    LIBS => ["-L../../ -lhammer"],
     OBJECT => 'hammer_wrap.o',
     INC => '-I../..',
-    CCFLAGS => "$Config{ccflags} -DSWIG -DHAMMER_INTERNAL__NO_STDARG_H -std=gnu99",
+    CCFLAGS => "$Config{ccflags} -DSWIG -DHAS_BOOL -std=gnu99",
     );
 
diff --git a/src/bindings/perl/SConscript b/src/bindings/perl/SConscript
index c9a20fd250809c050e74322184840671a8163d99..49b693a7035cabfe1914c0a2fc172d31a07e23dd 100644
--- a/src/bindings/perl/SConscript
+++ b/src/bindings/perl/SConscript
@@ -5,13 +5,13 @@ Import("env libhammer_shared testruns targets")
 perlenv = env.Clone()
 
 perlenv.Append(CCFLAGS=["-fpic", '-DSWIG', '-Wno-all',
-                        '-Wno-extra', '-Wno-error',
-                        '-DHAMMER_INTERNAL__NO_STDARG_H'],
+                        '-Wno-extra', '-Wno-error'],
                CPPPATH=["../.."],
                LIBS=['hammer'],
                LIBPATH=["../.."],
                SWIGFLAGS=["-DHAMMER_INTERNAL__NO_STDARG_H",
                           "-Isrc/", "-perl"])
+perlenv['ENV']['CC'] = perlenv['CC']
 import os
 if 'PERL_MM_OPT' in os.environ:
     perlenv['ENV']['PERL_MM_OPT'] = os.environ['PERL_MM_OPT']
@@ -21,7 +21,7 @@ if 'PERL5LIB' in os.environ:
 swig = ['hammer.i']
 
 hammer_wrap = perlenv.Command(['hammer_wrap.c', 'hammer.pm'], swig, "swig $SWIGFLAGS $SOURCE")
-makefile = perlenv.Command(['Makefile'], ['Makefile.PL'], "perl $SOURCE")
+makefile = perlenv.Command(['Makefile'], ['Makefile.PL'], "perl $SOURCE CC=" + perlenv['ENV']['CC'])
 
 targetdir = os.path.dirname(str(hammer_wrap[0].path))
 
diff --git a/src/bindings/perl/hammer.i b/src/bindings/perl/hammer.i
index ff9d7f4ebc7cb71c08f0d17872c42159bd41d628..eaf504d87f1b38c07098a3414a7011952bcbbeda 100644
--- a/src/bindings/perl/hammer.i
+++ b/src/bindings/perl/hammer.i
@@ -1,6 +1,7 @@
 %module hammer;
 %begin %{
 #include <unistd.h>
+#include <stdbool.h>
 #include <stdint.h>
 %}
 
@@ -36,7 +37,7 @@
     SWIG_exception_fail(SWIG_TypeError, "Expected array ref");
 
   AV* av = (AV*) SvRV($input);
-  size_t amax = av_top_index(av) + 1; // I want the length, not the top index...
+  size_t amax = av_len(av) + 1; // I want the length, not the top index...
   // TODO: is this array copied?
   $1 = malloc((amax+1) * sizeof(*$1));
   $1[amax] = NULL;
diff --git a/src/hammer.h b/src/hammer.h
index 6756c0cc584951c905b9abdc918d5587b3ced28e..2914b8ffee80f8f0409546a85f737e8920480d51 100644
--- a/src/hammer.h
+++ b/src/hammer.h
@@ -20,6 +20,7 @@
 #ifndef HAMMER_INTERNAL__NO_STDARG_H
 #include <stdarg.h>
 #endif // HAMMER_INTERNAL__NO_STDARG_H
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include "allocator.h"
@@ -33,12 +34,6 @@
 extern "C" {
 #endif
 
-#ifndef __cplusplus
-#ifndef HAMMER_INTERNAL__NO_STDARG_H
-typedef int bool;
-#endif // HAMMER_INTERNAL__NO_STDARG_H
-#endif
-
 typedef struct HParseState_ HParseState;
 
 typedef enum HParserBackend_ {
@@ -242,7 +237,7 @@ typedef struct HBenchmarkResults_ {
   rtype_t name##__m(HAllocator* mm__, params, ...);       	\
   rtype_t name##__a(void *args[]);				\
   rtype_t name##__ma(HAllocator *mm__, void *args[])
-#endif // HAMMER_INTERNAL__NO_STDARG_H
+#endif // SWIG
 // }}}