From 52815a5aac85e8c69ffba76c25a51de3b6ae1365 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 27 Jan 2016 12:02:52 +0100 Subject: [PATCH] psi_dump() & psi_validate() --- src/context.c | 2 +- src/context.h | 2 +- src/context_validate.c | 65 ++++++++++++++++++++------- src/module.c | 82 +++++++++++++++++++++++++++++++--- src/parser.re | 10 ++--- tests/parser/dump/dump001.phpt | 12 +++-- 6 files changed, 139 insertions(+), 34 deletions(-) diff --git a/src/context.c b/src/context.c index 1887a7c..de72810 100644 --- a/src/context.c +++ b/src/context.c @@ -137,7 +137,7 @@ PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErr predef_decl = farg; } - PSI_ContextValidatePredef(C, &T); + PSI_ContextValidateData(PSI_DATA(C), &T); C->count = 1; C->data = malloc(sizeof(*C->data)); diff --git a/src/context.h b/src/context.h index 386304b..a54e69a 100644 --- a/src/context.h +++ b/src/context.h @@ -29,7 +29,7 @@ struct PSI_Context { PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErrorFunc error); void PSI_ContextBuild(PSI_Context *C, const char *path); int PSI_ContextValidate(PSI_Context *C, PSI_Parser *P); -void PSI_ContextValidatePredef(PSI_Context *C, PSI_Data *D); +int PSI_ContextValidateData(PSI_Data *C, PSI_Data *D); zend_function_entry *PSI_ContextCompile(PSI_Context *C); void PSI_ContextCall(PSI_Context *C, decl_callinfo *decl_call, impl_vararg *va); void PSI_ContextDump(PSI_Context *C, int fd); diff --git a/src/context_validate.c b/src/context_validate.c index da760c6..38e0f84 100644 --- a/src/context_validate.c +++ b/src/context_validate.c @@ -919,39 +919,70 @@ int PSI_ContextValidate(PSI_Context *C, PSI_Parser *P) return 1; } -void PSI_ContextValidatePredef(PSI_Context *C, PSI_Data *D) +int PSI_ContextValidateData(PSI_Data *dest, PSI_Data *source) { size_t i; + int errors = 0; - for (i = 0; i < D->defs->count; ++i) { - decl_typedef *def = D->defs->list[i]; + if (source->defs) for (i = 0; i < source->defs->count; ++i) { + decl_typedef *def = source->defs->list[i]; - if (validate_decl_typedef(D, def)) { - C->defs = add_decl_typedef(C->defs, def); + if (validate_decl_typedef(source, def)) { + if (dest) { + dest->defs = add_decl_typedef(dest->defs, def); + } + } else { + ++errors; } } - for (i = 0; i < D->consts->count; ++i) { - constant *constant = D->consts->list[i]; + if (source->consts) for (i = 0; i < source->consts->count; ++i) { + constant *constant = source->consts->list[i]; - if (validate_constant(D, constant)) { - C->consts = add_constant(C->consts, constant); + if (validate_constant(source, constant)) { + if (dest) { + dest->consts = add_constant(dest->consts, constant); + } + } else { + ++errors; } } - for (i = 0; i < D->structs->count; ++i) { - decl_struct *dstruct = D->structs->list[i]; + if (source->structs) for (i = 0; i < source->structs->count; ++i) { + decl_struct *dstruct = source->structs->list[i]; - if (validate_decl_struct(D, dstruct)) { - C->structs = add_decl_struct(C->structs, dstruct); + if (validate_decl_struct(source, dstruct)) { + if (dest) { + dest->structs = add_decl_struct(dest->structs, dstruct); + } + } else { + ++errors; } } - for (i = 0; i < D->decls->count; ++i) { - decl *decl = D->decls->list[i]; + if (source->decls) for (i = 0; i < source->decls->count; ++i) { + decl *decl = source->decls->list[i]; - if (validate_decl(D, NULL, decl)) { - C->decls = add_decl(C->decls, decl); + if (validate_decl(source, NULL, decl)) { + if (dest) { + dest->decls = add_decl(dest->decls, decl); + } + } else { + ++errors; } } + + if (source->impls) for (i = 0; i < source->impls->count; ++i) { + impl *impl = source->impls->list[i]; + + if (validate_impl(source, impl)) { + if (dest) { + dest->impls = add_impl(dest->impls, impl); + } + } else { + ++errors; + } + } + + return errors; } diff --git a/src/module.c b/src/module.c index 1fe5bf3..c3728a7 100644 --- a/src/module.c +++ b/src/module.c @@ -40,11 +40,25 @@ zend_class_entry *psi_object_get_class_entry() void psi_error_wrapper(PSI_Token *t, int type, const char *msg, ...) { va_list argv; + const char *fn = NULL; + unsigned ln = 0; + + if (t) { + fn = t->file; + ln = t->line; + } else if (zend_is_executing()) { + fn = zend_get_executed_filename(); + ln = zend_get_executed_lineno(); + } else if (zend_is_compiling()) { + fn = zend_get_compiled_filename(); + ln = zend_get_compiled_lineno(); + } va_start(argv, msg); - psi_verror(type, t?t->file:"Unknown", t?t->line:0, msg, argv); + psi_verror(type, fn, ln, msg, argv); va_end(argv); } + void psi_error(int type, const char *fn, unsigned ln, const char *msg, ...) { va_list argv; @@ -53,6 +67,7 @@ void psi_error(int type, const char *fn, unsigned ln, const char *msg, ...) psi_verror(type, fn, ln, msg, argv); va_end(argv); } + void psi_verror(int type, const char *fn, unsigned ln, const char *msg, va_list argv) { zend_error_cb(type, fn, ln, msg, argv); @@ -80,7 +95,59 @@ static zend_object *psi_object_init(zend_class_entry *ce) return &o->std; } -PHP_MINIT_FUNCTION(psi) +ZEND_BEGIN_ARG_INFO_EX(ai_psi_dump, 0, 0, 0) + ZEND_ARG_INFO(0, stream) +ZEND_END_ARG_INFO(); +static PHP_FUNCTION(psi_dump) { + php_stream *s; + zval *r = NULL; + int fd = STDOUT_FILENO; + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "|r!", &r)) { + return; + } + if (r) { + php_stream_from_zval(s, r); + + if (SUCCESS != php_stream_cast(s, PHP_STREAM_AS_FD | PHP_STREAM_CAST_INTERNAL, (void **)&fd, 1)) { + RETURN_FALSE; + } + } + PSI_ContextDump(&PSI_G(context), fd); +} + +ZEND_BEGIN_ARG_INFO_EX(ai_psi_validate, 0, 0, 1) + ZEND_ARG_INFO(0, file) +ZEND_END_ARG_INFO(); +static PHP_FUNCTION(psi_validate) { + zend_string *file; + PSI_Parser P; + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "P", &file)) { + return; + } + + if (!PSI_ParserInit(&P, file->val, psi_error_wrapper, 0)) { + RETURN_FALSE; + } + + while (0 < PSI_ParserScan(&P)) { + PSI_ParserParse(&P, PSI_TokenAlloc(&P)); + if (P.num == PSI_T_EOF) { + break; + } + } + PSI_ParserParse(&P, NULL); + + if (0 == PSI_ContextValidateData(NULL, PSI_DATA(&P)) && !P.errors) { + RETVAL_TRUE; + } else { + RETVAL_FALSE; + } + PSI_ParserDtor(&P); +} + +static PHP_MINIT_FUNCTION(psi) { PSI_ContextOps *ops = NULL; zend_class_entry ce = {0}; @@ -120,7 +187,7 @@ PHP_MINIT_FUNCTION(psi) return SUCCESS; } -PHP_MSHUTDOWN_FUNCTION(psi) +static PHP_MSHUTDOWN_FUNCTION(psi) { PSI_ContextDtor(&PSI_G(context)); @@ -130,14 +197,14 @@ PHP_MSHUTDOWN_FUNCTION(psi) } #if defined(COMPILE_DL_PSI) && defined(ZTS) -PHP_RINIT_FUNCTION(psi) +static PHP_RINIT_FUNCTION(psi) { ZEND_TSRMLS_CACHE_UPDATE(); return SUCCESS; } #endif -PHP_MINFO_FUNCTION(psi) +static PHP_MINFO_FUNCTION(psi) { php_info_print_table_start(); php_info_print_table_header(2, "psi support", "enabled"); @@ -145,7 +212,10 @@ PHP_MINFO_FUNCTION(psi) DISPLAY_INI_ENTRIES(); } -const zend_function_entry psi_functions[] = { + +static const zend_function_entry psi_functions[] = { + PHP_FE(psi_dump, ai_psi_dump) + PHP_FE(psi_validate, ai_psi_validate) PHP_FE_END }; diff --git a/src/parser.re b/src/parser.re index 0922ba1..7ab169e 100644 --- a/src/parser.re +++ b/src/parser.re @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include "parser.h" #include "parser_proc.h" @@ -14,15 +16,11 @@ PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, psi_error_cb err { FILE *fp; - if (!P) { - P = malloc(sizeof(*P)); - } - memset(P, 0, sizeof(*P)); - fp = fopen(filename, "r"); if (!fp) { - perror(filename); + error(NULL, PSI_WARNING, "Could not open '%s' for reading: %s", + filename, strerror(errno)); return NULL; } diff --git a/tests/parser/dump/dump001.phpt b/tests/parser/dump/dump001.phpt index 68f23c2..da8589c 100644 --- a/tests/parser/dump/dump001.phpt +++ b/tests/parser/dump/dump001.phpt @@ -7,14 +7,20 @@ extension_loaded("psi") or die("skip - need ext/psi"); --FILE-- ===TEST=== ".__DIR__."/dump.psi"); -var_dump(file_exists(__DIR__."/dump.psi")); -echo shell_exec(PHP_BINARY." -d psi.directory=".__DIR__." -r ''"); +$fn = __DIR__."/dump.psi"; +$fd = fopen($fn, "w"); +psi_dump($fd); +fclose($fd); + +var_dump(file_exists($fn)); +var_dump(psi_validate($fn)); + ?> ===DONE=== --EXPECT-- ===TEST=== bool(true) +bool(true) ===DONE=== --CLEAN--