predef_decl = farg;
}
- PSI_ContextValidatePredef(C, &T);
+ PSI_ContextValidateData(PSI_DATA(C), &T);
C->count = 1;
C->data = malloc(sizeof(*C->data));
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);
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;
}
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;
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);
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};
return SUCCESS;
}
-PHP_MSHUTDOWN_FUNCTION(psi)
+static PHP_MSHUTDOWN_FUNCTION(psi)
{
PSI_ContextDtor(&PSI_G(context));
}
#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");
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
};
#include <stddef.h>
#include <stdio.h>
#include <assert.h>
+#include <errno.h>
+#include <string.h>
#include "parser.h"
#include "parser_proc.h"
{
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;
}
--FILE--
===TEST===
<?php
-echo shell_exec("PSI_DUMP=1 ".PHP_BINARY." -r '' > ".__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--
<?php