From 762750b4a3f4e0471993849c4bd12965f6b62356 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 20 Oct 2015 19:08:55 +0200 Subject: [PATCH 1/1] flush --- idl/old/compiler.h | 19 -------- idl/old/lexer.h | 17 ------- idl/old/validator.h | 21 --------- src/context.c | 38 +++++++++++++++- src/context.h | 1 + src/libjit.c | 10 ++++- src/parser.h | 68 +++++++++++++++++++++++++++- src/parser.re | 2 + src/parser_proc.h | 101 +++++++++++++++++++++--------------------- src/parser_proc.y | 29 ++++++++++++ tests/idn/idn.psi | 36 +++++++++++++++ tests/idn/idn001.phpt | 22 +++++++++ tests/idn/idn002.phpt | 23 ++++++++++ 13 files changed, 275 insertions(+), 112 deletions(-) delete mode 100644 idl/old/compiler.h delete mode 100644 idl/old/lexer.h delete mode 100644 idl/old/validator.h create mode 100644 tests/idn/idn.psi create mode 100644 tests/idn/idn001.phpt create mode 100644 tests/idn/idn002.phpt diff --git a/idl/old/compiler.h b/idl/old/compiler.h deleted file mode 100644 index 1dce838..0000000 --- a/idl/old/compiler.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _PSI_COMPILER_H -#define _PSI_COMPILER_H - -#include "types.h" -#include "validator.h" - -typedef struct PSI_Compiler { - decl_typedefs *defs; - decls *decls; - impls *impls; - char *lib; - char *fn; -} PSI_Compiler; - -PSI_Compiler *PSI_CompilerInit(PSI_Compiler *C, PSI_Validator *V); -void PSI_CompilerDtor(PSI_Compiler *C); -void PSI_CompilerFree(PSI_Compiler **C); - -#endif diff --git a/idl/old/lexer.h b/idl/old/lexer.h deleted file mode 100644 index 1e955a7..0000000 --- a/idl/old/lexer.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _PSI_LEXER_H -#define _PSI_LEXER_H - -#include "types.h" - -#define BSIZE 256 - - -PSI_Lexer *PSI_LexerInit(PSI_Lexer *L, const char *filename); -size_t PSI_LexerFill(PSI_Lexer *L, size_t n); -token_t PSI_LexerScan(PSI_Lexer *L); -void PSI_LexerDtor(PSI_Lexer *L); -void PSI_LexerFree(PSI_Lexer **L); - -PSI_Token *PSI_TokenAlloc(PSI_Lexer *L, token_t t); - -#endif diff --git a/idl/old/validator.h b/idl/old/validator.h deleted file mode 100644 index 0b8a279..0000000 --- a/idl/old/validator.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _PSI_VALIDATOR_H -#define _PSI_VALIDATOR_H - -#include "types.h" -#include "lexer.h" - -typedef struct PSI_Validator { - decl_typedefs *defs; - decls *decls; - impls *impls; - char *lib; - char *fn; - void *dlopened; -} PSI_Validator; - -PSI_Validator *PSI_ValidatorInit(PSI_Validator *V, PSI_Lexer *L); -int PSI_ValidatorValidate(PSI_Validator *V); -void PSI_ValidatorDtor(PSI_Validator *V); -void PSI_ValidatorFree(PSI_Validator **V); - -#endif diff --git a/src/context.c b/src/context.c index 825682d..7670462 100644 --- a/src/context.c +++ b/src/context.c @@ -6,6 +6,7 @@ #include "php.h" #include "php_scandir.h" #include "context.h" +#include "parser.h" #include "validator.h" PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErrorFunc error) @@ -39,6 +40,7 @@ void PSI_ContextBuild(PSI_Context *C, const char *path) n = php_scandir(path, &entries, psi_select_dirent, alphasort); if (n < 0) { + return; C->error(PSI_WARNING, "Failed to scan PSI directory '%s'", path); } else for (i = 0; i < n; ++i) { char psi[MAXPATHLEN]; @@ -67,12 +69,39 @@ void PSI_ContextBuild(PSI_Context *C, const char *path) PSI_ParserDtor(&P); if (PSI_ValidatorValidate(&V)) { - zend_function_entry *closures = PSI_ContextCompile(C, (PSI_Data *) &V); + zend_function_entry *closures; + + if (V.consts) { + zend_constant zc; + + zc.flags = CONST_PERSISTENT|CONST_CS; + zc.module_number = EG(current_module)->module_number; + + for (i = 0; i < V.consts->count; ++i) { + constant *c = V.consts->list[i]; + + zc.name = zend_string_init(c->name + (c->name[0] == '\\'), strlen(c->name) - (c->name[0] == '\\'), 1); + ZVAL_NEW_STR(&zc.value, zend_string_init(c->val->text, strlen(c->val->text), 1)); + + switch (c->type->type) { + case PSI_T_BOOL: + convert_to_boolean(&zc.value); + break; + case PSI_T_INT: + convert_to_long(&zc.value); + break; + case PSI_T_FLOAT: + convert_to_double(&zc.value); + break; + } + zend_register_constant(&zc); + } + } + closures = PSI_ContextCompile(C, (PSI_Data *) &V); if (closures && SUCCESS != zend_register_functions(NULL, closures, NULL, MODULE_PERSISTENT)) { C->error(PSI_WARNING, "Failed to register functions!"); } - } PSI_ValidatorDtor(&V); } @@ -109,8 +138,13 @@ void PSI_ContextDtor(PSI_Context *C) for (i = 0; i < C->count; ++i) { PSI_DataDtor(&C->data[i]); + if (C->closures[i]){ + free(C->closures[i]->arg_info); + free(C->closures[i]); + } } free(C->data); + free(C->closures); memset(C, 0, sizeof(*C)); } diff --git a/src/context.h b/src/context.h index 24bdb9c..6e86e44 100644 --- a/src/context.h +++ b/src/context.h @@ -28,6 +28,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); zend_function_entry *PSI_ContextCompile(PSI_Context *C, PSI_Data *D); +zend_constant a; void PSI_ContextDtor(PSI_Context *C); void PSI_ContextFree(PSI_Context **C); diff --git a/src/libjit.c b/src/libjit.c index 5dc011f..5cc8525 100644 --- a/src/libjit.c +++ b/src/libjit.c @@ -109,7 +109,7 @@ static inline PSI_ClosureData *PSI_ClosureDataAlloc(void *context, impl *impl) { static inline impl_val *deref(unsigned level, impl_val *ret_val, decl_arg *darg) { unsigned i; - for (i = level; i < darg->var->pointer_level; ++i) { + for (i = level; i < darg->var->pointer_level; ++i && ret_val->ptr) { ret_val = *(void **)ret_val; } @@ -135,7 +135,12 @@ static void to_string(impl_val *ret_val, decl_arg *func, zval *return_value) { char chr = ret_val->lval; RETVAL_STRINGL(&chr, 1); } else { - RETVAL_STRING(deref(1, ret_val, func)->ptr); + ret_val = deref(1, ret_val, func); + if (ret_val->ptr) { + RETVAL_STRING(ret_val->ptr); + } else { + RETVAL_EMPTY_STRING(); + } } break; case PSI_T_FLOAT: @@ -270,6 +275,7 @@ static void handle_rval(impl *impl, impl_val *ret_val, zval *return_value) { static void handle_set(zval *return_value, set_func *func, decl_vars *vars) { impl_val *val = &vars->vars[0]->arg->let->ptr; + ZVAL_DEREF(return_value); zval_dtor(return_value); switch (func->type) { diff --git a/src/parser.h b/src/parser.h index 0ed55ca..d7393d4 100644 --- a/src/parser.h +++ b/src/parser.h @@ -689,18 +689,81 @@ static void free_impls(impls *impls) { free(impls); } +typedef struct const_type { + token_t type; + char *name; +} const_type; + +static inline const_type *init_const_type(token_t type, const char *name) { + const_type *ct = malloc(sizeof(*ct)); + ct->type = type; + ct->name = strdup(name); + return ct; +} + +static inline void free_const_type(const_type *type) { + free(type->name); + free(type); +} + +typedef struct constant { + const_type *type; + char *name; + impl_def_val *val; +} constant; + +static inline constant *init_constant(const_type *type, char *name, impl_def_val *val) { + constant *c = malloc(sizeof(*c)); + c->type = type; + c->name = strdup(name); + c->val = val; + return c; +} + +static inline void free_constant(constant *constant) { + free_const_type(constant->type); + free(constant->name); + free_impl_def_val(constant->val); + free(constant); +} + +typedef struct constants { + size_t count; + constant **list; +} constants; + +static inline constants *add_constant(constants *constants, constant *constant) { + if (!constants) { + constants = calloc(1, sizeof(*constants)); + } + constants->list = realloc(constants->list, ++constants->count * sizeof(*constants->list)); + constants->list[constants->count-1] = constant; + return constants; +} + +static inline void free_constants(constants *c) { + size_t i; + + for (i = 0; i < c->count; ++i) { + free_constant(c->list[i]); + } + free(c->list); + free(c); +} + #define PSI_ERROR 16 #define PSI_WARNING 32 typedef void (*psi_error_cb)(int type, const char *msg, ...); -typedef struct PSI_Data { #define PSI_DATA_MEMBERS \ + constants *consts; \ decl_typedefs *defs; \ decls *decls; \ impls *impls; \ char *lib; \ char *fn; \ psi_error_cb error +typedef struct PSI_Data { PSI_DATA_MEMBERS; } PSI_Data; @@ -710,6 +773,9 @@ static inline void PSI_DataExchange(PSI_Data *dest, PSI_Data *src) { } static inline void PSI_DataDtor(PSI_Data *data) { + if (data->consts) { + free_constants(data->consts); + } if (data->defs) { free_decl_typedefs(data->defs); } diff --git a/src/parser.re b/src/parser.re index d0daecb..0d13d79 100644 --- a/src/parser.re +++ b/src/parser.re @@ -201,6 +201,7 @@ token_t PSI_ParserScan(PSI_Parser *P) ARRAY = 'array'; FUNCTION = 'function'; TYPEDEF = 'typedef'; + CONST = 'const'; LIB = 'lib'; LET = 'let'; SET = 'set'; @@ -255,6 +256,7 @@ token_t PSI_ParserScan(PSI_Parser *P) ARRAY {RETURN(PSI_T_ARRAY);} FUNCTION {RETURN(PSI_T_FUNCTION);} TYPEDEF {RETURN(PSI_T_TYPEDEF);} + CONST {RETURN(PSI_T_CONST);} LIB {RETURN(PSI_T_LIB);} LET {RETURN(PSI_T_LET);} SET {RETURN(PSI_T_SET);} diff --git a/src/parser_proc.h b/src/parser_proc.h index e5d418a..b025185 100644 --- a/src/parser_proc.h +++ b/src/parser_proc.h @@ -2,53 +2,54 @@ #define PSI_T_LIB 2 #define PSI_T_QUOTED_STRING 3 #define PSI_T_EOS 4 -#define PSI_T_TYPEDEF 5 -#define PSI_T_NAME 6 -#define PSI_T_LPAREN 7 -#define PSI_T_RPAREN 8 -#define PSI_T_COMMA 9 -#define PSI_T_VOID 10 -#define PSI_T_CHAR 11 -#define PSI_T_SHORT 12 -#define PSI_T_INT 13 -#define PSI_T_LONG 14 -#define PSI_T_FLOAT 15 -#define PSI_T_DOUBLE 16 -#define PSI_T_SINT8 17 -#define PSI_T_UINT8 18 -#define PSI_T_SINT16 19 -#define PSI_T_UINT16 20 -#define PSI_T_SINT32 21 -#define PSI_T_UINT32 22 -#define PSI_T_SINT64 23 -#define PSI_T_UINT64 24 -#define PSI_T_LBRACE 25 -#define PSI_T_RBRACE 26 -#define PSI_T_FUNCTION 27 -#define PSI_T_NSNAME 28 -#define PSI_T_COLON 29 -#define PSI_T_REFERENCE 30 -#define PSI_T_NULL 31 -#define PSI_T_NUMBER 32 -#define PSI_T_TRUE 33 -#define PSI_T_FALSE 34 -#define PSI_T_DOLLAR 35 -#define PSI_T_EQUALS 36 -#define PSI_T_LET 37 -#define PSI_T_STRLEN 38 -#define PSI_T_STRVAL 39 -#define PSI_T_INTVAL 40 -#define PSI_T_FLOATVAL 41 -#define PSI_T_BOOLVAL 42 -#define PSI_T_SET 43 -#define PSI_T_TO_STRING 44 -#define PSI_T_TO_INT 45 -#define PSI_T_TO_FLOAT 46 -#define PSI_T_TO_BOOL 47 -#define PSI_T_RETURN 48 -#define PSI_T_FREE 49 -#define PSI_T_MIXED 50 -#define PSI_T_BOOL 51 -#define PSI_T_STRING 52 -#define PSI_T_ARRAY 53 -#define PSI_T_POINTER 54 +#define PSI_T_BOOL 5 +#define PSI_T_INT 6 +#define PSI_T_FLOAT 7 +#define PSI_T_STRING 8 +#define PSI_T_CONST 9 +#define PSI_T_NSNAME 10 +#define PSI_T_EQUALS 11 +#define PSI_T_TYPEDEF 12 +#define PSI_T_NAME 13 +#define PSI_T_LPAREN 14 +#define PSI_T_RPAREN 15 +#define PSI_T_COMMA 16 +#define PSI_T_VOID 17 +#define PSI_T_CHAR 18 +#define PSI_T_SHORT 19 +#define PSI_T_LONG 20 +#define PSI_T_DOUBLE 21 +#define PSI_T_SINT8 22 +#define PSI_T_UINT8 23 +#define PSI_T_SINT16 24 +#define PSI_T_UINT16 25 +#define PSI_T_SINT32 26 +#define PSI_T_UINT32 27 +#define PSI_T_SINT64 28 +#define PSI_T_UINT64 29 +#define PSI_T_LBRACE 30 +#define PSI_T_RBRACE 31 +#define PSI_T_FUNCTION 32 +#define PSI_T_COLON 33 +#define PSI_T_REFERENCE 34 +#define PSI_T_NULL 35 +#define PSI_T_NUMBER 36 +#define PSI_T_TRUE 37 +#define PSI_T_FALSE 38 +#define PSI_T_DOLLAR 39 +#define PSI_T_LET 40 +#define PSI_T_STRLEN 41 +#define PSI_T_STRVAL 42 +#define PSI_T_INTVAL 43 +#define PSI_T_FLOATVAL 44 +#define PSI_T_BOOLVAL 45 +#define PSI_T_SET 46 +#define PSI_T_TO_STRING 47 +#define PSI_T_TO_INT 48 +#define PSI_T_TO_FLOAT 49 +#define PSI_T_TO_BOOL 50 +#define PSI_T_RETURN 51 +#define PSI_T_FREE 52 +#define PSI_T_MIXED 53 +#define PSI_T_ARRAY 54 +#define PSI_T_POINTER 55 diff --git a/src/parser_proc.y b/src/parser_proc.y index 3dc06e2..f7bec63 100644 --- a/src/parser_proc.y +++ b/src/parser_proc.y @@ -42,6 +42,32 @@ block ::= impl(impl). { block ::= decl_typedef(def). { P->defs = add_decl_typedef(P->defs, def); } +block ::= constant(constant). { + P->consts = add_constant(P->consts, constant); +} + +%type const_type {const_type*} +const_type(type_) ::= BOOL(T). { + type_ = init_const_type(T->type, T->text); + free(T); +} +const_type(type_) ::= INT(T). { + type_ = init_const_type(T->type, T->text); + free(T); +} +const_type(type_) ::= FLOAT(T). { + type_ = init_const_type(T->type, T->text); + free(T); +} +const_type(type_) ::= STRING(T). { + type_ = init_const_type(T->type, T->text); + free(T); +} +%type constant {constant*} +constant(constant) ::= CONST const_type(type) NSNAME(T) EQUALS impl_def_val(val) EOS. { + constant = init_constant(type, T->text, val); + free(T); +} %type decl_typedef {decl_typedef*} decl_typedef(def) ::= TYPEDEF NAME(ALIAS) decl_type(type) EOS. { @@ -158,6 +184,7 @@ decl_type(type_) ::= NAME(T). { } %type impl {impl*} +%destructor impl {free_impl($$);} impl(impl) ::= impl_func(func) LBRACE impl_stmts(stmts) RBRACE. { impl = init_impl(func, stmts); } @@ -223,6 +250,7 @@ impl_arg_list(args) ::= impl_arg_list(args_) COMMA impl_arg(arg). { } %type impl_stmts {impl_stmts*} +%destructor impl_stmts {free_impl_stmts($$);} impl_stmts(stmts) ::= impl_stmt(stmt). { stmts = init_impl_stmts(stmt); } @@ -231,6 +259,7 @@ impl_stmts(stmts) ::= impl_stmts(stmts_) impl_stmt(stmt). { } %type impl_stmt {impl_stmt*} +%destructor impl_stmt {free_impl_stmt($$);} impl_stmt(stmt) ::= let_stmt(let). { stmt = init_impl_stmt(PSI_T_LET, let); } diff --git a/tests/idn/idn.psi b/tests/idn/idn.psi new file mode 100644 index 0000000..1583680 --- /dev/null +++ b/tests/idn/idn.psi @@ -0,0 +1,36 @@ +# libidn +lib "idn"; + +# IDNA errors +const int \IDNA_SUCCESS = 0; +const int \IDNA_STRINGPREP_ERROR = 1; +const int \IDNA_PUNYCODE_ERROR = 2; +const int \IDNA_CONTAINS_NON_LDH = 3; +const int \IDNA_CONTAINS_LDH = 3; +const int \IDNA_CONTAINS_MINUS = 4; +const int \IDNA_INVALID_LENGTH = 5; +const int \IDNA_NO_ACE_PREFIX = 6; +const int \IDNA_ROUNDTRIP_VERIFY_ERROR = 7; +const int \IDNA_CONTAINS_ACE_PREFIX = 8; +const int \IDNA_ICONV_ERROR = 9; +const int \IDNA_MALLOC_ERROR = 201; +const int \IDNA_DLOPEN_ERROR = 202; +# IDNA flags +const int \IDNA_ALLOW_UNASSIGNED = 1; +const int \IDNA_USE_STD3_ASCII_RULES = 2; + + +default int idna_to_ascii_8z(sint8 *host, sint8 **buffer, int flags); +function idn\utf8_to_ascii(string $host, string &$result, int $flags = 0) : int { + let buffer = &NULL; + let host = strval($host); + let flags = intval($flags); + set $result = to_string(*buffer); + return to_int(idna_to_ascii_8z); + free *buffer; +} +default sint8 *idna_strerror(int rc); +function idn\strerror(int $rc) : string { + return to_string(idna_strerror); + let rc = intval($rc); +} diff --git a/tests/idn/idn001.phpt b/tests/idn/idn001.phpt new file mode 100644 index 0000000..c5d19c6 --- /dev/null +++ b/tests/idn/idn001.phpt @@ -0,0 +1,22 @@ +--TEST-- +libidn +--INI-- +psi.directory={PWD} +--SKIPIF-- + +--FILE-- +===TEST=== + +===DONE=== +--EXPECT-- +===TEST=== +xn--flte-6qa.de +Success +===DONE=== \ No newline at end of file diff --git a/tests/idn/idn002.phpt b/tests/idn/idn002.phpt new file mode 100644 index 0000000..9f092b1 --- /dev/null +++ b/tests/idn/idn002.phpt @@ -0,0 +1,23 @@ +--TEST-- +libidn +--INI-- +psi.directory={PWD} +--SKIPIF-- + +--FILE-- +===TEST=== + +===DONE=== +--EXPECT-- +===TEST=== + +Non-digit/letter/hyphen in input +===DONE=== \ No newline at end of file -- 2.30.2