From 4b00cd88e533597f6ca9507ab3c061052bc6cb03 Mon Sep 17 00:00:00 2001
From: "Meredith L. Patterson" <mlp@thesmartpolitenerd.com>
Date: Sun, 17 Nov 2013 17:57:43 -0600
Subject: [PATCH] scons builds the SWIG PHP bindings that can create parsers
 but not parse any input yet

---
 src/SConscript              |  2 +-
 src/allocator.h             |  4 +++
 src/bindings/php/SConscript | 12 +++++++++
 src/bindings/swig/hammer.i  | 16 ++++++++++++
 src/hammer.h                | 49 +++++++++++++++++++++++++++++--------
 5 files changed, 72 insertions(+), 11 deletions(-)
 create mode 100644 src/bindings/php/SConscript
 create mode 100644 src/bindings/swig/hammer.i

diff --git a/src/SConscript b/src/SConscript
index a06244b9..1240fd08 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -1,7 +1,7 @@
 # -*- python -*-
 Import('env')
 
-bindings = []
+bindings = ['php']
 
 dist_headers = [
     "hammer.h",
diff --git a/src/allocator.h b/src/allocator.h
index 2dfc14e6..a02d97cd 100644
--- a/src/allocator.h
+++ b/src/allocator.h
@@ -29,7 +29,11 @@ typedef struct HAllocator_ {
 typedef struct HArena_ HArena ; // hidden implementation
 
 HArena *h_new_arena(HAllocator* allocator, size_t block_size); // pass 0 for default...
+#ifndef SWIG
 void* h_arena_malloc(HArena *arena, size_t count) __attribute__(( malloc, alloc_size(2) ));
+#else
+void* h_arena_malloc(HArena *arena, size_t count);
+#endif
 void h_arena_free(HArena *arena, void* ptr); // For future expansion, with alternate memory managers.
 void h_delete_arena(HArena *arena);
 
diff --git a/src/bindings/php/SConscript b/src/bindings/php/SConscript
new file mode 100644
index 00000000..9962264e
--- /dev/null
+++ b/src/bindings/php/SConscript
@@ -0,0 +1,12 @@
+# -*- python -*-
+Import('env')
+
+phpenv = env.Clone()
+
+phpenv.Append(CPPPATH = ['../../', '/usr/include/php5', '/usr/include/php5/main', '/usr/include/php5/Zend', '/usr/include/php5/TSRM'])
+phpenv.Append(CCFLAGS = ['-fpic', '-DSWIG', '-Wno-unused-variable', '-Wno-unused-label', '-Wno-unused-function', '-Wno-missing-field-initializers'])
+phpenv.Append(SWIGFLAGS = '-DHAMMER_INTERNAL__NO_STDARG_H -Isrc/ -php')
+
+swig = ['../swig/hammer.i']
+
+libhammer_php = phpenv.SharedLibrary('hammer', swig)
\ No newline at end of file
diff --git a/src/bindings/swig/hammer.i b/src/bindings/swig/hammer.i
new file mode 100644
index 00000000..f784f31e
--- /dev/null
+++ b/src/bindings/swig/hammer.i
@@ -0,0 +1,16 @@
+%module hammer
+
+%include "typemaps.i"
+%include "stdint.i"
+
+ // All the include paths are relative to the build, i.e., ../../. If you need to build these manually (i.e., not with scons), keep that in mind.
+%{
+#include "allocator.h"
+#include "hammer.h"
+#include "internal.h"
+%}
+%include "allocator.h"
+%include "hammer.h"
+
+%apply const char* { const uint8_t* }
+
diff --git a/src/hammer.h b/src/hammer.h
index c70c7632..c1d6e77e 100644
--- a/src/hammer.h
+++ b/src/hammer.h
@@ -29,7 +29,9 @@
 #define BIT_LITTLE_ENDIAN 0x0
 #define BYTE_LITTLE_ENDIAN 0x0
 
+#ifndef HAMMER_INTERNAL__NO_STDARG_H
 typedef int bool;
+#endif // HAMMER_INTERNAL__NO_STDARG_H
 
 typedef struct HParseState_ HParseState;
 
@@ -68,8 +70,21 @@ typedef struct HBytes_ {
   size_t len;
 } HBytes;
 
+#ifdef SWIG
+typedef union {
+  HBytes bytes;
+  int64_t sint;
+  uint64_t uint;
+  double dbl;
+  float flt;
+  HCountedArray *seq;
+  void *user;
+} HTokenData;
+#endif
+
 typedef struct HParsedToken_ {
   HTokenType token_type;
+#ifndef SWIG
   union {
     HBytes bytes;
     int64_t sint;
@@ -79,6 +94,9 @@ typedef struct HParsedToken_ {
     HCountedArray *seq; // a sequence of HParsedToken's
     void *user;
   };
+#else
+  HTokenData token_data;
+#endif
   size_t index;
   char bit_offset;
 } HParsedToken;
@@ -142,12 +160,23 @@ typedef struct HParserTestcase_ {
   char* output_unambiguous;
 } HParserTestcase;
 
+#ifdef SWIG
+typedef union {
+  const char* actual_results;
+  size_t parse_time;
+} HResultTiming;
+#endif
+
 typedef struct HCaseResult_ {
   bool success;
+#ifndef SWIG
   union {
     const char* actual_results; // on failure, filled in with the results of h_write_result_unamb
     size_t parse_time; // on success, filled in with time for a single parse, in nsec
   };
+#else
+  HResultTiming timestamp;
+#endif
 } HCaseResult;
 
 typedef struct HBackendResults_ {
@@ -177,7 +206,7 @@ typedef struct HBenchmarkResults_ {
   rtype_t name(__VA_ARGS__) attr;					\
   rtype_t name##__m(HAllocator* mm__, __VA_ARGS__) attr
 
-#ifndef HAMMER_INTERNAL__NO_STDARG_H
+#ifndef SWIG
 #define HAMMER_FN_DECL_VARARGS(rtype_t, name, ...)			\
   rtype_t name(__VA_ARGS__, ...);					\
   rtype_t name##__m(HAllocator* mm__, __VA_ARGS__, ...);		\
@@ -195,17 +224,17 @@ typedef struct HBenchmarkResults_ {
   rtype_t name##__a(void *args[]);					\
   rtype_t name##__ma(HAllocator *mm__, void *args[])
 #else
-#define HAMMER_FN_DECL_VARARGS(rtype_t, name, ...)			\
-  rtype_t name(__VA_ARGS__, ...);					\
-  rtype_t name##__m(HAllocator* mm__, __VA_ARGS__, ...);		\
-  rtype_t name##__a(void *args[]);					\
+#define HAMMER_FN_DECL_VARARGS(rtype_t, name, params...)  \
+  rtype_t name(params, ...);				  \
+  rtype_t name##__m(HAllocator* mm__, params, ...);    	  \
+  rtype_t name##__a(void *args[]);			 \
   rtype_t name##__ma(HAllocator *mm__, void *args[])
 
 // Note: this drops the attributes on the floor for the __v versions
-#define HAMMER_FN_DECL_VARARGS_ATTR(attr, rtype_t, name, ...)		\
-  rtype_t name(__VA_ARGS__, ...) attr;					\
-  rtype_t name##__m(HAllocator* mm__, __VA_ARGS__, ...) attr;		\
-  rtype_t name##__a(void *args[]);					\
+#define HAMMER_FN_DECL_VARARGS_ATTR(attr, rtype_t, name, params...)		\
+  rtype_t name(params, ...);				\
+  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
 // }}}
@@ -631,7 +660,7 @@ HParsedToken *h_act_ignore(const HParseResult *p);
 // {{{ Benchmark functions
 HAMMER_FN_DECL(HBenchmarkResults *, h_benchmark, HParser* parser, HParserTestcase* testcases);
 void h_benchmark_report(FILE* stream, HBenchmarkResults* results);
-void h_benchmark_dump_optimized_code(FILE* stream, HBenchmarkResults* results);
+//void h_benchmark_dump_optimized_code(FILE* stream, HBenchmarkResults* results);
 // }}}
 
 // {{{ Token type registry
-- 
GitLab