%module hammer; %include "exception.i"; %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_; void hpt_to_php(zval *return_value, 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; itoken, $1->len, 1); } %typemap(out) struct HParseResult_* { if ($1 == NULL) { /* If we want parse errors to be exceptions, this is the place to do it */ //SWIG_exception(SWIG_TypeError, "typemap: should have been an HParseResult*, was NULL"); RETVAL_NULL(); } else { hpt_to_php($result, $1->ast); } } %include "../swig/hammer.i"; %inline { void hpt_to_php(zval *return_value, const HParsedToken *token) { if (!token) { RETVAL_NULL(); return; } switch (token->token_type) { case TT_NONE: RETVAL_NULL(); break; case TT_BYTES: RETVAL_STRINGL((char*)token->token_data.bytes.token, token->token_data.bytes.len, 1); break; case TT_SINT: RETVAL_LONG(token->token_data.sint); break; case TT_UINT: RETVAL_LONG(token->token_data.uint); break; case TT_SEQUENCE: array_init(return_value); for (int i=0; i < token->token_data.seq->used; i++) { zval *tmp; ALLOC_INIT_ZVAL(tmp); hpt_to_php(tmp, token->token_data.seq->elements[i]); add_next_index_zval(return_value, tmp); } break; default: if (token->token_type == h_tt_php) { RETVAL_RESOURCE(token->token_data.user); } else { int res = 0; res = SWIG_ConvertPtr(return_value, (void*)token, SWIGTYPE_p_HParsedToken_, 0 | 0); if (!SWIG_IsOK(res)) { SWIG_exception(SWIG_TypeError, "hpt_to_php: that wasn't an HParsedToken"); } // TODO: support registry } break; } } static HParsedToken* call_action(const HParseResult *p, void *user_data) { zval *args[1]; zval ret, func; ZVAL_STRING(&func, (const char*)user_data, 0); hpt_to_php(args[0], p->ast); int ok = call_user_function(EG(function_table), NULL, &func, &ret, 1, args TSRMLS_CC); if (ok != SUCCESS) { printf("call_user_function failed\n"); // FIXME throw some error return NULL; } printf("Value being returned is %s\n", Z_STRVAL(ret)); // TODO: add reference to ret to parse-local data HParsedToken *tok = h_make(p->arena, h_tt_php, &ret); return tok; } HParser* action(HParser *parser, const char *name) { return h_action(parser, call_action, (void*)name); } } %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 in($charset) { return action(h_in($charset), \"chr\"); } function not_in($charset) { return action(h_not_in($charset), \"chr\"); } "