diff --git a/src/bindings/php/SConscript b/src/bindings/php/SConscript index 94c9d83bb1a8afe2556eb2204dcf253f1749eab3..fc4c1d1a5a780e592a45a73ff7b9745de8dce618 100644 --- a/src/bindings/php/SConscript +++ b/src/bindings/php/SConscript @@ -10,10 +10,10 @@ phpenv.Append(CCFLAGS = ['-fpic', '-DSWIG', '-Wno-all', '-Wno-extra', '-Wno-erro phpenv.Append(LIBS = ['hammer']) phpenv.Append(LIBPATH = ['../../']) -swig_src = phpenv.Command("hammer.i", "../swig/hammer.i", Copy("$TARGET", "$SOURCE")) -bindings_src = phpenv.Command(['hammer.php', 'hammer_wrap.c', 'php_hammer.h'], 'hammer.i', 'swig -php -DHAMMER_INTERNAL__NO_STDARG_H -Isrc/ $SOURCE') +swig = ['hammer.i'] +bindings_src = phpenv.Command(['hammer.php', 'hammer_wrap.c', 'php_hammer.h'], swig, 'swig -php -DHAMMER_INTERNAL__NO_STDARG_H -Isrc/ $SOURCE') libhammer_php = phpenv.SharedLibrary('hammer', ['hammer_wrap.c']) -Default(swig_src, bindings_src, libhammer_php) +Default(swig, bindings_src, libhammer_php) phptestenv = phpenv.Clone() phptestenv['ENV']['LD_LIBRARY_PATH'] = os.path.dirname(str(libhammer_shared[0])) diff --git a/src/bindings/php/hammer.i b/src/bindings/php/hammer.i new file mode 100644 index 0000000000000000000000000000000000000000..e2a687741292861061cedb01e53482179ac49cce --- /dev/null +++ b/src/bindings/php/hammer.i @@ -0,0 +1,229 @@ +%module hammer; + +%ignore HCountedArray_; + +%inline %{ + static int h_tt_php; + %} + +%init %{ + h_tt_php = h_allocate_token_type("com.upstandinghackers.hammer.php"); + %} + +%inline { + struct HParsedToken_; + struct HParseResult_; + static zval* hpt_to_php(const struct HParsedToken_ *token); + + static struct HParsedToken_* call_action(const struct HParseResult_ *p, void* user_data); + } + +%typemap(in) (const uint8_t* str, const size_t len) { + $1 = (uint8_t*)(*$input)->value.str.val; + $2 = (*$input)->value.str.len; + } + +%apply (const uint8_t* str, const size_t len) { (const uint8_t* input, size_t length) } +%apply (const uint8_t* str, const size_t len) { (const uint8_t* charset, size_t length) } + +%typemap(in) void*[] { + if (IS_ARRAY == Z_TYPE_PP($input)) { + HashTable *arr = Z_ARRVAL_PP($input); + HashPosition pointer; + int size = zend_hash_num_elements(arr); + int i = 0; + int res = 0; + $1 = (void**)malloc((size+1)*sizeof(HParser*)); + for (i=0; i<size; i++) { + zval **data; + if (zend_hash_index_find(arr, i, (void**)&data) == FAILURE) { + // FIXME raise some error + arg1 = NULL; + } else { + res = SWIG_ConvertPtr(*data, &(arg1[i]), SWIGTYPE_p_HParser_, 0 | 0); + if (!SWIG_IsOK(res)) { + // TODO do we not *have* SWIG_TypeError? + SWIG_exception_fail(res, "that wasn't an HParser"); + } + } + } + } else { + // FIXME raise some error + $1 = NULL; + } + } + +%typemap(in) uint8_t { + if (IS_LONG == Z_TYPE_PP($input)) { + $1 = Z_LVAL_PP($input); + } else if (IS_STRING != Z_TYPE_PP($input)) { + // FIXME raise some error + } else { + $1 = *(uint8_t*)Z_STRVAL_PP($input); + } + } + +%typemap(out) HBytes* { + RETVAL_STRINGL((char*)$1->token, $1->len, 1); + } + +/* TODO do we need this anymore? +%typemap(out) struct HCountedArray_* { + + } +*/ +%typemap(out) struct HParseResult_* { + if ($1 == NULL) { + // TODO: raise parse failure + RETVAL_NULL(); + } else { + if ($1->ast == NULL) { + RETVAL_NULL(); + } else { + switch($1->ast->token_type) { + case TT_NONE: + RETVAL_NULL(); + break; + case TT_BYTES: + RETVAL_STRINGL((char*)$1->ast->token_data.bytes.token, $1->ast->token_data.bytes.len, 1); + break; + case TT_SINT: + RETVAL_LONG($1->ast->token_data.sint); + break; + case TT_UINT: + RETVAL_LONG($1->ast->token_data.uint); + break; + case TT_SEQUENCE: + array_init($result); + for (int i=0; i < $1->ast->token_data.seq->used; i++) { + add_next_index_zval($result, hpt_to_php($1->ast->token_data.seq->elements[i])); + } + break; + default: + /* if (token->token_type == h_tt_php) { */ + /* ZEND_REGISTER_RESOURCE(return_value, token->token_data.user, le_swig__p_void); // it's a void*, what else could I do with it? */ + /* return return_value; */ + /* } else { */ + /* // I guess that's a python thing */ + /* //return (zval*)SWIG_NewPointerObj((void*)token, SWIGTYPE_p_HParsedToken_, 0 | 0); */ + /* // TODO: support registry */ + /* } */ + break; + } + } + } + } +/* +%typemap(in) (HPredicate* pred, void* user_data) { + + } +*/ +%typemap(in) (const HAction a, void* user_data) { + $2 = $input; + $1 = call_action; + } + +%include "../swig/hammer.i"; + +%inline { + static zval* hpt_to_php(const HParsedToken *token) { + zval *ret; + ALLOC_INIT_ZVAL(ret); + if (token == NULL) { + ZVAL_NULL(ret); + return ret; + } + switch (token->token_type) { + case TT_NONE: + ZVAL_NULL(ret); + return ret; + case TT_BYTES: + ZVAL_STRINGL(ret, (char*)token->token_data.bytes.token, token->token_data.bytes.len, 1); + return ret; + case TT_SINT: + ZVAL_LONG(ret, token->token_data.sint); + return ret; + case TT_UINT: + ZVAL_LONG(ret, token->token_data.uint); + return ret; + case TT_SEQUENCE: + array_init(ret); + for (int i=0; i < token->token_data.seq->used; i++) { + add_next_index_zval(ret, hpt_to_php(token->token_data.seq->elements[i])); + } + return ret; + default: + /* if (token->token_type == h_tt_php) { */ + /* ZEND_REGISTER_RESOURCE(return_value, token->token_data.user, le_swig__p_void); // it's a void*, wh + /* return return_value; */ + /* } else { */ + /* // I guess that's a python thing */ + /* //return (zval*)SWIG_NewPointerObj((void*)token, SWIGTYPE_p_HParsedToken_, 0 | 0); */ + /* // TODO: support registry */ + /* } */ + break; + } + } + + static struct HParsedToken_* call_action(const struct HParseResult_ *p, void* user_data) { + zval *args[1]; + zval ret; + // in PHP land, the HAction is passed by its name as a string + if (IS_STRING != Z_TYPE_P((zval*)user_data)) { + // FIXME throw some error + return NULL; + } + zval *callable; + callable = user_data; + args[0] = hpt_to_php(p->ast); + int ok = call_user_function(EG(function_table), NULL, callable, &ret, 1, args TSRMLS_CC); + if (ok != SUCCESS) { + // FIXME throw some error + return NULL; + } + // TODO: add reference to ret to parse-local data + HParsedToken *tok = h_make(p->arena, h_tt_php, &ret); + return tok; + } + } + +%pragma(php) code=" + +function ch($ch) +{ + if (is_string($ch)) + return h_token($ch); + else + return h_ch($ch); +} + +function choice() +{ + $arg_list = func_get_args(); + $arg_list[] = NULL; + return h_choice__a($arg_list); +} + +function sequence() +{ + $arg_list = func_get_args(); + $arg_list[] = NULL; + return h_sequence__a($arg_list); +} + +function action($p, $act) +{ + return h_action($p, $act); +} + +function in($charset) +{ + return action(h_in($charset), 'chr'); +} + +function not_in($charset) +{ + return action(h_not_in($charset), 'chr'); +} +" + diff --git a/src/bindings/swig/hammer.i b/src/bindings/swig/hammer.i index d7cf3a061a0b0b33d13bad825b30f255af58eec5..122ffe4012937add3bd71107aef0589980f3575d 100644 --- a/src/bindings/swig/hammer.i +++ b/src/bindings/swig/hammer.i @@ -1,5 +1,4 @@ %module hammer -%nodefaultctor; %nodefaultctor; @@ -132,141 +131,6 @@ #warning no uint8_t* typemaps defined #endif -//%include "typemaps.i" - -#if defined(SWIGPHP) -%ignore HCountedArray_; - -%inline %{ - static int h_tt_php; - %} - -%init %{ - h_tt_php = h_allocate_token_type("com.upstandinghackers.hammer.php"); - %} - -%inline { - struct HParsedToken_; - struct HParseResult_; - static zval* hpt_to_php(const struct HParsedToken_ *token); - - static struct HParsedToken_* call_action(const struct HParseResult_ *p, void* user_data); - } - -%typemap(in) (const uint8_t* str, const size_t len) { - $1 = (uint8_t*)(*$input)->value.str.val; - $2 = (*$input)->value.str.len; - } - -//%typemap(out) (const uint8_t* str, const size_t len) { -// RETVAL_STRINGL((char*)$1, $2, 1); -// } -%apply (const uint8_t* str, const size_t len) { (const uint8_t* input, size_t length) } -%apply (const uint8_t* str, const size_t len) { (const uint8_t* charset, size_t length) } -%typemap(in) void*[] { - if (IS_ARRAY == Z_TYPE_PP($input)) { - HashTable *arr = Z_ARRVAL_PP($input); - HashPosition pointer; - int size = zend_hash_num_elements(arr); - int i = 0; - int res = 0; - $1 = (void**)malloc((size)*sizeof(HParser*)); - for (i=0; i<size; i++) { - zval **data; - if (zend_hash_index_find(arr, i, (void**)&data) == FAILURE) { - // FIXME raise some error - $1 = NULL; - } else { - res = SWIG_ConvertPtr(*data, &($1[i]), SWIGTYPE_p_HParser_, 0 | 0); - if (!SWIG_IsOK(res)) { - // TODO do we not *have* SWIG_TypeError? - SWIG_exception_fail(res, "that wasn't an HParser"); - } - } - } - } else { - // FIXME some error - $1 = NULL; - } - } - -%typemap(in) uint8_t { - if (IS_LONG == Z_TYPE_PP($input)) { - $1 = Z_LVAL_PP($input); - } else if (IS_STRING != Z_TYPE_PP($input)) { - // FIXME raise some error - } else { - $1 = *(uint8_t*)Z_STRVAL_PP($input); - } - } - -%typemap(out) HBytes* { - RETVAL_STRINGL((char*)$1->token, $1->len, 1); - } - -%typemap(in) HAction* { - if (IS_CALLABLE == Z_TYPE_PP($input)) { - if (!zend_make_callable($1, *$input TSRMLS_CC)) { - // FIXME some error - $1 = NULL; - } - // don't need an else here, $1 gets populated - } else { - // FIXME some error - $1 = NULL; - } - } - -%typemap(out) struct HParseResult_* { - if ($1 == NULL) { - // TODO: raise parse failure - RETVAL_NULL(); - } else { - if ($1->ast == NULL) { - RETVAL_NULL(); - } else { - switch($1->ast->token_type) { - case TT_NONE: - RETVAL_NULL(); - break; - case TT_BYTES: - RETVAL_STRINGL((char*)$1->ast->token_data.bytes.token, $1->ast->token_data.bytes.len, 1); - break; - case TT_SINT: - RETVAL_LONG($1->ast->token_data.sint); - break; - case TT_UINT: - RETVAL_LONG($1->ast->token_data.uint); - break; - case TT_SEQUENCE: - array_init($result); - for (int i=0; i < $1->ast->token_data.seq->used; i++) { - add_next_index_zval($result, hpt_to_php($1->ast->token_data.seq->elements[i])); - } - break; - default: - /* if (token->token_type == h_tt_php) { */ - /* ZEND_REGISTER_RESOURCE(return_value, token->token_data.user, le_swig__p_void); // it's a void*, what else could I do with it? */ - /* return return_value; */ - /* } else { */ - /* // I guess that's a python thing */ - /* //return (zval*)SWIG_NewPointerObj((void*)token, SWIGTYPE_p_HParsedToken_, 0 | 0); */ - /* // TODO: support registry */ - /* } */ - break; - } - } - } - } -/* -%typemap(in) (HPredicate* pred, void* user_data) { - - } -*/ -#else - #warning no Hammer typemaps defined -#endif - // 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" @@ -480,108 +344,5 @@ def int64(): return _h_int64() %} #endif -//%apply const char* { const uint8_t* } - -#if defined(SWIGPHP) -%inline { - static zval* hpt_to_php(const HParsedToken *token) { - zval *ret; - ALLOC_INIT_ZVAL(ret); - if (token == NULL) { - ZVAL_NULL(ret); - return ret; - } - switch (token->token_type) { - case TT_NONE: - ZVAL_NULL(ret); - return ret; - case TT_BYTES: - ZVAL_STRINGL(ret, (char*)token->token_data.bytes.token, token->token_data.bytes.len, 1); - return ret; - case TT_SINT: - ZVAL_LONG(ret, token->token_data.sint); - return ret; - case TT_UINT: - ZVAL_LONG(ret, token->token_data.uint); - return ret; - case TT_SEQUENCE: - array_init(ret); - for (int i=0; i < token->token_data.seq->used; i++) { - add_next_index_zval(ret, hpt_to_php(token->token_data.seq->elements[i])); - } - return ret; - default: - /* if (token->token_type == h_tt_php) { */ - /* ZEND_REGISTER_RESOURCE(return_value, token->token_data.user, le_swig__p_void); // it's a void*, wh - /* return return_value; */ - /* } else { */ - /* // I guess that's a python thing */ - /* //return (zval*)SWIG_NewPointerObj((void*)token, SWIGTYPE_p_HParsedToken_, 0 | 0); */ - /* // TODO: support registry */ - /* } */ - break; - } - } - - static struct HParsedToken_* call_action(const struct HParseResult_ *p, void* user_data) { - zval *args[1]; - zval ret; - // in PHP land, the HAction is passed by its name as a string - if (IS_STRING != Z_TYPE_P((zval*)user_data)) { - // FIXME throw some error - return NULL; - } - zval *callable; - callable = user_data; - args[0] = hpt_to_php(p->ast); - int ok = call_user_function(EG(function_table), NULL, callable, &ret, 1, args TSRMLS_CC); - if (ok != SUCCESS) { - // FIXME throw some error - return NULL; - } - // TODO: add reference to ret to parse-local data - HParsedToken *tok = h_make(p->arena, h_tt_php, &ret); - return tok; - } - } -%pragma(php) code=" -function ch($ch) -{ - if (is_string($ch)) - return h_token($ch); - else - return h_ch($ch); -} - -function choice() -{ - $arg_list = func_get_args(); - $arg_list[] = NULL; - return h_choice__a($arg_list); -} - -function sequence() -{ - $arg_list = func_get_args(); - $arg_list[] = NULL; - return h_sequence__a($arg_list); -} - -function action($p, $act) -{ - return h_action($p, $act); -} - -function in($charset) -{ - return action(h_in($charset), 'chr'); -} - -function not_in($charset) -{ - return action(h_not_in($charset), 'chr'); -} -" -#endif