PEAR::CodeGen_PECLの例外定義対応パッチ
PEAR::CodeGen_PECLの構成・動作とCソースでの例外の投げ方が分かってきたので、ここら辺でひとつPEAR::CodeGen_PECLの例外定義対応パッチを作ってみました。
- CodeGen_PECL_throws_patch.zip(md5:4e4f3f0693d4c21d58bd69231124bf69)
パッチ当てるのが面倒な方は、以下のアーカイブでCodeGen_PECLのファイルを上書きしてください。
- PECL_throws.zip(md5:7849f90a76d5987bba52299a218a9ed1)
パッチを適用/ファイルを差し替えると、以下のことが行えるようになります。
- function要素の属性として「throws」が追加される(関数・メソッドの両者で有効)
- throws属性にはthrowされる例外クラス名をカンマ区切りで記述
- 例外クラスに関するクラスエントリなどのコードを出力
- 関数・メソッドに例外を投げるためのコードを出力
- code要素の値として独自コードを記載していない場合のみ
たとえば、以下のようなspecファイルの場合、
<?xml version="1.0"?> <extension name="exception_test" version="0.0.4"> <function name="TestFunction" throws="TestFunctionException"> <proto>bool TestFunction()</proto> </function> <class name="ExceptionTest"> <function name="throwException" throws="Exception"> <proto>bool throwException()</proto> </function> <function name="throwAnotherException" throws="AnotherException"> <proto>bool throwAnotherException()</proto> </function> <function name="throwAnotherException2" throws="AnotherException"> <proto>bool throwAnotherException2()</proto> </function> </class> <class name="ExceptionTest2"> <function name="throwException" throws="Exception, AnotherException"> <proto>bool throwException()</proto> </function> <function name="throwAnotherException" throws="AnotherException"> <proto>bool throwAnotherException()</proto> </function> </class> </extension>
次のようなコードを出力します(長いです)。
/* +----------------------------------------------------------------------+ | unknown license: | +----------------------------------------------------------------------+ +----------------------------------------------------------------------+ */ /* $ Id: $ */ #include "php_exception_test.h" #if HAVE_EXCEPTION_TEST /* {{{ Exception class definitions */ zend_class_entry *AnotherException_exception_ce; zend_class_entry *TestFunctionException_exception_ce; /* }}} Exception class definitions*/ /* {{{ Class definitions */ /* {{{ Class ExceptionTest */ static zend_class_entry * ExceptionTest_ce_ptr = NULL; /* {{{ Methods */ /* {{{ proto bool throwException() */ PHP_METHOD(ExceptionTest, throwException) { zend_class_entry * _this_ce; zval * _this_zval = NULL; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &_this_zval, ExceptionTest_ce_ptr) == FAILURE) { return; } _this_ce = Z_OBJCE_P(_this_zval); php_error(E_WARNING, "throwException: not yet implemented"); RETURN_FALSE; RETURN_FALSE; } /* }}} throwException */ /* {{{ proto bool throwAnotherException() */ PHP_METHOD(ExceptionTest, throwAnotherException) { zend_class_entry * _this_ce; zval * _this_zval = NULL; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &_this_zval, ExceptionTest_ce_ptr) == FAILURE) { return; } _this_ce = Z_OBJCE_P(_this_zval); zend_throw_exception_ex(AnotherException_exception_ce, 0 TSRMLS_CC, "AnotherException was threw"); php_error(E_WARNING, "throwAnotherException: not yet implemented"); RETURN_FALSE; RETURN_FALSE; } /* }}} throwAnotherException */ /* {{{ proto bool throwAnotherException2() */ PHP_METHOD(ExceptionTest, throwAnotherException2) { zend_class_entry * _this_ce; zval * _this_zval = NULL; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &_this_zval, ExceptionTest_ce_ptr) == FAILURE) { return; } _this_ce = Z_OBJCE_P(_this_zval); zend_throw_exception_ex(AnotherException_exception_ce, 0 TSRMLS_CC, "AnotherException was threw"); php_error(E_WARNING, "throwAnotherException2: not yet implemented"); RETURN_FALSE; RETURN_FALSE; } /* }}} throwAnotherException2 */ static zend_function_entry ExceptionTest_methods[] = { PHP_ME(ExceptionTest, throwException, NULL, /**/ZEND_ACC_PUBLIC) PHP_ME(ExceptionTest, throwAnotherException, NULL, /**/ZEND_ACC_PUBLIC) PHP_ME(ExceptionTest, throwAnotherException2, NULL, /**/ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; /* }}} Methods */ static void class_init_ExceptionTest(void) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "ExceptionTest", ExceptionTest_methods); ExceptionTest_ce_ptr = zend_register_internal_class(&ce); } /* }}} Class ExceptionTest */ /* {{{ Class ExceptionTest2 */ static zend_class_entry * ExceptionTest2_ce_ptr = NULL; /* {{{ Methods */ /* {{{ proto bool throwException() */ PHP_METHOD(ExceptionTest2, throwException) { zend_class_entry * _this_ce; zval * _this_zval = NULL; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &_this_zval, ExceptionTest2_ce_ptr) == FAILURE) { return; } _this_ce = Z_OBJCE_P(_this_zval); zend_throw_exception_ex(AnotherException_exception_ce, 0 TSRMLS_CC, "AnotherException was threw"); php_error(E_WARNING, "throwException: not yet implemented"); RETURN_FALSE; RETURN_FALSE; } /* }}} throwException */ /* {{{ proto bool throwAnotherException() */ PHP_METHOD(ExceptionTest2, throwAnotherException) { zend_class_entry * _this_ce; zval * _this_zval = NULL; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &_this_zval, ExceptionTest2_ce_ptr) == FAILURE) { return; } _this_ce = Z_OBJCE_P(_this_zval); zend_throw_exception_ex(AnotherException_exception_ce, 0 TSRMLS_CC, "AnotherException was threw"); php_error(E_WARNING, "throwAnotherException: not yet implemented"); RETURN_FALSE; RETURN_FALSE; } /* }}} throwAnotherException */ static zend_function_entry ExceptionTest2_methods[] = { PHP_ME(ExceptionTest2, throwException, NULL, /**/ZEND_ACC_PUBLIC) PHP_ME(ExceptionTest2, throwAnotherException, NULL, /**/ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; /* }}} Methods */ static void class_init_ExceptionTest2(void) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "ExceptionTest2", ExceptionTest2_methods); ExceptionTest2_ce_ptr = zend_register_internal_class(&ce); } /* }}} Class ExceptionTest2 */ /* }}} Class definitions*/ /* {{{ exception_test_functions[] */ function_entry exception_test_functions[] = { PHP_FE(TestFunction , NULL) { NULL, NULL, NULL } }; /* }}} */ /* {{{ exception_test_module_entry */ zend_module_entry exception_test_module_entry = { STANDARD_MODULE_HEADER, "exception_test", exception_test_functions, PHP_MINIT(exception_test), /* Replace with NULL if there is nothing to do at php startup */ PHP_MSHUTDOWN(exception_test), /* Replace with NULL if there is nothing to do at php shutdown */ PHP_RINIT(exception_test), /* Replace with NULL if there is nothing to do at request start */ PHP_RSHUTDOWN(exception_test), /* Replace with NULL if there is nothing to do at request end */ PHP_MINFO(exception_test), "0.0.1", STANDARD_MODULE_PROPERTIES }; /* }}} */ #ifdef COMPILE_DL_EXCEPTION_TEST ZEND_GET_MODULE(exception_test) #endif /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(exception_test) { class_init_ExceptionTest(); class_init_ExceptionTest2(); zend_class_entry ce; INIT_CLASS_ENTRY(ce, "AnotherException", NULL); AnotherException_exception_ce = zend_register_internal_class_ex(&ce, zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC); INIT_CLASS_ENTRY(ce, "TestFunctionException", NULL); TestFunctionException_exception_ce = zend_register_internal_class_ex(&ce, zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC); /* add your stuff here */ return SUCCESS; } /* }}} */ /* {{{ PHP_MSHUTDOWN_FUNCTION */ PHP_MSHUTDOWN_FUNCTION(exception_test) { /* add your stuff here */ return SUCCESS; } /* }}} */ /* {{{ PHP_RINIT_FUNCTION */ PHP_RINIT_FUNCTION(exception_test) { /* add your stuff here */ return SUCCESS; } /* }}} */ /* {{{ PHP_RSHUTDOWN_FUNCTION */ PHP_RSHUTDOWN_FUNCTION(exception_test) { /* add your stuff here */ return SUCCESS; } /* }}} */ /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(exception_test) { php_info_print_box_start(0); php_printf("<p>The unknown extension</p>\n"); php_printf("<p>Version 0.0.1devel (2007-04-05)</p>\n"); php_info_print_box_end(); /* add your stuff here */ } /* }}} */ /* {{{ proto bool TestFunction() */ PHP_FUNCTION(TestFunction) { if (ZEND_NUM_ARGS()>0) { WRONG_PARAM_COUNT; } zend_throw_exception_ex(TestFunctionException_exception_ce, 0 TSRMLS_CC, "TestFunctionException was threw"); php_error(E_WARNING, "TestFunction: not yet implemented"); RETURN_FALSE; RETURN_FALSE; } /* }}} TestFunction */ #endif /* HAVE_EXCEPTION_TEST */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */