From e16c15d5936c3b57b05e49570fb9526920de8188 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Mon, 28 Dec 2015 17:28:38 +0100 Subject: [PATCH 01/16] flush --- Makefile.frag | 2 +- php_psi.h | 1 - psi.d/stdio.psi | 6 ++++ src/context.c | 51 ++++++++++++++++---------- src/module.c | 33 ++++++++++++++--- src/parser.h | 43 ++++++++++++++++------ src/parser.re | 91 +++++++++++++++++++++++++++++++++++++++++++++-- src/parser_proc.h | 67 +++++++++++++++++----------------- src/parser_proc.y | 46 ++++++++++++++++++------ 9 files changed, 260 insertions(+), 80 deletions(-) diff --git a/Makefile.frag b/Makefile.frag index c6ce97d..1917557 100644 --- a/Makefile.frag +++ b/Makefile.frag @@ -26,7 +26,7 @@ lemon.c: $(CC) -o $@ $< $(PHP_PSI_SRCDIR)/src/parser_proc.h: $(PHP_PSI_SRCDIR)/src/parser_proc.y - + $(PHP_PSI_SRCDIR)/src/%.c: $(PHP_PSI_SRCDIR)/src/parser.h $(PHP_PSI_SRCDIR)/src/parser_proc.h touch $@ $(PHP_PSI_SRCDIR)/src/parser_proc.y: $(PHP_PSI_SRCDIR)/src/parser.h diff --git a/php_psi.h b/php_psi.h index 367739a..f5859e3 100644 --- a/php_psi.h +++ b/php_psi.h @@ -18,7 +18,6 @@ extern zend_module_entry psi_module_entry; #include "TSRM.h" #endif -#include "parser.h" #include "context.h" void psi_error(int type, const char *msg, ...); diff --git a/psi.d/stdio.psi b/psi.d/stdio.psi index 3e54ac4..1e136ce 100644 --- a/psi.d/stdio.psi +++ b/psi.d/stdio.psi @@ -64,3 +64,9 @@ function psi\rewind(object $stream) : void { let stream = objval($stream); return void(rewind); } + +extern int printf(const char *fmt, ...); +function psi\printf(string $fmt, mixed ...$args) : int { + let fmt = strval($fmt); + return to_int(printf); +} diff --git a/src/context.c b/src/context.c index 5b08426..ba9fabb 100644 --- a/src/context.c +++ b/src/context.c @@ -105,8 +105,6 @@ #include "php.h" #include "php_scandir.h" #include "php_psi.h" -#include "context.h" -#include "parser.h" #include "libjit.h" #include "libffi.h" @@ -294,8 +292,10 @@ static inline int validate_constant(PSI_Data *data, constant *c) { static inline int validate_decl_arg(PSI_Data *data, decl_arg *arg) { if (!validate_decl_type(data, arg->type)) { - data->error(PSI_WARNING, "Cannot use '%s'(%d) as type for '%s'", - arg->type->name, arg->type->type, arg->var->name); + data->error(PSI_WARNING, "Cannot use '%s'(%d) as type for decl var '%s'" + " in %s on line %zu at col %zu", + arg->type->name, arg->type->type, arg->var->name, + arg->type->token->file, arg->type->token->line, arg->type->token->col); return 0; } return 1; @@ -1371,11 +1371,16 @@ void PSI_ContextDump(PSI_Context *C, int fd) dprintf(fd, "%s ", decl->abi->convention); dump_decl_arg(fd, decl->func); dprintf(fd, "("); - if (decl->args) for (j = 0; j < decl->args->count; ++j) { - if (j) { - dprintf(fd, ", "); + if (decl->args) { + for (j = 0; j < decl->args->count; ++j) { + if (j) { + dprintf(fd, ", "); + } + dump_decl_arg(fd, decl->args->args[j]); + } + if (decl->args->varargs) { + dprintf(fd, ", ..."); } - dump_decl_arg(fd, decl->args->args[j]); } dprintf(fd, ");\n"); } @@ -1386,16 +1391,26 @@ void PSI_ContextDump(PSI_Context *C, int fd) impl *impl = C->impls->list[i]; dprintf(fd, "function %s(", impl->func->name); - if (impl->func->args) for (j = 0; j < impl->func->args->count; ++j) { - impl_arg *iarg = impl->func->args->args[j]; - - dprintf(fd, "%s%s %s$%s", - j ? ", " : "", - iarg->type->name, - iarg->var->reference ? "&" : "", - iarg->var->name); - if (iarg->def) { - dprintf(fd, " = %s", iarg->def->text); + if (impl->func->args) { + for (j = 0; j < impl->func->args->count; ++j) { + impl_arg *iarg = impl->func->args->args[j]; + + dprintf(fd, "%s%s %s$%s", + j ? ", " : "", + iarg->type->name, + iarg->var->reference ? "&" : "", + iarg->var->name); + if (iarg->def) { + dprintf(fd, " = %s", iarg->def->text); + } + } + if (impl->func->args->vararg) { + impl_arg *vararg = impl->func->args->vararg; + + dprintf(fd, ", %s %s...$%s", + vararg->type->name, + vararg->var->reference ? "&" : "", + vararg->var->name); } } dprintf(fd, ") : %s%s {\n", diff --git a/src/module.c b/src/module.c index bde40a4..c820f4f 100644 --- a/src/module.c +++ b/src/module.c @@ -11,8 +11,6 @@ #include "zend_operators.h" #include "php_psi.h" -#include "parser.h" -#include "context.h" #if HAVE_LIBJIT # include "libjit.h" @@ -124,13 +122,26 @@ zend_internal_arg_info *psi_internal_arginfo(impl *impl) zend_internal_arg_info *aip; zend_internal_function_info *fi; - aip = calloc(impl->func->args->count + 1, sizeof(*aip)); + aip = calloc(impl->func->args->count + 1 + !!impl->func->args->vararg, sizeof(*aip)); fi = (zend_internal_function_info *) &aip[0]; + fi->allow_null = 1; fi->required_num_args = psi_num_min_args(impl); fi->return_reference = impl->func->return_reference; fi->type_hint = psi_internal_type(impl->func->return_type); + if (impl->func->args->vararg) { + impl_arg *vararg = impl->func->args->vararg; + zend_internal_arg_info *ai = &aip[impl->func->args->count]; + + ai->name = vararg->var->name; + ai->type_hint = psi_internal_type(vararg->type); + if (vararg->var->reference) { + ai->pass_by_reference = 1; + } + ai->is_variadic = 1; + } + for (i = 0; i < impl->func->args->count; ++i) { impl_arg *iarg = impl->func->args->args[i]; zend_internal_arg_info *ai = &aip[i+1]; @@ -479,7 +490,7 @@ static inline ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, i return rv; } - ZEND_PARSE_PARAMETERS_START(psi_num_min_args(impl), impl->func->args->count) + ZEND_PARSE_PARAMETERS_START(psi_num_min_args(impl), impl->func->args->vararg ? -1 : impl->func->args->count) nextarg: iarg = impl->func->args->args[_i]; if (iarg->def) { @@ -504,6 +515,20 @@ static inline ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, i error_code = ZPP_ERROR_FAILURE; break; } + if (impl->func->args->vararg) { + iarg = impl->func->args->vararg; + + if (_i == impl->func->args->count) { + zval *ptr = iarg->_zv = calloc(_num_args - _i + 1, sizeof(zval)); + + _optional = 1; + while (_i < _num_args) { + Z_PARAM_PROLOGUE(0); + ZVAL_COPY_VALUE(ptr++, _arg); + } + break; + } + } if (_i < _num_args) { goto nextarg; } diff --git a/src/parser.h b/src/parser.h index 660b355..55f4f9d 100644 --- a/src/parser.h +++ b/src/parser.h @@ -21,9 +21,9 @@ size_t psi_t_size(token_t); typedef struct PSI_Token { token_t type; - unsigned line; - size_t size; - char text[1]; + size_t size, line, col; + char *text, *file; + char buf[1]; } PSI_Token; typedef union impl_val { @@ -51,6 +51,7 @@ typedef union impl_val { } impl_val; typedef struct decl_type { + PSI_Token *token; char *name; token_t type; struct decl_type *real; @@ -217,6 +218,7 @@ static inline void free_decl_vars(decl_vars *vars) { typedef struct decl_args { decl_arg **args; size_t count; + unsigned varargs:1; } decl_args; static inline decl_args *init_decl_args(decl_arg *arg) { @@ -500,6 +502,7 @@ static inline void free_impl_arg(impl_arg *arg) { typedef struct impl_args { impl_arg **args; size_t count; + impl_arg *vararg; } impl_args; static inline impl_args *init_impl_args(impl_arg *arg) { @@ -1166,38 +1169,58 @@ typedef struct PSI_Parser { unsigned flags; unsigned errors; void *proc; - size_t line; + size_t line, col; token_t num; char *cur, *tok, *lim, *eof, *ctx, *mrk, buf[BSIZE]; } PSI_Parser; static inline PSI_Token *PSI_TokenAlloc(PSI_Parser *P) { PSI_Token *T; - size_t token_len; + size_t token_len, fname_len; + token_t token_typ; if (P->cur < P->tok) { return NULL; } + token_typ = P->num; token_len = P->cur - P->tok; + fname_len = strlen(P->psi.file.fn); - T = calloc(1, sizeof(*T) + token_len); - T->type = P->num; - T->line = P->line; + T = calloc(1, sizeof(*T) + token_len + fname_len + 1); + T->type = token_typ; T->size = token_len; - T->text[token_len] = 0; + T->line = P->line; + T->col = P->col; + T->file = &T->buf[0]; + T->text = &T->buf[fname_len + 1]; + + memcpy(T->file, P->psi.file.fn, fname_len); memcpy(T->text, P->tok, token_len); return T; } +static inline PSI_Token *PSI_TokenCopy(PSI_Token *src) { + size_t fname_len = strlen(src->file); + size_t strct_len = sizeof(*src) + src->size + fname_len + 1; + PSI_Token *ptr = malloc(strct_len); + + memcpy(ptr, src, strct_len); + + ptr->file = &ptr->buf[0]; + ptr->text = &ptr->buf[fname_len + 1]; + + return ptr; +} + #define PSI_PARSER_DEBUG 0x1 PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, psi_error_cb error, unsigned flags); void PSI_ParserSyntaxError(PSI_Parser *P, const char *fn, size_t ln, const char *msg, ...); size_t PSI_ParserFill(PSI_Parser *P, size_t n); token_t PSI_ParserScan(PSI_Parser *P); -void PSI_ParserParse(PSI_Parser *P, PSI_Token *T); +void PSI_ParserParse(PSI_Parser *P, PSI_Token *src); void PSI_ParserDtor(PSI_Parser *P); void PSI_ParserFree(PSI_Parser **P); diff --git a/src/parser.re b/src/parser.re index affe901..69e76c8 100644 --- a/src/parser.re +++ b/src/parser.re @@ -32,6 +32,7 @@ PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, psi_error_cb err P->psi.file.fn = strdup(filename); P->fp = fp; + P->col = 1; P->line = 1; P->error = error; P->flags = flags; @@ -139,17 +140,100 @@ void PSI_ParserFree(PSI_Parser **P) # error BSIZE must be greater than YYMAXFILL #endif +#define PSI_T(n) \ +(n) == PSI_T_NAME ? "NAME" : \ +(n) == PSI_T_PLUS ? "PLUS" : \ +(n) == PSI_T_MINUS ? "MINUS" : \ +(n) == PSI_T_SLASH ? "SLASH" : \ +(n) == PSI_T_ASTERISK ? "ASTERISK" : \ +(n) == PSI_T_TEMP ? "TEMP" : \ +(n) == PSI_T_FREE ? "FREE" : \ +(n) == PSI_T_SET ? "SET" : \ +(n) == PSI_T_LET ? "LET" : \ +(n) == PSI_T_RETURN ? "RETURN" : \ +(n) == PSI_T_LIB ? "LIB" : \ +(n) == PSI_T_INT ? "INT" : \ +(n) == PSI_T_UNSIGNED ? "UNSIGNED" : \ +(n) == PSI_T_EOF ? "EOF" : \ +(n) == PSI_T_QUOTED_STRING ? "QUOTED_STRING" : \ +(n) == PSI_T_EOS ? "EOS" : \ +(n) == PSI_T_STRUCT ? "STRUCT" : \ +(n) == PSI_T_LBRACE ? "LBRACE" : \ +(n) == PSI_T_RBRACE ? "RBRACE" : \ +(n) == PSI_T_COLON ? "COLON" : \ +(n) == PSI_T_LPAREN ? "LPAREN" : \ +(n) == PSI_T_NUMBER ? "NUMBER" : \ +(n) == PSI_T_RPAREN ? "RPAREN" : \ +(n) == PSI_T_BOOL ? "BOOL" : \ +(n) == PSI_T_FLOAT ? "FLOAT" : \ +(n) == PSI_T_STRING ? "STRING" : \ +(n) == PSI_T_CONST ? "CONST" : \ +(n) == PSI_T_NSNAME ? "NSNAME" : \ +(n) == PSI_T_EQUALS ? "EQUALS" : \ +(n) == PSI_T_TYPEDEF ? "TYPEDEF" : \ +(n) == PSI_T_VOID ? "VOID" : \ +(n) == PSI_T_LBRACKET ? "LBRACKET" : \ +(n) == PSI_T_RBRACKET ? "RBRACKET" : \ +(n) == PSI_T_COMMA ? "COMMA" : \ +(n) == PSI_T_ELLIPSIS ? "ELLIPSIS" : \ +(n) == PSI_T_DOUBLE ? "DOUBLE" : \ +(n) == PSI_T_INT8 ? "INT8" : \ +(n) == PSI_T_UINT8 ? "UINT8" : \ +(n) == PSI_T_INT16 ? "INT16" : \ +(n) == PSI_T_UINT16 ? "UINT16" : \ +(n) == PSI_T_INT32 ? "INT32" : \ +(n) == PSI_T_UINT32 ? "UINT32" : \ +(n) == PSI_T_INT64 ? "INT64" : \ +(n) == PSI_T_UINT64 ? "UINT64" : \ +(n) == PSI_T_FUNCTION ? "FUNCTION" : \ +(n) == PSI_T_NULL ? "NULL" : \ +(n) == PSI_T_TRUE ? "TRUE" : \ +(n) == PSI_T_FALSE ? "FALSE" : \ +(n) == PSI_T_DOLLAR ? "DOLLAR" : \ +(n) == PSI_T_CALLOC ? "CALLOC" : \ +(n) == PSI_T_OBJVAL ? "OBJVAL" : \ +(n) == PSI_T_ARRVAL ? "ARRVAL" : \ +(n) == PSI_T_PATHVAL ? "PATHVAL" : \ +(n) == PSI_T_STRLEN ? "STRLEN" : \ +(n) == PSI_T_STRVAL ? "STRVAL" : \ +(n) == PSI_T_FLOATVAL ? "FLOATVAL" : \ +(n) == PSI_T_INTVAL ? "INTVAL" : \ +(n) == PSI_T_BOOLVAL ? "BOOLVAL" : \ +(n) == PSI_T_TO_OBJECT ? "TO_OBJECT" : \ +(n) == PSI_T_TO_ARRAY ? "TO_ARRAY" : \ +(n) == PSI_T_TO_STRING ? "TO_STRING" : \ +(n) == PSI_T_TO_INT ? "TO_INT" : \ +(n) == PSI_T_TO_FLOAT ? "TO_FLOAT" : \ +(n) == PSI_T_TO_BOOL ? "TO_BOOL" : \ +(n) == PSI_T_MIXED ? "MIXED" : \ +(n) == PSI_T_ARRAY ? "ARRAY" : \ +(n) == PSI_T_OBJECT ? "OBJECT" : \ +(n) == PSI_T_AMPERSAND ? "AMPERSAND" : \ + + #define RETURN(t) do { \ P->num = t; \ if (P->flags & PSI_PARSER_DEBUG) { \ - fprintf(stderr, "PSI> TOKEN: %d %.*s (EOF=%d)\n", P->num, (int) (P->cur-P->tok), P->tok, P->num == PSI_T_EOF); \ + fprintf(stderr, "PSI> TOKEN: %d %.*s (EOF=%d %s:%zu:%zu)\n", \ + P->num, (int) (P->cur-P->tok), P->tok, P->num == PSI_T_EOF, \ + P->psi.file.fn, P->line, P->col); \ } \ return t; \ } while(1) +#define ADDCOLS \ + P->col += P->cur - P->tok + +#define NEWLINE \ + P->col = 1; \ + ++P->line; \ + goto nextline + token_t PSI_ParserScan(PSI_Parser *P) { for (;;) { + ADDCOLS; + nextline: P->tok = P->cur; /*!re2c re2c:indent:top = 2; @@ -167,7 +251,7 @@ token_t PSI_ParserScan(PSI_Parser *P) QUOTED_STRING = "\"" ([^\"])+ "\""; NUMBER = [+-]? [0-9]* "."? [0-9]+ ([eE] [+-]? [0-9]+)?; - ("#"|"//") .* "\n" { ++P->line; continue;} + ("#"|"//") .* "\n" { NEWLINE; } "(" {RETURN(PSI_T_LPAREN);} ")" {RETURN(PSI_T_RPAREN);} ";" {RETURN(PSI_T_EOS);} @@ -184,7 +268,8 @@ token_t PSI_ParserScan(PSI_Parser *P) "+" {RETURN(PSI_T_PLUS);} "-" {RETURN(PSI_T_MINUS);} "/" {RETURN(PSI_T_SLASH);} - [\r\n] { ++P->line; continue; } + "..." {RETURN(PSI_T_ELLIPSIS);} + [\r\n] { NEWLINE; } [\t ]+ { continue; } 'TRUE' {RETURN(PSI_T_TRUE);} 'FALSE' {RETURN(PSI_T_FALSE);} diff --git a/src/parser_proc.h b/src/parser_proc.h index 0ca3c48..30ad543 100644 --- a/src/parser_proc.h +++ b/src/parser_proc.h @@ -32,36 +32,37 @@ #define PSI_T_LBRACKET 32 #define PSI_T_RBRACKET 33 #define PSI_T_COMMA 34 -#define PSI_T_DOUBLE 35 -#define PSI_T_INT8 36 -#define PSI_T_UINT8 37 -#define PSI_T_INT16 38 -#define PSI_T_UINT16 39 -#define PSI_T_INT32 40 -#define PSI_T_UINT32 41 -#define PSI_T_INT64 42 -#define PSI_T_UINT64 43 -#define PSI_T_FUNCTION 44 -#define PSI_T_NULL 45 -#define PSI_T_TRUE 46 -#define PSI_T_FALSE 47 -#define PSI_T_DOLLAR 48 -#define PSI_T_CALLOC 49 -#define PSI_T_OBJVAL 50 -#define PSI_T_ARRVAL 51 -#define PSI_T_PATHVAL 52 -#define PSI_T_STRLEN 53 -#define PSI_T_STRVAL 54 -#define PSI_T_FLOATVAL 55 -#define PSI_T_INTVAL 56 -#define PSI_T_BOOLVAL 57 -#define PSI_T_TO_OBJECT 58 -#define PSI_T_TO_ARRAY 59 -#define PSI_T_TO_STRING 60 -#define PSI_T_TO_INT 61 -#define PSI_T_TO_FLOAT 62 -#define PSI_T_TO_BOOL 63 -#define PSI_T_MIXED 64 -#define PSI_T_ARRAY 65 -#define PSI_T_OBJECT 66 -#define PSI_T_AMPERSAND 67 +#define PSI_T_ELLIPSIS 35 +#define PSI_T_DOUBLE 36 +#define PSI_T_INT8 37 +#define PSI_T_UINT8 38 +#define PSI_T_INT16 39 +#define PSI_T_UINT16 40 +#define PSI_T_INT32 41 +#define PSI_T_UINT32 42 +#define PSI_T_INT64 43 +#define PSI_T_UINT64 44 +#define PSI_T_FUNCTION 45 +#define PSI_T_NULL 46 +#define PSI_T_TRUE 47 +#define PSI_T_FALSE 48 +#define PSI_T_DOLLAR 49 +#define PSI_T_CALLOC 50 +#define PSI_T_OBJVAL 51 +#define PSI_T_ARRVAL 52 +#define PSI_T_PATHVAL 53 +#define PSI_T_STRLEN 54 +#define PSI_T_STRVAL 55 +#define PSI_T_FLOATVAL 56 +#define PSI_T_INTVAL 57 +#define PSI_T_BOOLVAL 58 +#define PSI_T_TO_OBJECT 59 +#define PSI_T_TO_ARRAY 60 +#define PSI_T_TO_STRING 61 +#define PSI_T_TO_INT 62 +#define PSI_T_TO_FLOAT 63 +#define PSI_T_TO_BOOL 64 +#define PSI_T_MIXED 65 +#define PSI_T_ARRAY 66 +#define PSI_T_OBJECT 67 +#define PSI_T_AMPERSAND 68 diff --git a/src/parser_proc.y b/src/parser_proc.y index 94cdf58..7f38f17 100644 --- a/src/parser_proc.y +++ b/src/parser_proc.y @@ -103,25 +103,29 @@ decl_typedef(def) ::= TYPEDEF decl_type(type) NAME(ALIAS) EOS. { /* support opaque types */ decl_typedef(def) ::= TYPEDEF VOID(V) NAME(ALIAS) EOS. { def = init_decl_typedef(ALIAS->text, init_decl_type(V->type, V->text)); - free(V); + def->type->token = V; + //free(V); free(ALIAS); } decl_typedef(def) ::= TYPEDEF STRUCT(S) NAME(N) NAME(ALIAS) EOS. { def = init_decl_typedef(ALIAS->text, init_decl_type(S->type, N->text)); + def->type->token = N; free(ALIAS); free(S); - free(N); + //free(N); } decl_typedef(def) ::= TYPEDEF decl_struct(s) NAME(ALIAS) EOS. { def = init_decl_typedef(ALIAS->text, init_decl_type(PSI_T_STRUCT, s->name)); + def->type->token = ALIAS; def->type->strct = s; - free(ALIAS); + //free(ALIAS); } %type decl {decl*} %destructor decl {free_decl($$);} decl(decl) ::= decl_abi(abi) decl_func(func) LPAREN decl_args(args) RPAREN EOS. { decl = init_decl(abi, func, args); + } %type decl_func {decl_arg*} @@ -135,7 +139,8 @@ decl_func(func) ::= VOID(T) NAME(N). { init_decl_type(T->type, T->text), init_decl_var(N->text, 0, 0) ); - free(T); + func->type->token = T; + //free(T); free(N); } @@ -178,7 +183,8 @@ decl_arg(arg_) ::= VOID(T) pointers(p) NAME(N). { init_decl_type(T->type, T->text), init_decl_var(N->text, p, 0) ); - free(T); + arg_->type->token = T; + //free(T); free(N); } decl_arg(arg_) ::= CONST VOID(T) pointers(p) NAME(N). { @@ -186,7 +192,8 @@ decl_arg(arg_) ::= CONST VOID(T) pointers(p) NAME(N). { init_decl_type(T->type, T->text), init_decl_var(N->text, p, 0) ); - free(T); + arg_->type->token = T; + //free(T); free(N); } @@ -200,6 +207,10 @@ decl_args(args) ::= decl_arg(arg). { decl_args(args) ::= decl_args(args_) COMMA decl_arg(arg). { args = add_decl_arg(args_, arg); } +decl_args(args) ::= decl_args(args_) COMMA ELLIPSIS. { + args = args_; + args->varargs = 1; +} %type struct_args {decl_args*} %destructor struct_args {free_decl_args($$);} struct_args(args) ::= struct_arg(arg). { @@ -231,28 +242,32 @@ struct_layout(layout) ::= COLON COLON LPAREN NUMBER(POS) COMMA NUMBER(SIZ) RPARE %destructor decl_type {free_decl_type($$);} decl_type(type_) ::= decl_type_token(T). { type_ = init_decl_type(T->type, T->text); - free(T); + type_->token = T; + //free(T); } /* unsigned, urgh */ decl_type(type_) ::= UNSIGNED NAME(T). { type_ = init_decl_type(T->type, T->text); + type_->token = T; type_->name = realloc(type_->name, T->size + sizeof("unsigned")); memmove(type_->name + sizeof("unsigned"), type_->name, T->size); memcpy(type_->name, "unsigned", sizeof("unsigned")-1); type_->name[sizeof("unsigned")] = ' '; type_->name[T->size + sizeof("unsigned")] = 0; - free(T); + //free(T); } /* we have to support plain int here because we have it in our lexer rules */ decl_type(type_) ::= INT(T). { type_ = init_decl_type(PSI_T_NAME, T->text); - free(T); + type_->token = T; + //free(T); } /* structs ! */ decl_type(type_) ::= STRUCT(S) NAME(T). { type_ = init_decl_type(S->type, T->text); + type_->token = T; free(S); - free(T); + //free(T); } %type const_decl_type {decl_type*} @@ -309,6 +324,17 @@ impl_args(args) ::= LPAREN RPAREN. { impl_args(args) ::= LPAREN impl_arg_list(args_) RPAREN. { args = args_; } +impl_args(args) ::= LPAREN impl_arg_list(args_) COMMA impl_vararg(va) RPAREN. { + args = args_; + args->vararg = va; +} + +%type impl_vararg {impl_arg*} +%destructor impl_vararg {free_impl_arg($$);} +impl_vararg(va) ::= impl_type(type) reference(r) ELLIPSIS DOLLAR NAME(T). { + va = init_impl_arg(type, init_impl_var(T->text, r), NULL); +} + %type impl_arg_list {impl_args*} %destructor impl_arg_list {free_impl_args($$);} impl_arg_list(args) ::= impl_arg(arg). { -- 2.30.2 From 43f9e142088705cc003bb021a32ecd4d4d3b3d2b Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Fri, 1 Jan 2016 19:02:21 +0100 Subject: [PATCH 02/16] prepare varargs calls --- src/context.c | 4 ++-- src/context.h | 4 ++-- src/libffi.c | 8 +++++--- src/libjit.c | 10 ++++++---- src/module.c | 5 ++--- src/parser.h | 14 +++++++++----- 6 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/context.c b/src/context.c index ba9fabb..ba58720 100644 --- a/src/context.c +++ b/src/context.c @@ -1214,9 +1214,9 @@ zend_function_entry *PSI_ContextCompile(PSI_Context *C) } -void PSI_ContextCall(PSI_Context *C, impl_val *ret_val, decl *decl) +void PSI_ContextCall(PSI_Context *C, decl_callinfo *decl_call) { - C->ops->call(C, ret_val, decl); + C->ops->call(C, decl_call); } static inline void dump_decl_type(int fd, decl_type *t) { diff --git a/src/context.h b/src/context.h index e68eddf..6611a4a 100644 --- a/src/context.h +++ b/src/context.h @@ -14,7 +14,7 @@ struct PSI_ContextOps { void (*init)(PSI_Context *C); void (*dtor)(PSI_Context *C); zend_function_entry *(*compile)(PSI_Context *C); - void (*call)(PSI_Context *C, impl_val *ret_val, decl *decl); + void (*call)(PSI_Context *C, decl *decl); }; struct PSI_Context { @@ -30,7 +30,7 @@ PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErr void PSI_ContextBuild(PSI_Context *C, const char *path); int PSI_ContextValidate(PSI_Context *C, PSI_Parser *P); zend_function_entry *PSI_ContextCompile(PSI_Context *C); -void PSI_ContextCall(PSI_Context *C, impl_val *ret_val, decl *decl); +void PSI_ContextCall(PSI_Context *C, decl_callinfo *decl_call); void PSI_ContextDump(PSI_Context *C, int fd); void PSI_ContextDtor(PSI_Context *C); void PSI_ContextFree(PSI_Context **C); diff --git a/src/libffi.c b/src/libffi.c index ee077af..257fb48 100644 --- a/src/libffi.c +++ b/src/libffi.c @@ -127,6 +127,8 @@ static inline PSI_LibffiCall *PSI_LibffiCallAlloc(PSI_Context *C, decl *decl) { call->params[c] = NULL; decl->call.info = call; + decl->call.rval = decl->func->ptr; + decl->call.argc = c; decl->call.args = (void **) &call->params[c+1]; rc = ffi_prep_cif(&call->signature, psi_ffi_abi(decl->abi->convention), @@ -250,10 +252,10 @@ static zend_function_entry *psi_ffi_compile(PSI_Context *C) return zfe; } -static void psi_ffi_call(PSI_Context *C, impl_val *ret_val, decl *decl) { - PSI_LibffiCall *call = decl->call.info; +static void psi_ffi_call(PSI_Context *C, decl_callinfo *decl_call) { + PSI_LibffiCall *call = decl_call->info; - ffi_call(&call->signature, FFI_FN(decl->call.sym), ret_val, decl->call.args); + ffi_call(&call->signature, FFI_FN(decl_call->sym), decl_call->rval, decl_call->args); } static PSI_ContextOps ops = { diff --git a/src/libjit.c b/src/libjit.c index 45ee8e7..13c0aa4 100644 --- a/src/libjit.c +++ b/src/libjit.c @@ -87,6 +87,8 @@ static inline PSI_LibjitCall *PSI_LibjitCallAlloc(PSI_Context *C, decl *decl) { call->params[c] = NULL; decl->call.info = call; + decl->call.rval = decl->func->ptr; + decl->call.argc = c; decl->call.args = (void **) &call->params[c+1]; call->signature = jit_type_create_signature( @@ -208,11 +210,11 @@ static zend_function_entry *psi_jit_compile(PSI_Context *C) return zfe; } -static void psi_jit_call(PSI_Context *C, impl_val *ret_val, decl *decl) { - PSI_LibjitCall *call = decl->call.info; +static void psi_jit_call(PSI_Context *C, decl_callinfo *decl_call) { + PSI_LibjitCall *call = decl_call->info; - jit_apply(call->signature, decl->call.sym, decl->call.args, - decl->args->count, ret_val); + jit_apply(call->signature, decl_call->sym, decl_call->args, + decl_call->argc, decl_call->rval); } static PSI_ContextOps ops = { diff --git a/src/module.c b/src/module.c index c820f4f..ba3e4d5 100644 --- a/src/module.c +++ b/src/module.c @@ -703,7 +703,6 @@ static inline void psi_do_return(zval *return_value, return_stmt *ret) static inline void psi_do_free(free_stmt *fre) { size_t i, j; - impl_val dummy; for (i = 0; i < fre->calls->count; ++i) { free_call *f = fre->calls->list[i]; @@ -716,7 +715,7 @@ static inline void psi_do_free(free_stmt *fre) } /* FIXME: check in validate_* that free functions return scalar */ - PSI_ContextCall(&PSI_G(context), &dummy, f->decl); + PSI_ContextCall(&PSI_G(context), &f->decl->call); } } @@ -1007,7 +1006,7 @@ void psi_call(zend_execute_data *execute_data, zval *return_value, impl *impl) impl->decl->call.args[i] = impl->decl->args->args[i]->let->ptr; } - PSI_ContextCall(&PSI_G(context), var->arg->ptr, impl->decl); + PSI_ContextCall(&PSI_G(context), &impl->decl->call); psi_do_return(return_value, ret); for (i = 0; i < impl->stmts->set.count; ++i) { diff --git a/src/parser.h b/src/parser.h index 55f4f9d..7faa43b 100644 --- a/src/parser.h +++ b/src/parser.h @@ -262,16 +262,20 @@ static inline void free_decl_abi(decl_abi *abi) { free(abi); } +typedef struct decl_callinfo { + void *sym; + void *info; + size_t argc; + void **args; + void *rval; +} decl_callinfo; + typedef struct decl { decl_abi *abi; decl_arg *func; decl_args *args; struct impl *impl; - struct { - void *sym; - void *info; - void **args; - } call; + decl_callinfo call; } decl; static inline decl* init_decl(decl_abi *abi, decl_arg *func, decl_args *args) { -- 2.30.2 From 7d89722785c32163fe6252ed199c86ba6ee0e28c Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Mon, 4 Jan 2016 11:15:17 +0100 Subject: [PATCH 03/16] flush --- src/context.c | 4 +- src/context.h | 2 +- src/module.c | 273 ++++++++++++++++++++++++++++------------------ src/parser.h | 10 +- src/parser_proc.y | 2 +- 5 files changed, 182 insertions(+), 109 deletions(-) diff --git a/src/context.c b/src/context.c index ba58720..8492fcd 100644 --- a/src/context.c +++ b/src/context.c @@ -1404,8 +1404,8 @@ void PSI_ContextDump(PSI_Context *C, int fd) dprintf(fd, " = %s", iarg->def->text); } } - if (impl->func->args->vararg) { - impl_arg *vararg = impl->func->args->vararg; + if (impl->func->args->vararg.name) { + impl_arg *vararg = impl->func->args->vararg.name; dprintf(fd, ", %s %s...$%s", vararg->type->name, diff --git a/src/context.h b/src/context.h index 6611a4a..92c9d2c 100644 --- a/src/context.h +++ b/src/context.h @@ -14,7 +14,7 @@ struct PSI_ContextOps { void (*init)(PSI_Context *C); void (*dtor)(PSI_Context *C); zend_function_entry *(*compile)(PSI_Context *C); - void (*call)(PSI_Context *C, decl *decl); + void (*call)(PSI_Context *C, decl_callinfo *decl_call); }; struct PSI_Context { diff --git a/src/module.c b/src/module.c index ba3e4d5..cf147b6 100644 --- a/src/module.c +++ b/src/module.c @@ -122,7 +122,7 @@ zend_internal_arg_info *psi_internal_arginfo(impl *impl) zend_internal_arg_info *aip; zend_internal_function_info *fi; - aip = calloc(impl->func->args->count + 1 + !!impl->func->args->vararg, sizeof(*aip)); + aip = calloc(impl->func->args->count + 1 + !!impl->func->args->vararg.name, sizeof(*aip)); fi = (zend_internal_function_info *) &aip[0]; fi->allow_null = 1; @@ -130,8 +130,8 @@ zend_internal_arg_info *psi_internal_arginfo(impl *impl) fi->return_reference = impl->func->return_reference; fi->type_hint = psi_internal_type(impl->func->return_type); - if (impl->func->args->vararg) { - impl_arg *vararg = impl->func->args->vararg; + if (impl->func->args->vararg.name) { + impl_arg *vararg = impl->func->args->vararg.name; zend_internal_arg_info *ai = &aip[impl->func->args->count]; ai->name = vararg->var->name; @@ -490,11 +490,26 @@ static inline ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, i return rv; } - ZEND_PARSE_PARAMETERS_START(psi_num_min_args(impl), impl->func->args->vararg ? -1 : impl->func->args->count) + ZEND_PARSE_PARAMETERS_START(psi_num_min_args(impl), impl->func->args->vararg.name ? -1 : impl->func->args->count) nextarg: - iarg = impl->func->args->args[_i]; - if (iarg->def) { + if (impl->func->args->vararg.name && _i >= impl->func->args->count) { + impl_arg *varg = impl->func->args->vararg.name; + iarg = init_impl_arg( + init_impl_type(varg->type->type, varg->type->name), + init_impl_var(varg->var->name, varg->var->reference), + NULL); + Z_PARAM_OPTIONAL; + if (_i == impl->func->args->count) { + impl->func->args->vararg.args = init_impl_args(iarg); + } else { + add_impl_arg(impl->func->args->vararg.args, iarg); + } + } else { + iarg = impl->func->args->args[_i]; + if (iarg->def) { + Z_PARAM_OPTIONAL; + } } if (PSI_T_BOOL == iarg->type->type) { Z_PARAM_BOOL(iarg->val.zend.bval); @@ -511,24 +526,12 @@ static inline ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, i Z_PARAM_PROLOGUE(0); } else if (PSI_T_OBJECT == iarg->type->type) { Z_PARAM_PROLOGUE(0); + } else if (PSI_T_MIXED == iarg->type->type) { + Z_PARAM_PROLOGUE(0); } else { error_code = ZPP_ERROR_FAILURE; break; } - if (impl->func->args->vararg) { - iarg = impl->func->args->vararg; - - if (_i == impl->func->args->count) { - zval *ptr = iarg->_zv = calloc(_num_args - _i + 1, sizeof(zval)); - - _optional = 1; - while (_i < _num_args) { - Z_PARAM_PROLOGUE(0); - ZVAL_COPY_VALUE(ptr++, _arg); - } - break; - } - } if (_i < _num_args) { goto nextarg; } @@ -576,6 +579,103 @@ static inline void *psi_do_calloc(let_calloc *alloc) return mem; } +static inline token_t psi_let_fn(token_t impl_type) { + switch (impl_type) { + case PSI_T_BOOL: + return PSI_T_BOOLVAL; + case PSI_T_INT: + return PSI_T_INTVAL; + case PSI_T_FLOAT: + case PSI_T_DOUBLE: + return PSI_T_FLOATVAL; + case PSI_T_STRING: + return PSI_T_STRVAL; + } + return 0; +} + +static inline ZEND_RESULT_CODE psi_let_val(token_t let_func, impl_arg *iarg, impl_val *arg_val, decl_struct *strct, void **to_free) +{ + switch (let_func) { + case PSI_T_BOOLVAL: + if (iarg->type->type == PSI_T_BOOL) { + arg_val->cval = iarg->val.zend.bval; + } else { + arg_val->cval = zend_is_true(iarg->_zv); + } + break; + case PSI_T_INTVAL: + if (iarg->type->type == PSI_T_INT) { + arg_val->lval = iarg->val.zend.lval; + } else { + arg_val->lval = zval_get_long(iarg->_zv); + } + break; + case PSI_T_FLOATVAL: + if (iarg->type->type == PSI_T_FLOAT || iarg->type->type == PSI_T_DOUBLE) { + arg_val->dval = iarg->val.dval; + } else { + arg_val->dval = zval_get_double(iarg->_zv); + } + break; + case PSI_T_PATHVAL: + case PSI_T_STRVAL: + if (iarg->type->type == PSI_T_STRING) { + if (iarg->val.zend.str) { + arg_val->ptr = estrdup(iarg->val.zend.str->val); + *to_free = arg_val->ptr; + } else { + arg_val->ptr = ""; + } + } else { + zend_string *zs = zval_get_string(iarg->_zv); + arg_val->ptr = estrdup(zs->val); + *to_free = arg_val->ptr; + zend_string_release(zs); + } + if (PSI_T_PATHVAL == let_func) { + if (SUCCESS != php_check_open_basedir(arg_val->ptr)) { + efree(arg_val->ptr); + return FAILURE; + } + } + break; + case PSI_T_STRLEN: + if (iarg->type->type == PSI_T_STRING) { + if (iarg->val.zend.str) { + arg_val->lval = iarg->val.zend.str->len; + } else { + arg_val->lval = 0; + } + } else { + zend_string *zs = zval_get_string(iarg->_zv); + arg_val->lval = zs->len; + zend_string_release(zs); + } + break; + case PSI_T_ARRVAL: + if (iarg->type->type == PSI_T_ARRAY) { + arg_val->ptr = psi_array_to_struct(strct, HASH_OF(iarg->_zv)); + *to_free = arg_val->ptr; + } + break; + case PSI_T_OBJVAL: + if (iarg->type->type == PSI_T_OBJECT) { + psi_object *obj; + + if (!instanceof_function(Z_OBJCE_P(iarg->_zv), psi_class_entry)) { + return FAILURE; + } + + obj = PSI_OBJ(iarg->_zv, NULL); + arg_val->ptr = obj->data; + } + break; + EMPTY_SWITCH_DEFAULT_CASE(); + } + return SUCCESS; +} + static inline void *psi_do_let(let_stmt *let) { decl_arg *darg = let->var->arg; @@ -604,81 +704,8 @@ static inline void *psi_do_let(let_stmt *let) case PSI_LET_FUNC: iarg = let->val->data.func->arg; - switch (let->val->data.func->type) { - case PSI_T_BOOLVAL: - if (iarg->type->type == PSI_T_BOOL) { - arg_val->cval = iarg->val.zend.bval; - } else { - arg_val->cval = zend_is_true(iarg->_zv); - } - break; - case PSI_T_INTVAL: - if (iarg->type->type == PSI_T_INT) { - arg_val->lval = iarg->val.zend.lval; - } else { - arg_val->lval = zval_get_long(iarg->_zv); - } - break; - case PSI_T_PATHVAL: - case PSI_T_STRVAL: - if (iarg->type->type == PSI_T_STRING) { - if (iarg->val.zend.str) { - arg_val->ptr = estrdup(iarg->val.zend.str->val); - darg->mem = arg_val->ptr; - } else { - arg_val->ptr = ""; - } - } else { - zend_string *zs = zval_get_string(iarg->_zv); - arg_val->ptr = estrdup(zs->val); - darg->mem = arg_val->ptr; - zend_string_release(zs); - } - if (PSI_T_PATHVAL == darg->let->val->data.func->type) { - if (SUCCESS != php_check_open_basedir(arg_val->ptr)) { - efree(arg_val->ptr); - return NULL; - } - } - break; - case PSI_T_STRLEN: - if (iarg->type->type == PSI_T_STRING) { - if (iarg->val.zend.str) { - arg_val->lval = iarg->val.zend.str->len; - } else { - arg_val->lval = 0; - } - } else { - zend_string *zs = zval_get_string(iarg->_zv); - arg_val->lval = zs->len; - zend_string_release(zs); - } - break; - case PSI_T_ARRVAL: - if (iarg->type->type == PSI_T_ARRAY) { - decl_type *type = real_decl_type(darg->type); - - switch (type->type) { - case PSI_T_STRUCT: - arg_val->ptr = psi_array_to_struct(type->strct, HASH_OF(iarg->_zv)); - darg->mem = arg_val->ptr; - break; - } - } - break; - case PSI_T_OBJVAL: - if (iarg->type->type == PSI_T_OBJECT) { - psi_object *obj; - - if (!instanceof_function(Z_OBJCE_P(iarg->_zv), psi_class_entry)) { - return NULL; - } - - obj = PSI_OBJ(iarg->_zv, NULL); - arg_val->ptr = obj->data; - } - break; - EMPTY_SWITCH_DEFAULT_CASE(); + if (SUCCESS != psi_let_val(let->val->data.func->type, iarg, real_decl_type(darg->type)->strct, darg->ptr, &darg->mem)) { + return NULL; } } @@ -980,13 +1007,43 @@ PSI_CALC_FN(sub) #define PSI_CALC(var1, var2) (var1) / (var2) PSI_CALC_FN(div) +static inline void psi_do_args(impl *impl) { + size_t i; + + for (i = 0; i < impl->decl->args->count; ++i) { + impl->decl->call.args[i] = impl->decl->args->args[i]->let->ptr; + } +} + +static inline void psi_do_varargs(impl *impl, void ***free_list) { + size_t i, j; + impl_vararg *va = &impl->func->args->vararg; + size_t vacount = va->args->count; + void **tmpvals = calloc(vacount, sizeof(*tmpvals)); + token_t type = psi_let_fn(va->name->type->type); + + va->types = calloc(vacount, sizeof(*va->types)); + va->values = calloc(vacount, sizeof(*va->values)); + + for (i = 0, j = 0; i < vacount; ++i) { + impl_arg *vaarg = va->args->args[i]; + void *to_free = NULL; + + psi_let_val(type, vaarg, &va->values[i], NULL, &to_free); + if (to_free) { + *free_list = realloc(*free_list, (j + 1) * sizeof(*free_list)); + (*free_list)[j++] = to_free; + } + } +} + void psi_call(zend_execute_data *execute_data, zval *return_value, impl *impl) { - size_t i; - return_stmt *ret = impl->stmts->ret.list[0]; - decl_var *var = ret->set->vars->vars[0]; + size_t i, j; + decl_callinfo *call = &impl->decl->call; + void **free_list = NULL; - memset(var->arg->ptr, 0, sizeof(impl_val)); + memset(impl->decl->func->ptr, 0, sizeof(impl_val)); if (SUCCESS != psi_parse_args(execute_data, impl)) { return; @@ -996,18 +1053,26 @@ void psi_call(zend_execute_data *execute_data, zval *return_value, impl *impl) let_stmt *let = impl->stmts->let.list[i]; if (!psi_do_let(let)) { - psi_do_return(return_value, ret); + psi_do_return(return_value, impl->stmts->ret.list[0]); psi_do_clean(impl); return; } } - if (impl->decl->args) for (i = 0; i < impl->decl->args->count; ++i) { - impl->decl->call.args[i] = impl->decl->args->args[i]->let->ptr; + if (impl->decl->args) { + psi_do_args(impl); + + if (impl->func->args->vararg.args) { + call = psi_do_varargs(impl, &free_list); + } } - PSI_ContextCall(&PSI_G(context), &impl->decl->call); - psi_do_return(return_value, ret); + if (impl->func->args->vararg.args) { + PSI_ContextCallVarargs(&PSI_G(context), &impl->decl->call) + } else { + PSI_ContextCall(&PSI_G(context), &impl->decl->call); + } + psi_do_return(return_value, impl->stmts->ret.list[0]); for (i = 0; i < impl->stmts->set.count; ++i) { set_stmt *set = impl->stmts->set.list[i]; diff --git a/src/parser.h b/src/parser.h index 7faa43b..e774e9b 100644 --- a/src/parser.h +++ b/src/parser.h @@ -503,10 +503,18 @@ static inline void free_impl_arg(impl_arg *arg) { free(arg); } +typedef struct impl_vararg { + impl_arg *name; + struct impl_args *args; + token_t *types; + impl_val *values; + void **free_list; +} impl_vararg; + typedef struct impl_args { impl_arg **args; size_t count; - impl_arg *vararg; + impl_vararg vararg; } impl_args; static inline impl_args *init_impl_args(impl_arg *arg) { diff --git a/src/parser_proc.y b/src/parser_proc.y index 7f38f17..fc2ff7a 100644 --- a/src/parser_proc.y +++ b/src/parser_proc.y @@ -326,7 +326,7 @@ impl_args(args) ::= LPAREN impl_arg_list(args_) RPAREN. { } impl_args(args) ::= LPAREN impl_arg_list(args_) COMMA impl_vararg(va) RPAREN. { args = args_; - args->vararg = va; + args->vararg.name = va; } %type impl_vararg {impl_arg*} -- 2.30.2 From 574519ef5e3ab76f00253fad870afce7135638d1 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Mon, 4 Jan 2016 15:44:41 +0100 Subject: [PATCH 04/16] flush --- m4/psi.m4 | 4 +- src/context.c | 19 ++++++++- src/context.h | 4 +- src/libffi.c | 41 +++++++++++++++++++- src/libjit.c | 2 +- src/module.c | 105 +++++++++++++++++++++++++++++++++----------------- 6 files changed, 130 insertions(+), 45 deletions(-) diff --git a/m4/psi.m4 b/m4/psi.m4 index e9955f0..ff483bf 100644 --- a/m4/psi.m4 +++ b/m4/psi.m4 @@ -77,10 +77,10 @@ AC_DEFUN(PSI_CHECK_LIBJIT, [ fi ]) +PHP_ARG_WITH(psi-libffi, where to find libffi, +[ --with-psi-libffi=DIR PSI: path to libffi], [ ], [ ]) AC_DEFUN(PSI_CHECK_LIBFFI, [ AC_REQUIRE([PSI_PKG_CONFIG])dnl - PHP_ARG_WITH(psi-libffi, where to find libffi, - [ --with-psi-libffi=DIR PSI: path to libffi], [ ], [ ]) AC_CACHE_CHECK(for libffi through pkg-config, psi_cv_libffi, [ if $PKG_CONFIG --exists libffi diff --git a/src/context.c b/src/context.c index 8492fcd..f580f7f 100644 --- a/src/context.c +++ b/src/context.c @@ -161,11 +161,26 @@ int psi_glob(const char *pattern, int flags, return rv; } +int psi_printf(const char *fmt, ...) { + int rs; + char *a1; + va_list ap1, ap2; + + va_start(ap1, fmt); + va_copy(ap2, ap1); + a1 = va_arg(ap2, char *); + rs = vprintf(fmt, ap1); + va_end(ap1); + va_end(ap2); + return rs; +} + static struct psi_func_redir { const char *name; void (*func)(void); } psi_func_redirs[] = { {"glob", (void (*)(void)) psi_glob}, + {"printf", (void (*)(void)) psi_printf}, PSI_REDIRS {0} }; @@ -1214,9 +1229,9 @@ zend_function_entry *PSI_ContextCompile(PSI_Context *C) } -void PSI_ContextCall(PSI_Context *C, decl_callinfo *decl_call) +void PSI_ContextCall(PSI_Context *C, decl_callinfo *decl_call, impl_vararg *va) { - C->ops->call(C, decl_call); + C->ops->call(C, decl_call, va); } static inline void dump_decl_type(int fd, decl_type *t) { diff --git a/src/context.h b/src/context.h index 92c9d2c..a010eee 100644 --- a/src/context.h +++ b/src/context.h @@ -14,7 +14,7 @@ struct PSI_ContextOps { void (*init)(PSI_Context *C); void (*dtor)(PSI_Context *C); zend_function_entry *(*compile)(PSI_Context *C); - void (*call)(PSI_Context *C, decl_callinfo *decl_call); + void (*call)(PSI_Context *C, decl_callinfo *decl_call, impl_vararg *va); }; struct PSI_Context { @@ -30,7 +30,7 @@ PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErr void PSI_ContextBuild(PSI_Context *C, const char *path); int PSI_ContextValidate(PSI_Context *C, PSI_Parser *P); zend_function_entry *PSI_ContextCompile(PSI_Context *C); -void PSI_ContextCall(PSI_Context *C, decl_callinfo *decl_call); +void PSI_ContextCall(PSI_Context *C, decl_callinfo *decl_call, impl_vararg *va); void PSI_ContextDump(PSI_Context *C, int fd); void PSI_ContextDtor(PSI_Context *C); void PSI_ContextFree(PSI_Context **C); diff --git a/src/libffi.c b/src/libffi.c index 257fb48..f776fb7 100644 --- a/src/libffi.c +++ b/src/libffi.c @@ -93,6 +93,20 @@ static inline ffi_type *psi_ffi_token_type(token_t t) { return &ffi_type_double; } } +static inline ffi_type *psi_ffi_impl_type(token_t impl_type) { + switch (impl_type) { + case PSI_T_BOOL: + return &ffi_type_sint8; + case PSI_T_INT: + return &ffi_type_sint64; + case PSI_T_STRING: + return &ffi_type_pointer; + case PSI_T_FLOAT: + case PSI_T_DOUBLE: + return &ffi_type_double; + EMPTY_SWITCH_DEFAULT_CASE(); + } +} static inline ffi_type *psi_ffi_decl_type(decl_type *type) { return psi_ffi_token_type(real_decl_type(type)->type); } @@ -252,10 +266,33 @@ static zend_function_entry *psi_ffi_compile(PSI_Context *C) return zfe; } -static void psi_ffi_call(PSI_Context *C, decl_callinfo *decl_call) { +static void psi_ffi_call(PSI_Context *C, decl_callinfo *decl_call, impl_vararg *va) { PSI_LibffiCall *call = decl_call->info; - ffi_call(&call->signature, FFI_FN(decl_call->sym), decl_call->rval, decl_call->args); + if (va) { + ffi_status rc; + ffi_cif signature; + size_t i, nfixedargs = decl_call->argc, ntotalargs = nfixedargs + va->args->count; + void **params = calloc(2 * ntotalargs + 2, sizeof(void *)); + + for (i = 0; i < nfixedargs; ++i) { + params[i] = call->params[i]; + params[i + ntotalargs + 1] = call->params[i + nfixedargs + 1]; + } + for (i = 0; i < va->args->count; ++i) { + params[nfixedargs + i] = psi_ffi_impl_type(va->types[i]); + params[nfixedargs + i + ntotalargs + 1] = &va->values[i]; + } + + rc = ffi_prep_cif_var(&signature, call->signature.abi, + nfixedargs, ntotalargs, + call->signature.rtype, (ffi_type **) params); + ZEND_ASSERT(FFI_OK == rc); + ffi_call(&signature, FFI_FN(decl_call->sym), decl_call->rval, ¶ms[ntotalargs + 1]); + free(params); + } else { + ffi_call(&call->signature, FFI_FN(decl_call->sym), decl_call->rval, decl_call->args); + } } static PSI_ContextOps ops = { diff --git a/src/libjit.c b/src/libjit.c index 13c0aa4..bc24c1a 100644 --- a/src/libjit.c +++ b/src/libjit.c @@ -210,7 +210,7 @@ static zend_function_entry *psi_jit_compile(PSI_Context *C) return zfe; } -static void psi_jit_call(PSI_Context *C, decl_callinfo *decl_call) { +static void psi_jit_call(PSI_Context *C, decl_callinfo *decl_call, impl_vararg *va) { PSI_LibjitCall *call = decl_call->info; jit_apply(call->signature, decl_call->sym, decl_call->args, diff --git a/src/module.c b/src/module.c index cf147b6..ff7353a 100644 --- a/src/module.c +++ b/src/module.c @@ -532,6 +532,8 @@ static inline ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, i error_code = ZPP_ERROR_FAILURE; break; } + iarg->_zv = _arg; + ZVAL_DEREF(iarg->_zv); if (_i < _num_args) { goto nextarg; } @@ -545,8 +547,6 @@ static inline ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, i iarg = impl->func->args->args[i]; if (i < EX_NUM_ARGS()) { - iarg->_zv = ++zarg; - ZVAL_DEREF(iarg->_zv); } else if (iarg->def) { switch (iarg->type->type) { case PSI_T_BOOL: @@ -579,21 +579,6 @@ static inline void *psi_do_calloc(let_calloc *alloc) return mem; } -static inline token_t psi_let_fn(token_t impl_type) { - switch (impl_type) { - case PSI_T_BOOL: - return PSI_T_BOOLVAL; - case PSI_T_INT: - return PSI_T_INTVAL; - case PSI_T_FLOAT: - case PSI_T_DOUBLE: - return PSI_T_FLOATVAL; - case PSI_T_STRING: - return PSI_T_STRVAL; - } - return 0; -} - static inline ZEND_RESULT_CODE psi_let_val(token_t let_func, impl_arg *iarg, impl_val *arg_val, decl_struct *strct, void **to_free) { switch (let_func) { @@ -704,7 +689,7 @@ static inline void *psi_do_let(let_stmt *let) case PSI_LET_FUNC: iarg = let->val->data.func->arg; - if (SUCCESS != psi_let_val(let->val->data.func->type, iarg, real_decl_type(darg->type)->strct, darg->ptr, &darg->mem)) { + if (SUCCESS != psi_let_val(let->val->data.func->type, iarg, darg->ptr, real_decl_type(darg->type)->strct, &darg->mem)) { return NULL; } } @@ -742,7 +727,7 @@ static inline void psi_do_free(free_stmt *fre) } /* FIXME: check in validate_* that free functions return scalar */ - PSI_ContextCall(&PSI_G(context), &f->decl->call); + PSI_ContextCall(&PSI_G(context), &f->decl->call, NULL); } } @@ -779,6 +764,29 @@ static inline void psi_do_clean(impl *impl) darg->mem = NULL; } } + + if (impl->func->args->vararg.args) { + free_impl_args(impl->func->args->vararg.args); + impl->func->args->vararg.args = NULL; + } + if (impl->func->args->vararg.types) { + efree(impl->func->args->vararg.types); + impl->func->args->vararg.types = NULL; + } + if (impl->func->args->vararg.values) { + efree(impl->func->args->vararg.values); + impl->func->args->vararg.values = NULL; + } + if (impl->func->args->vararg.free_list) { + void **list = impl->func->args->vararg.free_list; + + while (*list) { + efree(*list++); + } + + efree(impl->func->args->vararg.free_list); + impl->func->args->vararg.free_list = NULL; + } } static inline int psi_calc_num_exp_value(num_exp *exp, impl_val *strct, impl_val *res) { @@ -1015,33 +1023,62 @@ static inline void psi_do_args(impl *impl) { } } -static inline void psi_do_varargs(impl *impl, void ***free_list) { +static inline impl_vararg *psi_do_varargs(impl *impl) { size_t i, j; impl_vararg *va = &impl->func->args->vararg; size_t vacount = va->args->count; - void **tmpvals = calloc(vacount, sizeof(*tmpvals)); - token_t type = psi_let_fn(va->name->type->type); - va->types = calloc(vacount, sizeof(*va->types)); - va->values = calloc(vacount, sizeof(*va->values)); + + if (!vacount) { + return NULL; + } + + va->types = ecalloc(vacount, sizeof(*va->types)); + va->values = ecalloc(vacount, sizeof(*va->values)); for (i = 0, j = 0; i < vacount; ++i) { impl_arg *vaarg = va->args->args[i]; void *to_free = NULL; + token_t let_fn, vatype = va->name->type->type; + + if (vatype == PSI_T_MIXED) { + switch (Z_TYPE_P(vaarg->_zv)) { + case IS_TRUE: + case IS_FALSE: vatype = PSI_T_BOOL; break; + case IS_LONG: vatype = PSI_T_INT; break; + case IS_DOUBLE: vatype = PSI_T_FLOAT; break; + default: vatype = PSI_T_STRING; break; + } + } + + + switch (vatype) { + case PSI_T_BOOL: let_fn = PSI_T_BOOLVAL; break; + case PSI_T_INT: let_fn = PSI_T_INTVAL; break; + case PSI_T_FLOAT: + case PSI_T_DOUBLE: let_fn = PSI_T_FLOATVAL;break; + case PSI_T_STRING: let_fn = PSI_T_STRVAL; break; + EMPTY_SWITCH_DEFAULT_CASE(); + } + + va->types[i] = vatype; + psi_let_val(let_fn, vaarg, &va->values[i], NULL, &to_free); - psi_let_val(type, vaarg, &va->values[i], NULL, &to_free); if (to_free) { - *free_list = realloc(*free_list, (j + 1) * sizeof(*free_list)); - (*free_list)[j++] = to_free; + if (!va->free_list) { + va->free_list = ecalloc(vacount - i + 1, sizeof(*va->free_list)); + } + va->free_list[j++] = to_free; } } + + return va; } void psi_call(zend_execute_data *execute_data, zval *return_value, impl *impl) { - size_t i, j; - decl_callinfo *call = &impl->decl->call; - void **free_list = NULL; + size_t i; + impl_vararg *va = NULL; memset(impl->decl->func->ptr, 0, sizeof(impl_val)); @@ -1063,15 +1100,11 @@ void psi_call(zend_execute_data *execute_data, zval *return_value, impl *impl) psi_do_args(impl); if (impl->func->args->vararg.args) { - call = psi_do_varargs(impl, &free_list); + va = psi_do_varargs(impl); } } - if (impl->func->args->vararg.args) { - PSI_ContextCallVarargs(&PSI_G(context), &impl->decl->call) - } else { - PSI_ContextCall(&PSI_G(context), &impl->decl->call); - } + PSI_ContextCall(&PSI_G(context), &impl->decl->call, va); psi_do_return(return_value, impl->stmts->ret.list[0]); for (i = 0; i < impl->stmts->set.count; ++i) { -- 2.30.2 From 45cba21d5001261fd5dbceeea1e7374bbee6c1b0 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Mon, 4 Jan 2016 16:54:22 +0100 Subject: [PATCH 05/16] fix leaks --- src/parser.h | 6 ++++++ src/parser_proc.y | 1 + 2 files changed, 7 insertions(+) diff --git a/src/parser.h b/src/parser.h index e774e9b..014509d 100644 --- a/src/parser.h +++ b/src/parser.h @@ -73,6 +73,9 @@ static inline decl_type *real_decl_type(decl_type *type) { } static inline void free_decl_type(decl_type *type) { + if (type->token) { + free(type->token); + } free(type->name); free(type); } @@ -539,6 +542,9 @@ static inline void free_impl_args(impl_args *args) { for (i = 0; i < args->count; ++i) { free_impl_arg(args->args[i]); } + if (args->vararg.name) { + free_impl_arg(args->vararg.name); + } free(args->args); free(args); } diff --git a/src/parser_proc.y b/src/parser_proc.y index fc2ff7a..d55f7e7 100644 --- a/src/parser_proc.y +++ b/src/parser_proc.y @@ -333,6 +333,7 @@ impl_args(args) ::= LPAREN impl_arg_list(args_) COMMA impl_vararg(va) RPAREN. { %destructor impl_vararg {free_impl_arg($$);} impl_vararg(va) ::= impl_type(type) reference(r) ELLIPSIS DOLLAR NAME(T). { va = init_impl_arg(type, init_impl_var(T->text, r), NULL); + free(T); } %type impl_arg_list {impl_args*} -- 2.30.2 From 8cd572501cde6de9ce74840fe7f749ed076b7eda Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Mon, 4 Jan 2016 17:11:29 +0100 Subject: [PATCH 06/16] libjit vararg call --- src/context.c | 15 --------------- src/libjit.c | 49 +++++++++++++++++++++++++++++++++++++++++++++---- src/module.c | 6 ++---- 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/src/context.c b/src/context.c index f580f7f..b07b653 100644 --- a/src/context.c +++ b/src/context.c @@ -161,26 +161,11 @@ int psi_glob(const char *pattern, int flags, return rv; } -int psi_printf(const char *fmt, ...) { - int rs; - char *a1; - va_list ap1, ap2; - - va_start(ap1, fmt); - va_copy(ap2, ap1); - a1 = va_arg(ap2, char *); - rs = vprintf(fmt, ap1); - va_end(ap1); - va_end(ap2); - return rs; -} - static struct psi_func_redir { const char *name; void (*func)(void); } psi_func_redirs[] = { {"glob", (void (*)(void)) psi_glob}, - {"printf", (void (*)(void)) psi_printf}, PSI_REDIRS {0} }; diff --git a/src/libjit.c b/src/libjit.c index bc24c1a..8a766f3 100644 --- a/src/libjit.c +++ b/src/libjit.c @@ -45,6 +45,20 @@ static inline jit_type_t psi_jit_token_type(token_t t) { EMPTY_SWITCH_DEFAULT_CASE(); } } +static inline jit_type_t psi_jit_impl_type(token_t impl_type) { + switch (impl_type) { + case PSI_T_BOOL: + return jit_type_sbyte; + case PSI_T_INT: + return jit_type_long; + case PSI_T_STRING: + return jit_type_void_ptr; + case PSI_T_FLOAT: + case PSI_T_DOUBLE: + return jit_type_sys_double; + EMPTY_SWITCH_DEFAULT_CASE(); + } +} static inline jit_type_t psi_jit_decl_type(decl_type *type) { return psi_jit_token_type(real_decl_type(type)->type); } @@ -68,7 +82,7 @@ typedef struct PSI_LibjitContext { typedef struct PSI_LibjitCall { void *closure; jit_type_t signature; - jit_type_t params[1]; /* [type1, type2, NULL, arg1, arg2] ... */ + void *params[1]; /* [type1, type2, NULL, arg1, arg2] ... */ } PSI_LibjitCall; typedef struct PSI_LibjitData { @@ -94,7 +108,7 @@ static inline PSI_LibjitCall *PSI_LibjitCallAlloc(PSI_Context *C, decl *decl) { call->signature = jit_type_create_signature( psi_jit_abi(decl->abi->convention), psi_jit_decl_arg_type(decl->func), - call->params, c, 1); + (jit_type_t *) call->params, c, 1); return call; } @@ -106,6 +120,7 @@ static inline void PSI_LibjitCallInitClosure(PSI_Context *C, PSI_LibjitCall *cal static inline void PSI_LibjitCallFree(PSI_LibjitCall *call) { jit_type_free(call->signature); + free(call); } static inline PSI_LibjitContext *PSI_LibjitContextInit(PSI_LibjitContext *L) { @@ -213,8 +228,34 @@ static zend_function_entry *psi_jit_compile(PSI_Context *C) static void psi_jit_call(PSI_Context *C, decl_callinfo *decl_call, impl_vararg *va) { PSI_LibjitCall *call = decl_call->info; - jit_apply(call->signature, decl_call->sym, decl_call->args, - decl_call->argc, decl_call->rval); + if (va) { + jit_type_t signature; + size_t i, nfixedargs = decl_call->argc, ntotalargs = nfixedargs + va->args->count; + void **params = calloc(2 * ntotalargs + 2, sizeof(void *)); + + for (i = 0; i < nfixedargs; ++i) { + params[i] = call->params[i]; + params[i + ntotalargs + 1] = call->params[i + nfixedargs + 1]; + } + for (i = 0; i < va->args->count; ++i) { + params[nfixedargs + i] = psi_jit_impl_type(va->types[i]); + params[nfixedargs + i + ntotalargs + 1] = &va->values[i]; + } + + signature = jit_type_create_signature( + jit_type_get_abi(call->signature), + jit_type_get_return(call->signature), + (jit_type_t *) params, ntotalargs, 1); + ZEND_ASSERT(signature); + + jit_apply(signature, decl_call->sym, ¶ms[ntotalargs + 1], + nfixedargs, decl_call->rval); + jit_type_free(signature); + free(params); + } else { + jit_apply(call->signature, decl_call->sym, decl_call->args, + decl_call->argc, decl_call->rval); + } } static PSI_ContextOps ops = { diff --git a/src/module.c b/src/module.c index ff7353a..321ab63 100644 --- a/src/module.c +++ b/src/module.c @@ -476,7 +476,6 @@ void psi_to_object(zval *return_value, set_value *set, impl_val *r_val) static inline ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, impl *impl) { size_t i; - zval *zarg = ZEND_CALL_ARG(execute_data, 0); impl_arg *iarg; zend_error_handling zeh; @@ -544,10 +543,9 @@ static inline ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, i /* set up defaults */ for (i = 0; i < impl->func->args->count; ++i) { - iarg = impl->func->args->args[i]; + if (i >= EX_NUM_ARGS() && iarg->def) { + iarg = impl->func->args->args[i]; - if (i < EX_NUM_ARGS()) { - } else if (iarg->def) { switch (iarg->type->type) { case PSI_T_BOOL: iarg->val.zend.bval = iarg->def->type == PSI_T_TRUE ? 1 : 0; -- 2.30.2 From 0e6d6d0bdaf5cca59d04a8f4e9fcca8a65f341d8 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Mon, 4 Jan 2016 17:38:15 +0100 Subject: [PATCH 07/16] stdio vararg decls --- config.m4 | 2 ++ m4/psi.m4 | 1 + m4/psi_decl.m4 | 9 +++++++-- m4/stdio.m4 | 10 +++++++++- psi.d/stdio.psi | 2 +- src/context.c | 23 +++++++++++++++++++++++ 6 files changed, 43 insertions(+), 4 deletions(-) diff --git a/config.m4 b/config.m4 index e7d1e1f..cce2aff 100644 --- a/config.m4 +++ b/config.m4 @@ -71,6 +71,8 @@ if test "$PHP_PSI" != no; then AC_DEFINE_UNQUOTED([PSI_MACROS], [$PSI_MACROS], [Redirected Macros]) AC_DEFINE_UNQUOTED([PSI_REDIRS], [$PSI_REDIRS], [Redirected functions]) AC_DEFINE_UNQUOTED([PSI_DECLS], [$PSI_DECLS], [Predefined functions]) + AC_DEFINE_UNQUOTED([PSI_VA_DECLS], [$PSI_VA_DECLS], [Predefined vararg functions]) + PHP_ADD_INCLUDE($PHP_PSI_SRCDIR/src) PHP_ADD_BUILD_DIR($PHP_PSI_BUILDDIR/src) diff --git a/m4/psi.m4 b/m4/psi.m4 index ff483bf..4f09851 100644 --- a/m4/psi.m4 +++ b/m4/psi.m4 @@ -4,6 +4,7 @@ PSI_CONSTS= PSI_REDIRS= PSI_MACROS= PSI_DECLS= +PSI_VA_DECLS= psi_includes() { local have_ diff --git a/m4/psi_decl.m4 b/m4/psi_decl.m4 index 3bc2558..69f8edb 100644 --- a/m4/psi_decl.m4 +++ b/m4/psi_decl.m4 @@ -51,7 +51,7 @@ AC_DEFUN(PSI_DECL_ARG, [ psi_decl_args="[$psi_decl_args{]PSI_TYPE_PAIR(member_type)[, \"]member_name[\",] $pl, $as[}]" ]) -dnl PSI_DECL(type func, args) +dnl PSI_DECL(type func, args, flags) AC_DEFUN(PSI_DECL, [ psi_decl_args= PSI_DECL_ARG($1) @@ -60,9 +60,14 @@ AC_DEFUN(PSI_DECL, [ [()], [], [m4_map_args_sep([PSI_DECL_ARG(m4_normalize(], [))], [], m4_bregexp([$2], [(\(.*\))], [\1]))]) PSI_FUNC(PSI_VAR_NAME($1), [ - PSI_DECLS="$psi_decl_args, {0}, $PSI_DECLS" + ifelse([$3], vararg, [ + PSI_VA_DECLS="$psi_decl_args, {0}, $PSI_VA_DECLS" + ], [ + PSI_DECLS="$psi_decl_args, {0}, $PSI_DECLS" + ]) ], [ PSI_MACRO($1, $2, [ + ifelse([$3], vararg, AC_MSG_ERROR(varargs macro support is not implemented),[]) PSI_DECLS="$psi_decl_args, {0}, $PSI_DECLS" ]) ]) diff --git a/m4/stdio.m4 b/m4/stdio.m4 index a6f8a2e..82aaa1b 100644 --- a/m4/stdio.m4 +++ b/m4/stdio.m4 @@ -71,5 +71,13 @@ AC_DEFUN(PSI_CHECK_STDIO, [ PSI_DECL(FILE *tmpfile, [(void)]) PSI_DECL(char *tmpnam, [(char *s)]) PSI_DECL(int ungetc, [(int c, FILE *stream)]) - + + PSI_DECL(int dprintf, [(int fd, char *fmt)], vararg) + PSI_DECL(int fprintf, [(FILE *stream, char *fmt)], vararg) + PSI_DECL(int fscanf, [(FILE *stream, char *fmt)], vararg) + PSI_DECL(int printf, [(char *fmt)], vararg) + PSI_DECL(int scanf, [(char *fmt)], vararg) + PSI_DECL(int snprintf, [(char *str, size_t size, char *fmt)], vararg) + PSI_DECL(int sprintf, [(char *str, char *fmt)], vararg) + PSI_DECL(int sscanf, [(char *str, char *fmt)], vararg) ]) diff --git a/psi.d/stdio.psi b/psi.d/stdio.psi index 1e136ce..0741874 100644 --- a/psi.d/stdio.psi +++ b/psi.d/stdio.psi @@ -65,7 +65,7 @@ function psi\rewind(object $stream) : void { return void(rewind); } -extern int printf(const char *fmt, ...); +//extern int printf(const char *fmt, ...); function psi\printf(string $fmt, mixed ...$args) : int { let fmt = strval($fmt); return to_int(printf); diff --git a/src/context.c b/src/context.c index b07b653..3b5c734 100644 --- a/src/context.c +++ b/src/context.c @@ -180,6 +180,10 @@ static struct psi_predef_decl { PSI_DECLS {0} }; +static struct psi_predef_decl psi_predef_vararg_decls[] = { + PSI_VA_DECLS + {0} +}; static struct psi_predef_struct { token_t type_tag; @@ -992,6 +996,24 @@ PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErr decl_args *args = init_decl_args(NULL); decl *decl = init_decl(init_decl_abi("default"), func, args); + for (farg = &predef_decl[1]; farg->type_tag; ++farg) { + decl_type *arg_type = init_decl_type(farg->type_tag, farg->type_name); + decl_var *arg_var = init_decl_var(farg->var_name, farg->pointer_level, farg->array_size); + decl_arg *darg = init_decl_arg(arg_type, arg_var); + args = add_decl_arg(args, darg); + } + + T.decls = add_decl(T.decls, decl); + predef_decl = farg; + } + + for (predef_decl = &psi_predef_vararg_decls[0]; predef_decl->type_tag; ++predef_decl) { + struct psi_predef_decl *farg; + decl_type *ftype = init_decl_type(predef_decl->type_tag, predef_decl->type_name); + decl_var *fname = init_decl_var(predef_decl->var_name, predef_decl->pointer_level, predef_decl->array_size); + decl_arg *func = init_decl_arg(ftype, fname); + decl_args *args = init_decl_args(NULL); + decl *decl = init_decl(init_decl_abi("default"), func, args); for (farg = &predef_decl[1]; farg->type_tag; ++farg) { decl_type *arg_type = init_decl_type(farg->type_tag, farg->type_name); @@ -999,6 +1021,7 @@ PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErr decl_arg *darg = init_decl_arg(arg_type, arg_var); args = add_decl_arg(args, darg); } + args->varargs = 1; T.decls = add_decl(T.decls, decl); predef_decl = farg; -- 2.30.2 From ad859923be758c210e2ad4226eb8e3b09bcf91eb Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Mon, 4 Jan 2016 21:57:03 +0100 Subject: [PATCH 08/16] workaround for old libffi --- m4/psi.m4 | 4 ++++ src/libffi.c | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/m4/psi.m4 b/m4/psi.m4 index 4f09851..eecfa61 100644 --- a/m4/psi.m4 +++ b/m4/psi.m4 @@ -130,6 +130,10 @@ AC_DEFUN(PSI_CHECK_LIBFFI, [ ], [ ], -L$psi_cv_libffi_dir/$PHP_LIBDIR) ], -L$psi_cv_libffi_dir/$PHP_LIBDIR) + PHP_CHECK_LIBRARY(ffi, ffi_prep_cif_var, [ + AC_DEFINE(PSI_HAVE_FFI_PREP_CIF_VAR, 1, [ ]) + ], [ + ], -L$psi_cv_libffi_dir/$PHP_LIBDIR) ]) dnl PSI_COMPUTE_STR(variable, string or expression) diff --git a/src/libffi.c b/src/libffi.c index f776fb7..8d41b7a 100644 --- a/src/libffi.c +++ b/src/libffi.c @@ -283,10 +283,15 @@ static void psi_ffi_call(PSI_Context *C, decl_callinfo *decl_call, impl_vararg * params[nfixedargs + i] = psi_ffi_impl_type(va->types[i]); params[nfixedargs + i + ntotalargs + 1] = &va->values[i]; } - +#ifdef PSI_HAVE_FFI_PREP_CIF_VAR rc = ffi_prep_cif_var(&signature, call->signature.abi, nfixedargs, ntotalargs, call->signature.rtype, (ffi_type **) params); +#else + /* FIXME: test in config.m4; assume we can just call anyway */ + rc = ffi_prep_cif(&signature, call->signature.abi, ntotalargs, + call->signature.rtype, (ffi_type **) params); +#endif ZEND_ASSERT(FFI_OK == rc); ffi_call(&signature, FFI_FN(decl_call->sym), decl_call->rval, ¶ms[ntotalargs + 1]); free(params); -- 2.30.2 From 94a98b74d920f4eefea55c41fa0b047f27aaf854 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 5 Jan 2016 10:22:56 +0100 Subject: [PATCH 09/16] syslog --- config.m4 | 4 +++- m4/stdio.m4 | 18 +++++++++--------- m4/wchar.m4 | 8 ++++++-- psi.d/stdio.psi | 4 ++-- src/context.c | 3 +++ 5 files changed, 23 insertions(+), 14 deletions(-) diff --git a/config.m4 b/config.m4 index cce2aff..e0890da 100644 --- a/config.m4 +++ b/config.m4 @@ -29,6 +29,7 @@ if test "$PHP_PSI" != no; then [sys_types.m4], [sys_uio.m4], [sys_utsname.m4], + [syslog.m4], [time.m4], [wchar.m4]], [ dnl pecl build @@ -59,6 +60,7 @@ if test "$PHP_PSI" != no; then PSI_CHECK_SYS_STAT PSI_CHECK_SYS_UIO PSI_CHECK_SYS_UTSNAME + PSI_CHECK_SYSLOG PSI_CHECK_WCHAR PHP_SUBST(PSI_SHARED_LIBADD) @@ -72,7 +74,7 @@ if test "$PHP_PSI" != no; then AC_DEFINE_UNQUOTED([PSI_REDIRS], [$PSI_REDIRS], [Redirected functions]) AC_DEFINE_UNQUOTED([PSI_DECLS], [$PSI_DECLS], [Predefined functions]) AC_DEFINE_UNQUOTED([PSI_VA_DECLS], [$PSI_VA_DECLS], [Predefined vararg functions]) - + PHP_ADD_INCLUDE($PHP_PSI_SRCDIR/src) PHP_ADD_BUILD_DIR($PHP_PSI_BUILDDIR/src) diff --git a/m4/stdio.m4 b/m4/stdio.m4 index 82aaa1b..7d601f5 100644 --- a/m4/stdio.m4 +++ b/m4/stdio.m4 @@ -71,13 +71,13 @@ AC_DEFUN(PSI_CHECK_STDIO, [ PSI_DECL(FILE *tmpfile, [(void)]) PSI_DECL(char *tmpnam, [(char *s)]) PSI_DECL(int ungetc, [(int c, FILE *stream)]) - - PSI_DECL(int dprintf, [(int fd, char *fmt)], vararg) - PSI_DECL(int fprintf, [(FILE *stream, char *fmt)], vararg) - PSI_DECL(int fscanf, [(FILE *stream, char *fmt)], vararg) - PSI_DECL(int printf, [(char *fmt)], vararg) - PSI_DECL(int scanf, [(char *fmt)], vararg) - PSI_DECL(int snprintf, [(char *str, size_t size, char *fmt)], vararg) - PSI_DECL(int sprintf, [(char *str, char *fmt)], vararg) - PSI_DECL(int sscanf, [(char *str, char *fmt)], vararg) + + PSI_DECL(int dprintf, [(int fd, char *format)], vararg) + PSI_DECL(int fprintf, [(FILE *stream, char *format)], vararg) + PSI_DECL(int fscanf, [(FILE *stream, char *format)], vararg) + PSI_DECL(int printf, [(char *format)], vararg) + PSI_DECL(int scanf, [(char *format)], vararg) + PSI_DECL(int snprintf, [(char *str, size_t size, char *format)], vararg) + PSI_DECL(int sprintf, [(char *str, char *format)], vararg) + PSI_DECL(int sscanf, [(char *str, char *format)], vararg) ]) diff --git a/m4/wchar.m4 b/m4/wchar.m4 index 97a0b9e..ebffee9 100644 --- a/m4/wchar.m4 +++ b/m4/wchar.m4 @@ -1,9 +1,13 @@ AC_DEFUN(PSI_CHECK_WCHAR, [ AC_CHECK_HEADERS(wchar.h) - + PSI_TYPE(wint_t, int) - + PSI_CONST(WINT_MIN, int) PSI_CONST(WINT_MAX, int) PSI_CONST(WEOF, int) + + PSI_DECL(int wprintf, [(wchar_t *format)], vararg) + PSI_DECL(int fwprintf, [(FILE *stream, wchar_t *format)], vararg) + PSI_DECL(int swprintf, [(wchar_t *wcs, size_t maxlen, wchar_t *format)], vararg) ]) diff --git a/psi.d/stdio.psi b/psi.d/stdio.psi index 0741874..685d6c8 100644 --- a/psi.d/stdio.psi +++ b/psi.d/stdio.psi @@ -65,8 +65,8 @@ function psi\rewind(object $stream) : void { return void(rewind); } -//extern int printf(const char *fmt, ...); +//extern int printf(const char *format, ...); function psi\printf(string $fmt, mixed ...$args) : int { - let fmt = strval($fmt); + let format = strval($fmt); return to_int(printf); } diff --git a/src/context.c b/src/context.c index 3b5c734..64fce37 100644 --- a/src/context.c +++ b/src/context.c @@ -77,6 +77,9 @@ #ifdef HAVE_TIME_H # include #endif +#ifdef HAVE_SYSLOG_H +# include +#endif #ifdef HAVE_WCHAR_H # include #endif -- 2.30.2 From 19f0eb5807fb8d0f3aa305f2476f094e66a02709 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 5 Jan 2016 15:53:46 +0100 Subject: [PATCH 10/16] better errors --- php_psi.h | 4 ++- psi.d/stdio.psi | 1 + src/context.c | 79 +++++++++++++++++++++++++++-------------------- src/context.h | 2 +- src/module.c | 19 +++++++++--- src/parser.h | 76 +++++++++++++++++++++++++++++++++++---------- src/parser.re | 16 +--------- src/parser_proc.y | 55 ++++++++++++++++----------------- 8 files changed, 150 insertions(+), 102 deletions(-) diff --git a/php_psi.h b/php_psi.h index f5859e3..31e6565 100644 --- a/php_psi.h +++ b/php_psi.h @@ -20,7 +20,9 @@ extern zend_module_entry psi_module_entry; #include "context.h" -void psi_error(int type, const char *msg, ...); +void psi_error_wrapper(PSI_Token *t, int type, const char *msg, ...); +void psi_error(int type, const char *fn, unsigned ln, const char *msg, ...); +void psi_verror(int type, const char *fn, unsigned ln, const char *msg, va_list argv); static inline int psi_check_env(const char *var) { char *set = getenv(var); diff --git a/psi.d/stdio.psi b/psi.d/stdio.psi index 685d6c8..43987de 100644 --- a/psi.d/stdio.psi +++ b/psi.d/stdio.psi @@ -70,3 +70,4 @@ function psi\printf(string $fmt, mixed ...$args) : int { let format = strval($fmt); return to_int(printf); } + diff --git a/src/context.c b/src/context.c index 64fce37..a75368e 100644 --- a/src/context.c +++ b/src/context.c @@ -212,13 +212,13 @@ static int validate_lib(PSI_Data *data, void **dlopened) { } else if (!strchr(ptr, '/')) { len = snprintf(lib, MAXPATHLEN, "lib%s.%s", ptr, PHP_PSI_SHLIB_SUFFIX); if (MAXPATHLEN == len) { - data->error(PSI_WARNING, "Library name too long: '%s'", ptr); + data->error(NULL, PSI_WARNING, "Library name too long: '%s'", ptr); } lib[len] = 0; ptr = lib; } if (!(*dlopened = dlopen(ptr, RTLD_LAZY|RTLD_LOCAL))) { - data->error(PSI_WARNING, "Could not open library '%s': %s.", + data->error(NULL, PSI_WARNING, "Could not open library '%s': %s.", data->psi.file.ln, dlerror()); return 0; } @@ -284,7 +284,8 @@ static inline int validate_decl_type(PSI_Data *data, decl_type *type) { } static inline int validate_decl_typedef(PSI_Data *data, decl_typedef *def) { if (!validate_decl_type(data, def->type)) { - data->error(PSI_WARNING, "Type '%s' cannot be aliased to %s'%s'", + data->error(def->token, PSI_WARNING, + "Type '%s' cannot be aliased to %s'%s'", def->type->name, def->type->type == PSI_T_STRUCT?"struct ":"",def->alias); return 0; } @@ -299,10 +300,9 @@ static inline int validate_constant(PSI_Data *data, constant *c) { static inline int validate_decl_arg(PSI_Data *data, decl_arg *arg) { if (!validate_decl_type(data, arg->type)) { - data->error(PSI_WARNING, "Cannot use '%s'(%d) as type for decl var '%s'" - " in %s on line %zu at col %zu", - arg->type->name, arg->type->type, arg->var->name, - arg->type->token->file, arg->type->token->line, arg->type->token->col); + data->error(arg->type->token, PSI_WARNING, + "Cannot use '%s'(%d) as type for decl var '%s'", + arg->type->name, arg->type->type, arg->var->name); return 0; } return 1; @@ -367,7 +367,6 @@ static inline int validate_decl_abi(PSI_Data *data, decl_abi *abi) { return 1; } } - data->error(PSI_WARNING, "Invalid calling convention: '%s'", abi->convention); return 0; } static inline int validate_decl_func(PSI_Data *data, void *dl, decl *decl, decl_arg *func) @@ -375,7 +374,7 @@ static inline int validate_decl_func(PSI_Data *data, void *dl, decl *decl, decl_ struct psi_func_redir *redir; if (!strcmp(func->var->name, "dlsym")) { - data->error(PSI_WARNING, "Cannot dlsym dlsym (sic!)"); + data->error(func->token, PSI_WARNING, "Cannot dlsym dlsym (sic!)"); return 0; } @@ -393,7 +392,8 @@ static inline int validate_decl_func(PSI_Data *data, void *dl, decl *decl, decl_ #endif decl->call.sym = dlsym(dl ?: RTLD_NEXT, func->var->name); if (!decl->call.sym) { - data->error(PSI_WARNING, "Failed to locate symbol '%s': %s", + data->error(func->token, PSI_WARNING, + "Failed to locate symbol '%s': %s", func->var->name, dlerror()); } } @@ -402,6 +402,8 @@ static inline int validate_decl_func(PSI_Data *data, void *dl, decl *decl, decl_ static inline int validate_decl(PSI_Data *data, void *dl, decl *decl) { if (!validate_decl_abi(data, decl->abi)) { + data->error(decl->abi->token, PSI_WARNING, + "Invalid calling convention: '%s'", decl->abi->token->text); return 0; } if (!validate_decl_func(data, dl, decl, decl->func)) { @@ -480,14 +482,14 @@ static inline int validate_num_exp(PSI_Data *data, decl_args *dargs, decl_arg *f switch (exp->t) { case PSI_T_NAME: if (!locate_decl_var_arg(exp->u.dvar, dargs, func)) { - data->error(PSI_WARNING, "Unknown variable '%s' in numeric expression", + data->error(exp->token, PSI_WARNING, "Unknown variable '%s' in numeric expression", exp->u.dvar->name); return 0; } return 1; case PSI_T_NSNAME: if (!locate_num_exp_constant(exp, data->consts)) { - data->error(PSI_WARNING, "Unknown constant '%s' in numeric expression", + data->error(exp->token, PSI_WARNING, "Unknown constant '%s' in numeric expression", exp->u.numb); return 0; } @@ -545,14 +547,14 @@ static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg decl_var *set_var = set->vars->vars[0]; if (!validate_set_value_handler(set)) { - data->error(PSI_WARNING, "Invalid cast '%s'", set->func->name); + data->error(set->func->token, PSI_WARNING, "Invalid cast '%s'", set->func->name); return 0; } for (i = 0; i < set->vars->count; ++i) { decl_var *svar = set->vars->vars[i]; if (!svar->arg && !locate_decl_var_arg(svar, ref_list, NULL)) { - data->error(PSI_WARNING, "Unknown variable '%s'", svar->name); + data->error(svar->token, PSI_WARNING, "Unknown variable '%s'", svar->name); return 0; } } @@ -567,7 +569,7 @@ static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg int is_pointer_to_struct = (ref_type->type == PSI_T_STRUCT && ref->var->pointer_level); if (!is_to_array && !is_pointer_to_struct) { - data->error(E_WARNING, "Inner `set` statement casts only work with " + data->error(set->func->token, E_WARNING, "Inner `set` statement casts only work with " "to_array() casts on structs or pointers: %s(%s...", set->func->name, set->vars->vars[0]->name); return 0; } @@ -599,7 +601,7 @@ static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg set->inner[0]->outer.set = set; if (sub_ref) { if (strcmp(sub_var->name, set_var->name)) { - data->error(E_WARNING, "Inner `set` statement casts on pointers must reference the same variable"); + data->error(sub_var->token, E_WARNING, "Inner `set` statement casts on pointers must reference the same variable"); return 0; } if (!validate_set_value_ex(data, set->inner[0], sub_ref, ref_list)) { @@ -607,7 +609,7 @@ static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg } } } else if (set->count > 1) { - data->error(E_WARNING, "Inner `set` statement casts on pointers may only occur once"); + data->error(set->func->token, E_WARNING, "Inner `set` statement casts on pointers may only occur once"); return 0; } @@ -649,11 +651,13 @@ static inline int validate_impl_ret_stmt(PSI_Data *data, impl *impl) { /* and which type cast to apply */ if (impl->stmts->ret.count != 1) { if (impl->stmts->ret.count > 1) { - data->error(PSI_WARNING, "Too many `return` statements for implmentation %s;" + data->error(impl->stmts->ret.list[1]->token, PSI_WARNING, + "Too many `return` statements for implmentation %s;" " found %zu, exactly one is needed", impl->func->name, impl->stmts->ret.count); } else { - data->error(PSI_WARNING, "Missing `return` statement for implementation %s", + data->error(impl->func->token, PSI_WARNING, + "Missing `return` statement for implementation %s", impl->func->name); } return 0; @@ -662,8 +666,9 @@ static inline int validate_impl_ret_stmt(PSI_Data *data, impl *impl) { ret = impl->stmts->ret.list[0]; if (!(impl->decl = locate_impl_decl(data->decls, ret))) { - data->error(PSI_WARNING, "Missing declaration for implementation %s", - impl->func->name); + data->error(ret->token, PSI_WARNING, + "Missing declaration '%s' for `return` statment for implementation %s", + ret->set->vars->vars[0]->name, impl->func->name); return 0; } @@ -693,7 +698,7 @@ static inline int validate_impl_let_stmts(PSI_Data *data, impl *impl) { } if (!locate_decl_var_arg(let_var, impl->decl->args, impl->decl->func)) { - data->error(PSI_WARNING, "Unknown variable '%s' in `let` statement" + data->error(let_var->token, PSI_WARNING, "Unknown variable '%s' in `let` statement" " of implementation '%s'", let_var->name, impl->func->name); return 0; } @@ -740,7 +745,7 @@ static inline int validate_impl_let_stmts(PSI_Data *data, impl *impl) { } } if (!check) { - data->error(PSI_WARNING, "Unknown value '$%s' of `let` statement" + data->error(let->var->token, PSI_WARNING, "Unknown value '$%s' of `let` statement" " for variable '%s' of implementation '%s'", let->val->data.func->var->name, let->var->name, impl->func->name); return 0; @@ -764,7 +769,8 @@ static inline int validate_impl_let_stmts(PSI_Data *data, impl *impl) { } } if (!check) { - data->error(PSI_WARNING, "Missing `let` statement for arg '%s %.*s%s'" + data->error(impl->func->token, PSI_WARNING, + "Missing `let` statement for arg '%s %.*s%s'" " of declaration '%s' for implementation '%s'", darg->type->name, (int) darg->var->pointer_level, "*****", darg->var->name, impl->decl->func->var->name, impl->func->name); @@ -792,7 +798,7 @@ static inline int validate_impl_set_stmts(PSI_Data *data, impl *impl) { } } if (!check) { - data->error(PSI_WARNING, "Unknown variable '$%s' of `set` statement" + data->error(set->var->token, PSI_WARNING, "Unknown variable '$%s' of `set` statement" " of implementation '%s'", set->var->name, impl->func->name); return 0; @@ -835,7 +841,7 @@ static inline int validate_impl_set_stmts(PSI_Data *data, impl *impl) { } if (!check) { - data->error(PSI_WARNING, "Unknown value '%s' of `set` statement" + data->error(set_var->token, PSI_WARNING, "Unknown value '%s' of `set` statement" " for variable '$%s' of implementation '%s'", set_var->name, set->arg->var->name, impl->func->name); return 0; @@ -869,12 +875,15 @@ static inline int validate_impl_free_stmts(PSI_Data *data, impl *impl) { /* first find the decl of the free func */ if (!locate_free_decl(data->decls, free_call)) { - data->error(PSI_WARNING, "Unknown function '%s' in `free` statement" - " of implementation '%s'", free_call->func, impl->func->name); + data->error(free_call->token, PSI_WARNING, + "Missing declaration '%s' in `free` statement" + " of implementation '%s'", + free_call->func, impl->func->name); return 0; } if (!impl->decl->args) { - data->error(PSI_WARNING, "Declaration '%s' of implementation '%s'" + data->error(free_call->token, PSI_WARNING, + "Declaration '%s' of implementation '%s'" " does not have any arguments to free", impl->decl->func->var->name, impl->func->name); } @@ -895,7 +904,8 @@ static inline int validate_impl_free_stmts(PSI_Data *data, impl *impl) { } if (!check) { - data->error(PSI_WARNING, "Unknown variable '%s' of `free` statement" + data->error(free_var->token, PSI_WARNING, + "Unknown variable '%s' of `free` statement" " of implementation '%s'", free_var->name, impl->func->name); return 0; @@ -907,7 +917,8 @@ static inline int validate_impl_free_stmts(PSI_Data *data, impl *impl) { } static inline int validate_impl_stmts(PSI_Data *data, impl *impl) { if (!impl->stmts) { - data->error(PSI_WARNING, "Missing body for implementation %s!", + data->error(impl->func->token, PSI_WARNING, + "Missing body for implementation %s!", impl->func->name); return 0; } @@ -1164,11 +1175,11 @@ void PSI_ContextBuild(PSI_Context *C, const char *paths) PSI_Parser P; if (MAXPATHLEN <= slprintf(psi, MAXPATHLEN, "%s/%s", ptr, entries[i]->d_name)) { - C->error(PSI_WARNING, "Path to PSI file too long: %s/%s", + C->error(NULL, PSI_WARNING, "Path to PSI file too long: %s/%s", ptr, entries[i]->d_name); } if (!PSI_ParserInit(&P, psi, C->error, flags)) { - C->error(PSI_WARNING, "Failed to init PSI parser (%s): %s", + C->error(NULL, PSI_WARNING, "Failed to init PSI parser (%s): %s", psi, strerror(errno)); continue; } @@ -1198,7 +1209,7 @@ void PSI_ContextBuild(PSI_Context *C, const char *paths) if (PSI_ContextCompile(C) && SUCCESS != zend_register_functions(NULL, C->closures, NULL, MODULE_PERSISTENT)) { - C->error(PSI_WARNING, "Failed to register functions!"); + C->error(NULL, PSI_WARNING, "Failed to register functions!"); } free(cpy); diff --git a/src/context.h b/src/context.h index a010eee..c8416a5 100644 --- a/src/context.h +++ b/src/context.h @@ -5,7 +5,7 @@ #define PSI_ERROR 16 #define PSI_WARNING 32 -typedef void (*PSI_ContextErrorFunc)(int type, const char *msg, ...); +typedef void (*PSI_ContextErrorFunc)(PSI_Token *token, int type, const char *msg, ...); typedef struct PSI_Context PSI_Context; typedef struct PSI_ContextOps PSI_ContextOps; diff --git a/src/module.c b/src/module.c index 321ab63..39d1291 100644 --- a/src/module.c +++ b/src/module.c @@ -33,16 +33,25 @@ PHP_INI_END(); static zend_object_handlers psi_object_handlers; static zend_class_entry *psi_class_entry; -void psi_error(int type, const char *msg, ...) +void psi_error_wrapper(PSI_Token *t, int type, const char *msg, ...) { - char buf[0x1000]; va_list argv; va_start(argv, msg); - vslprintf(buf, 0x1000, msg, argv); + psi_verror(type, t?t->file:"Unknown", t?*t->line:0, msg, argv); va_end(argv); +} +void psi_error(int type, const char *fn, unsigned ln, const char *msg, ...) +{ + va_list argv; - php_error(type, buf); + va_start(argv, 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); } size_t psi_t_alignment(token_t t) @@ -1172,7 +1181,7 @@ PHP_MINIT_FUNCTION(psi) return FAILURE; } - PSI_ContextInit(&PSI_G(context), ops, psi_error); + PSI_ContextInit(&PSI_G(context), ops, psi_error_wrapper); PSI_ContextBuild(&PSI_G(context), PSI_G(directory)); if (psi_check_env("PSI_DUMP")) { diff --git a/src/parser.h b/src/parser.h index 014509d..aadb31c 100644 --- a/src/parser.h +++ b/src/parser.h @@ -21,7 +21,7 @@ size_t psi_t_size(token_t); typedef struct PSI_Token { token_t type; - size_t size, line, col; + unsigned size, *line; char *text, *file; char buf[1]; } PSI_Token; @@ -81,6 +81,7 @@ static inline void free_decl_type(decl_type *type) { } typedef struct decl_typedef { + PSI_Token *token; char *alias; decl_type *type; } decl_typedef; @@ -93,6 +94,9 @@ static inline decl_typedef *init_decl_typedef(const char *name, decl_type *type) } static inline void free_decl_typedef(decl_typedef *t) { + if (t->token) { + free(t->token); + } free(t->alias); free_decl_type(t->type); free(t); @@ -123,6 +127,7 @@ static void free_decl_typedefs(decl_typedefs *defs) { } typedef struct decl_var { + PSI_Token *token; char *name; unsigned pointer_level; unsigned array_size; @@ -138,6 +143,9 @@ static inline decl_var *init_decl_var(const char *name, unsigned pl, unsigned as } static inline void free_decl_var(decl_var *var) { + if (var->token) { + free(var->token); + } free(var->name); free(var); } @@ -160,6 +168,7 @@ static inline void free_decl_struct_layout(decl_struct_layout *l) { } typedef struct decl_arg { + PSI_Token *token; decl_type *type; decl_var *var; decl_struct_layout *layout; @@ -171,6 +180,7 @@ typedef struct decl_arg { static inline decl_arg *init_decl_arg(decl_type *type, decl_var *var) { decl_arg *arg = calloc(1, sizeof(*arg)); + arg->token = var->token; arg->type = type; arg->var = var; var->arg = arg; @@ -251,6 +261,7 @@ static inline void free_decl_args(decl_args *args) { } typedef struct decl_abi { + PSI_Token *token; char *convention; } decl_abi; @@ -261,6 +272,9 @@ static inline decl_abi *init_decl_abi(const char *convention) { } static inline void free_decl_abi(decl_abi *abi) { + if (abi->token) { + free(abi->token); + } free(abi->convention); free(abi); } @@ -323,6 +337,7 @@ static inline void free_decls(decls *decls) { } typedef struct decl_struct { + PSI_Token *token; char *name; decl_args *args; size_t size; @@ -336,6 +351,9 @@ static inline decl_struct *init_decl_struct(const char *name, decl_args *args) { } static inline void free_decl_struct(decl_struct *s) { + if (s->token) { + free(s->token); + } if (s->args) { free_decl_args(s->args); } @@ -386,6 +404,7 @@ static inline void free_impl_type(impl_type *type) { } typedef struct impl_var { + PSI_Token *token; char *name; unsigned reference:1; } impl_var; @@ -398,6 +417,9 @@ static inline impl_var *init_impl_var(const char *name, int is_reference) { } static inline void free_impl_var(impl_var *var) { + if (var->token) { + free(var->token); + } free(var->name); free(var); } @@ -550,6 +572,7 @@ static inline void free_impl_args(impl_args *args) { } typedef struct impl_func { + PSI_Token *token; char *name; impl_args *args; impl_type *return_type; @@ -566,6 +589,9 @@ static inline impl_func *init_impl_func(char *name, impl_args *args, impl_type * } static inline void free_impl_func(impl_func *f) { + if (f->token) { + free(f->token); + } free_impl_type(f->return_type); free_impl_args(f->args); free(f->name); @@ -573,6 +599,7 @@ static inline void free_impl_func(impl_func *f) { } typedef struct num_exp { + PSI_Token *token; token_t t; union { char *numb; @@ -600,6 +627,9 @@ static inline num_exp *init_num_exp(token_t t, void *num) { } static inline void free_num_exp(num_exp *exp) { + if (exp->token) { + free(exp->token); + } switch (exp->t) { case PSI_T_NUMBER: free(exp->u.numb); @@ -750,6 +780,7 @@ static inline void free_let_stmt(let_stmt *stmt) { struct set_value; typedef struct set_func { + PSI_Token *token; token_t type; char *name; void (*handler)(zval *, struct set_value *set, impl_val *ret_val); @@ -763,6 +794,9 @@ static inline set_func *init_set_func(token_t type, const char *name) { } static inline void free_set_func(set_func *func) { + if (func->token) { + free(func->token); + } free(func->name); free(func); } @@ -827,6 +861,7 @@ static inline void free_set_stmt(set_stmt *set) { } typedef struct return_stmt { + PSI_Token *token; set_value *set; decl_arg *decl; } return_stmt; @@ -838,13 +873,15 @@ static inline return_stmt *init_return_stmt(set_value *val) { } static inline void free_return_stmt(return_stmt *ret) { - //free_set_func(ret->func); - //free_decl_var(ret->decl); + if (ret->token) { + free(ret->token); + } free_set_value(ret->set); free(ret); } typedef struct free_call { + PSI_Token *token; char *func; decl_vars *vars; decl *decl; @@ -858,6 +895,9 @@ static inline free_call *init_free_call(const char *func, decl_vars *vars) { } static inline void free_free_call(free_call *f) { + if (f->token) { + free(f->token); + } free(f->func); free_decl_vars(f->vars); free(f); @@ -1135,7 +1175,7 @@ static inline impl_val *struct_member_ref(decl_arg *set_arg, impl_val *struct_pt #define PSI_ERROR 16 #define PSI_WARNING 32 -typedef void (*psi_error_cb)(int type, const char *msg, ...); +typedef void (*psi_error_cb)(PSI_Token *token, int type, const char *msg, ...); #define PSI_DATA(D) ((PSI_Data *) (D)) #define PSI_DATA_MEMBERS \ @@ -1184,11 +1224,9 @@ static inline void PSI_DataDtor(PSI_Data *data) { typedef struct PSI_Parser { PSI_DATA_MEMBERS; FILE *fp; - unsigned flags; - unsigned errors; - void *proc; - size_t line, col; token_t num; + void *proc; + unsigned flags, errors, line, col; char *cur, *tok, *lim, *eof, *ctx, *mrk, buf[BSIZE]; } PSI_Parser; @@ -1205,33 +1243,37 @@ static inline PSI_Token *PSI_TokenAlloc(PSI_Parser *P) { token_len = P->cur - P->tok; fname_len = strlen(P->psi.file.fn); - T = calloc(1, sizeof(*T) + token_len + fname_len + 1); + T = calloc(1, sizeof(*T) + token_len + fname_len + sizeof(unsigned) + 2); T->type = token_typ; T->size = token_len; - T->line = P->line; - T->col = P->col; - T->file = &T->buf[0]; - T->text = &T->buf[fname_len + 1]; + T->text = &T->buf[0]; + T->file = &T->buf[token_len + 1]; + T->line = (void *) &T->buf[fname_len + token_len + 2]; - memcpy(T->file, P->psi.file.fn, fname_len); memcpy(T->text, P->tok, token_len); + memcpy(T->file, P->psi.file.fn, fname_len); + memcpy(T->line, &P->line, sizeof(unsigned)); return T; } static inline PSI_Token *PSI_TokenCopy(PSI_Token *src) { size_t fname_len = strlen(src->file); - size_t strct_len = sizeof(*src) + src->size + fname_len + 1; + size_t strct_len = sizeof(*src) + src->size + fname_len + sizeof(unsigned) + 2; PSI_Token *ptr = malloc(strct_len); memcpy(ptr, src, strct_len); - ptr->file = &ptr->buf[0]; - ptr->text = &ptr->buf[fname_len + 1]; + ptr->text = &ptr->buf[0]; + ptr->file = &ptr->buf[ptr->size + 1]; return ptr; } +static inline const char *PSI_TokenLocation(PSI_Token *t) { + return t ? t->file : ":0:0"; +} + #define PSI_PARSER_DEBUG 0x1 PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, psi_error_cb error, unsigned flags); diff --git a/src/parser.re b/src/parser.re index 69e76c8..3375a0b 100644 --- a/src/parser.re +++ b/src/parser.re @@ -47,20 +47,6 @@ PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, psi_error_cb err return P; } -void PSI_ParserSyntaxError(PSI_Parser *P, const char *fn, size_t ln, const char *msg, ...) { - char buf[0x1000] = {0}; - va_list argv; - - va_start(argv, msg); - vsnprintf(buf, 0x1000-1, msg, argv); - va_end(argv); - - P->error(PSI_WARNING, "PSI syntax error on line %zu in '%s'%s%s", - ln, fn, msg ? ": ": "", buf); - - ++P->errors; -} - size_t PSI_ParserFill(PSI_Parser *P, size_t n) { if (P->flags & PSI_PARSER_DEBUG) { @@ -214,7 +200,7 @@ void PSI_ParserFree(PSI_Parser **P) #define RETURN(t) do { \ P->num = t; \ if (P->flags & PSI_PARSER_DEBUG) { \ - fprintf(stderr, "PSI> TOKEN: %d %.*s (EOF=%d %s:%zu:%zu)\n", \ + fprintf(stderr, "PSI> TOKEN: %d %.*s (EOF=%d %s:%u:%u)\n", \ P->num, (int) (P->cur-P->tok), P->tok, P->num == PSI_T_EOF, \ P->psi.file.fn, P->line, P->col); \ } \ diff --git a/src/parser_proc.y b/src/parser_proc.y index d55f7e7..80a0519 100644 --- a/src/parser_proc.y +++ b/src/parser_proc.y @@ -5,6 +5,7 @@ #include "parser.h" +void psi_error(int, const char *, int, const char *, ...); } %name PSI_ParserProc @@ -15,10 +16,11 @@ %extra_argument {PSI_Parser *P} /* TOKEN is defined inside syntax_error */ %syntax_error { + ++P->errors; if (TOKEN && TOKEN->type != PSI_T_EOF) { - PSI_ParserSyntaxError(P, P->psi.file.fn, P->line, "Unexpected token '%s'", TOKEN->text); + psi_error(PSI_WARNING, TOKEN->file, *TOKEN->line, "PSI syntax error: Unexpected token '%s'", TOKEN->text); } else { - PSI_ParserSyntaxError(P, P->psi.file.fn, P->line, "Unexpected end of input"); + psi_error(PSI_WARNING, P->psi.file.fn, P->line, "PSI syntax error: Unexpected end of input"); } } @@ -36,7 +38,7 @@ block ::= EOF. block ::= LIB(T) QUOTED_STRING(libname) EOS. { if (P->psi.file.ln) { - PSI_ParserSyntaxError(P, P->psi.file.ln, T->line, "Extra 'lib %s' statement has no effect", libname->text); + P->error(T, PSI_WARNING, "Extra 'lib %s' statement has no effect", libname->text); } else { P->psi.file.ln = strndup(libname->text + 1, libname->size - 2); } @@ -68,7 +70,7 @@ block ::= decl_struct(strct). { decl_struct(strct) ::= STRUCT NAME(N) struct_size(size_) LBRACE struct_args(args) RBRACE. { strct = init_decl_struct(N->text, args); strct->size = size_; - free(N); + strct->token = N; } %type struct_size {size_t} @@ -98,34 +100,31 @@ constant(constant) ::= CONST const_type(type) NSNAME(T) EQUALS impl_def_val(val) %destructor decl_typedef {free_decl_typedef($$);} decl_typedef(def) ::= TYPEDEF decl_type(type) NAME(ALIAS) EOS. { def = init_decl_typedef(ALIAS->text, type); - free(ALIAS); + def->token = ALIAS; } /* support opaque types */ decl_typedef(def) ::= TYPEDEF VOID(V) NAME(ALIAS) EOS. { def = init_decl_typedef(ALIAS->text, init_decl_type(V->type, V->text)); + def->token = ALIAS; def->type->token = V; - //free(V); - free(ALIAS); } decl_typedef(def) ::= TYPEDEF STRUCT(S) NAME(N) NAME(ALIAS) EOS. { def = init_decl_typedef(ALIAS->text, init_decl_type(S->type, N->text)); + def->token = ALIAS; def->type->token = N; - free(ALIAS); free(S); - //free(N); } decl_typedef(def) ::= TYPEDEF decl_struct(s) NAME(ALIAS) EOS. { def = init_decl_typedef(ALIAS->text, init_decl_type(PSI_T_STRUCT, s->name)); - def->type->token = ALIAS; + def->token = ALIAS; + def->type->token = PSI_TokenCopy(s->token); def->type->strct = s; - //free(ALIAS); } %type decl {decl*} %destructor decl {free_decl($$);} decl(decl) ::= decl_abi(abi) decl_func(func) LPAREN decl_args(args) RPAREN EOS. { decl = init_decl(abi, func, args); - } %type decl_func {decl_arg*} @@ -148,18 +147,18 @@ decl_func(func) ::= VOID(T) NAME(N). { %destructor decl_abi {free_decl_abi($$);} decl_abi(abi) ::= NAME(T). { abi = init_decl_abi(T->text); - free(T); + abi->token = T; } %type decl_var {decl_var*} %destructor decl_var {free_decl_var($$);} decl_var(var) ::= indirection(p) NAME(T). { var = init_decl_var(T->text, p, 0); - free(T); + var->token = T; } decl_var(var) ::= indirection(p) NAME(T) LBRACKET NUMBER(D) RBRACKET. { var = init_decl_var(T->text, p+1, atol(D->text)); - free(T); + var->token = T; free(D); } @@ -184,8 +183,8 @@ decl_arg(arg_) ::= VOID(T) pointers(p) NAME(N). { init_decl_var(N->text, p, 0) ); arg_->type->token = T; - //free(T); - free(N); + arg_->var->token = N; + arg_->token = N; } decl_arg(arg_) ::= CONST VOID(T) pointers(p) NAME(N). { arg_ = init_decl_arg( @@ -193,8 +192,8 @@ decl_arg(arg_) ::= CONST VOID(T) pointers(p) NAME(N). { init_decl_var(N->text, p, 0) ); arg_->type->token = T; - //free(T); - free(N); + arg_->var->token = N; + arg_->token = N; } %type decl_args {decl_args*} @@ -243,7 +242,6 @@ struct_layout(layout) ::= COLON COLON LPAREN NUMBER(POS) COMMA NUMBER(SIZ) RPARE decl_type(type_) ::= decl_type_token(T). { type_ = init_decl_type(T->type, T->text); type_->token = T; - //free(T); } /* unsigned, urgh */ decl_type(type_) ::= UNSIGNED NAME(T). { @@ -254,20 +252,17 @@ decl_type(type_) ::= UNSIGNED NAME(T). { memcpy(type_->name, "unsigned", sizeof("unsigned")-1); type_->name[sizeof("unsigned")] = ' '; type_->name[T->size + sizeof("unsigned")] = 0; - //free(T); } /* we have to support plain int here because we have it in our lexer rules */ decl_type(type_) ::= INT(T). { type_ = init_decl_type(PSI_T_NAME, T->text); type_->token = T; - //free(T); } /* structs ! */ decl_type(type_) ::= STRUCT(S) NAME(T). { type_ = init_decl_type(S->type, T->text); type_->token = T; free(S); - //free(T); } %type const_decl_type {decl_type*} @@ -289,7 +284,7 @@ impl(impl) ::= impl_func(func) LBRACE impl_stmts(stmts) RBRACE. { %destructor impl_func {free_impl_func($$);} impl_func(func) ::= FUNCTION reference(r) NSNAME(NAME) impl_args(args) COLON impl_type(type). { func = init_impl_func(NAME->text, args, type, r); - free(NAME); + func->token = NAME; } %token_class impl_def_val_token NULL NUMBER TRUE FALSE QUOTED_STRING. @@ -304,7 +299,7 @@ impl_def_val(def) ::= impl_def_val_token(T). { %destructor impl_var {free_impl_var($$);} impl_var(var) ::= reference(r) DOLLAR NAME(T). { var = init_impl_var(T->text, r); - free(T); + var->token = T; } %type impl_arg {impl_arg*} @@ -375,10 +370,11 @@ impl_stmt(stmt) ::= free_stmt(free). { %destructor num_exp {free_num_exp($$);} num_exp(exp) ::= num_exp_token(tok). { exp = init_num_exp(tok->type, tok->text); - free(tok); + exp->token = tok; } num_exp(exp) ::= decl_var(var). { exp = init_num_exp(PSI_T_NAME, var); + exp->token = PSI_TokenCopy(var->token); } num_exp(exp) ::= num_exp(exp_) num_exp_op_token(operator_) num_exp(operand_). { exp_->operator = operator_->type; @@ -469,13 +465,14 @@ set_vals(vals) ::= set_vals(vals_) COMMA set_value(val). { %destructor set_func {free_set_func($$);} set_func(func) ::= set_func_token(T). { func = init_set_func(T->type, T->text); - free(T); + func->token = T; } %type return_stmt {return_stmt*} %destructor return_stmt {free_return_stmt($$);} -return_stmt(ret) ::= RETURN set_value(val) EOS. { +return_stmt(ret) ::= RETURN(T) set_value(val) EOS. { ret = init_return_stmt(val); + ret->token = T; } %type free_stmt {free_stmt*} @@ -497,7 +494,7 @@ free_calls(calls) ::= free_calls(calls_) COMMA free_call(call). { %destructor free_call {free_free_call($$);} free_call(call) ::= NAME(F) LPAREN decl_vars(vars) RPAREN. { call = init_free_call(F->text, vars); - free(F); + call->token = F; } %token_class impl_type_token VOID MIXED BOOL INT FLOAT STRING ARRAY OBJECT. -- 2.30.2 From 0d05258e368d32f04371734a45759ea9ac2f5a7a Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 5 Jan 2016 18:31:29 +0100 Subject: [PATCH 11/16] flush --- config.m4 | 2 ++ m4/netdb.m4 | 94 +++++++++++++++++++++++++++++++++++++++++++++++++ psi.d/netdb.psi | 38 ++++++++++++++++++++ src/context.c | 1 + 4 files changed, 135 insertions(+) create mode 100644 m4/netdb.m4 create mode 100644 psi.d/netdb.psi diff --git a/config.m4 b/config.m4 index e0890da..bfa56e5 100644 --- a/config.m4 +++ b/config.m4 @@ -29,6 +29,7 @@ if test "$PHP_PSI" != no; then [sys_types.m4], [sys_uio.m4], [sys_utsname.m4], + [netdb.m4], [syslog.m4], [time.m4], [wchar.m4]], [ @@ -60,6 +61,7 @@ if test "$PHP_PSI" != no; then PSI_CHECK_SYS_STAT PSI_CHECK_SYS_UIO PSI_CHECK_SYS_UTSNAME + PSI_CHECK_NETDB PSI_CHECK_SYSLOG PSI_CHECK_WCHAR diff --git a/m4/netdb.m4 b/m4/netdb.m4 new file mode 100644 index 0000000..4043210 --- /dev/null +++ b/m4/netdb.m4 @@ -0,0 +1,94 @@ +AC_DEFUN(PSI_CHECK_NETDB, [ + AC_CHECK_HEADERS(netdb.h) + + PSI_STRUCT(struct hostent, [ + char *h_name, + char **h_aliases, + int h_addrtype, + int h_length, + char **h_addr_list] + ) + + PSI_STRUCT(struct netent, [ + char *n_name, + char **n_aliases, + int n_addrtype, + uint32_t n_net] + ) + + PSI_STRUCT(struct protoent, [ + char *p_name, + char **p_aliases, + int p_proto] + ) + + PSI_STRUCT(struct servent, [ + char *s_name, + char **s_aliases, + int s_port, + char *s_proto] + ) + + PSI_CONST(IPPORT_RESERVED, int) + + PSI_STRUCT(struct addrinfo, [ + int ai_flags, + int ai_family, + int ai_socktype, + int ai_protocol, + socklen_t ai_addrlen, + struct sockaddr *ai_addr, + char *ai_canonname, + struct addrinfo *ai_next] + ) + + PSI_CONST(AI_PASSIVE, int) + PSI_CONST(AI_CANONNAME, int) + PSI_CONST(AI_NUMERICHOST, int) + PSI_CONST(AI_NUMERICSERV, int) + PSI_CONST(AI_V4MAPPED, int) + PSI_CONST(AI_ALL, int) + PSI_CONST(AI_ADDRCONFIG, int) + + PSI_CONST(NI_NOFQDN, int) + PSI_CONST(NI_NUMERICHOST, int) + PSI_CONST(NI_NAMEREQD, int) + PSI_CONST(NI_NUMERICSERV, int) + PSI_CONST(NI_NUMERICSCOPE, int) + PSI_CONST(NI_DGRAM, int) + + PSI_CONST(EAI_AGAIN, int) + PSI_CONST(EAI_BADFLAGS, int) + PSI_CONST(EAI_FAIL, int) + PSI_CONST(EAI_FAMILY, int) + PSI_CONST(EAI_MEMORY, int) + PSI_CONST(EAI_NONAME, int) + PSI_CONST(EAI_SERVICE, int) + PSI_CONST(EAI_SOCKTYPE, int) + PSI_CONST(EAI_SYSTEM, int) + PSI_CONST(EAI_OVERFLOW, int) + + PSI_DECL(void endhostent, [(void)]) + PSI_DECL(void endnetent, [(void)]) + PSI_DECL(void endprotoent, [(void)]) + PSI_DECL(void endservent, [(void)]) + PSI_DECL(void freeaddrinfo, [(struct addrinfo *res)]) + PSI_DECL(char *gai_strerror, [(int errcode)]) + PSI_DECL(int getaddrinfo, [(char *node, char *service, struct addrinfo *hints, struct addrinfo **res)]) + PSI_DECL(struct hostent *gethostent, [(void)]) + PSI_DECL(int getnameinfo, [(struct sockaddr *sa, socklen_t salen, char *host, socklen_t host_len, char *serv, socklen_t servlen, int flags)]) + PSI_DECL(struct netent *getnetbyaddr, [(uint32_t net, int type)]) + PSI_DECL(struct netent *getnetbyname, [(char *name)]) + PSI_DECL(struct netent *getnetent, [(void)]) + PSI_DECL(struct protoent *getprotobyname, [(char *name)]) + PSI_DECL(struct protoent *getprotobynumber, [(int proto)]) + PSI_DECL(struct protoent *getprotoent, [(void)]) + PSI_DECL(struct servent *getservbyname, [(char *name, char *proto)]) + PSI_DECL(struct servent *getservbyport, [(int port, char *proto)]) + PSI_DECL(struct servent *getservent, [(void)]) + PSI_DECL(void sethostent, [(int stayopen)]) + PSI_DECL(void setnetent, [(int stayopen)]) + PSI_DECL(void setprotoent, [(int stayopen)]) + PSI_DECL(void setservent, [(int stayopen)]) + +]) \ No newline at end of file diff --git a/psi.d/netdb.psi b/psi.d/netdb.psi new file mode 100644 index 0000000..8186a7d --- /dev/null +++ b/psi.d/netdb.psi @@ -0,0 +1,38 @@ +function psi\endhostent() : void { + return void(endhostent); +} +function psi\endnetend() : void { + return void(endnetent); +} +function psi\endprotoent() : void { + return void(endprotoent); +} +function psi\endservent() : void { + return void(endservent); +} + +function psi\gai_strerror(int $errcode) : string { + let errcode = intval($errcode); + return to_string(gai_strerror); +} + +function psi\getaddrinfo(string $node, string $service, array $hints, object &$res = NULL) : int { + let node = strval($node); + let service = strval($service); + let hints = arrval($hints); + let res = &NULL; + return to_int(getaddrinfo); + set $res = to_array(*res, + to_int(ai_flags), + to_int(ai_family), + to_int(ai_socktype), + to_int(ai_protocol), + to_int(ai_addrlen), + to_array(ai_addr, + to_int(sa_family), + to_string(sa_data, ai_addrlen) + ), + to_string(ai_canonname) + // FIXME ai_next + ); +} \ No newline at end of file diff --git a/src/context.c b/src/context.c index a75368e..3d20920 100644 --- a/src/context.c +++ b/src/context.c @@ -356,6 +356,7 @@ static const char * const abi_ccs[] = { "default", /* \ */ "extern", /* > - all the same */ "cdecl", /* / */ + "mscdecl", "stdcall", "fastcall", }; -- 2.30.2 From c2dc24a4967dd767fc4a240f93ca0de4600a8c62 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Thu, 7 Jan 2016 10:34:38 +0100 Subject: [PATCH 12/16] flush --- php_psi.h | 1 + psi.d/netdb.psi | 9 +++------ src/context.c | 26 ++++++++++++++++++++------ src/module.c | 19 ++++++++++++------- src/parser.h | 9 +++++++-- src/parser_proc.y | 5 +++++ 6 files changed, 48 insertions(+), 21 deletions(-) diff --git a/php_psi.h b/php_psi.h index 31e6565..8bac826 100644 --- a/php_psi.h +++ b/php_psi.h @@ -55,6 +55,7 @@ void psi_to_bool(zval *return_value, set_value *set, impl_val *ret_val); void psi_to_int(zval *return_value, set_value *set, impl_val *ret_val); void psi_to_double(zval *return_value, set_value *set, impl_val *ret_val); void psi_to_string(zval *return_value, set_value *set, impl_val *ret_val); +void psi_to_recursive(zval *return_value, set_value *set, impl_val *r_val); void psi_to_array(zval *return_value, set_value *set, impl_val *ret_val); void psi_to_object(zval *return_value, set_value *set, impl_val *ret_val); diff --git a/psi.d/netdb.psi b/psi.d/netdb.psi index 8186a7d..df34547 100644 --- a/psi.d/netdb.psi +++ b/psi.d/netdb.psi @@ -28,11 +28,8 @@ function psi\getaddrinfo(string $node, string $service, array $hints, object &$r to_int(ai_socktype), to_int(ai_protocol), to_int(ai_addrlen), - to_array(ai_addr, - to_int(sa_family), - to_string(sa_data, ai_addrlen) - ), - to_string(ai_canonname) - // FIXME ai_next + to_string(ai_addr, ai_addrlen), + to_string(ai_canonname), + to_array(ai_next, ...) ); } \ No newline at end of file diff --git a/src/context.c b/src/context.c index 3d20920..ee79c8f 100644 --- a/src/context.c +++ b/src/context.c @@ -524,6 +524,12 @@ static inline int validate_set_value_handler(set_value *set) { case PSI_T_VOID: set->func->handler = psi_to_void; break; + case PSI_T_ELLIPSIS: + if (set->outer.set && set->outer.set->func->type == PSI_T_TO_ARRAY) { + set->func->handler = psi_to_recursive; + break; + } + /* no break */ default: return 0; } @@ -548,14 +554,14 @@ static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg decl_var *set_var = set->vars->vars[0]; if (!validate_set_value_handler(set)) { - data->error(set->func->token, PSI_WARNING, "Invalid cast '%s'", set->func->name); + data->error(set->func->token, PSI_WARNING, "Invalid cast '%s' in `set` statement", set->func->name); return 0; } for (i = 0; i < set->vars->count; ++i) { decl_var *svar = set->vars->vars[i]; if (!svar->arg && !locate_decl_var_arg(svar, ref_list, NULL)) { - data->error(svar->token, PSI_WARNING, "Unknown variable '%s'", svar->name); + data->error(svar->token, PSI_WARNING, "Unknown variable '%s' in `set` statement", svar->name); return 0; } } @@ -587,7 +593,6 @@ static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg decl_var *sub_var = set->inner[i]->vars->vars[0]; decl_arg *sub_ref = locate_struct_member(ref_type->strct, sub_var); - set->inner[i]->outer.set = set; if (sub_ref) { if (!validate_set_value_ex(data, set->inner[i], sub_ref, ref_type->strct->args)) { return 0; @@ -599,7 +604,6 @@ static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg decl_var *sub_var = set->inner[0]->vars->vars[0]; decl_arg *sub_ref = locate_decl_var_arg(sub_var, ref_list, ref); - set->inner[0]->outer.set = set; if (sub_ref) { if (strcmp(sub_var->name, set_var->name)) { data->error(sub_var->token, E_WARNING, "Inner `set` statement casts on pointers must reference the same variable"); @@ -1312,14 +1316,20 @@ static inline void dump_num_exp(int fd, num_exp *exp) { exp = exp->operand; } } + static inline void dump_impl_set_value(int fd, set_value *set, unsigned level) { - size_t i; + size_t i, j; if (level > 1) { /* only if not directly after `set ...` */ dump_level(fd, level); } - dprintf(fd, "%s(", set->func->name); + + if (set->func->type == PSI_T_ELLIPSIS) { + dprintf(fd, "%s(", set->outer.set->func->name); + } else { + dprintf(fd, "%s(", set->func->name); + } for (i = 0; i < set->vars->count; ++i) { decl_var *svar = set->vars->vars[i]; @@ -1328,6 +1338,10 @@ static inline void dump_impl_set_value(int fd, set_value *set, unsigned level) { } dump_decl_var(fd, svar); } + + if (set->func->type == PSI_T_ELLIPSIS) { + dprintf(fd, ", ..."); + } if (set->num) { dprintf(fd, ", "); dump_num_exp(fd, set->num); diff --git a/src/module.c b/src/module.c index 39d1291..607015d 100644 --- a/src/module.c +++ b/src/module.c @@ -297,6 +297,13 @@ void psi_to_string(zval *return_value, set_value *set, impl_val *ret_val) token_t t = real_decl_type(var->arg->type)->type; switch (t) { + case PSI_T_FLOAT: + RETVAL_DOUBLE((double) deref_impl_val(ret_val, var)->fval); + break; + case PSI_T_DOUBLE: + RETVAL_DOUBLE(deref_impl_val(ret_val, var)->dval); + break; + default: case PSI_T_VOID: case PSI_T_INT8: case PSI_T_UINT8: @@ -315,13 +322,6 @@ void psi_to_string(zval *return_value, set_value *set, impl_val *ret_val) } } return; - case PSI_T_FLOAT: - RETVAL_DOUBLE((double) deref_impl_val(ret_val, var)->fval); - break; - case PSI_T_DOUBLE: - RETVAL_DOUBLE(deref_impl_val(ret_val, var)->dval); - break; - default: psi_to_int(return_value, set, ret_val); break; } @@ -386,6 +386,11 @@ void *psi_array_to_struct(decl_struct *s, HashTable *arr) return mem; } +void psi_to_recursive(zval *return_value, set_value *set, impl_val *r_val) +{ + set->outer.set->func->handler(return_value, set->outer.set, r_val->ptr); +} + void psi_to_array(zval *return_value, set_value *set, impl_val *r_val) { size_t i; diff --git a/src/parser.h b/src/parser.h index aadb31c..2ea0ec8 100644 --- a/src/parser.h +++ b/src/parser.h @@ -822,12 +822,17 @@ static inline set_value *init_set_value(set_func *func, decl_vars *vars) { static inline set_value *add_inner_set_value(set_value *val, set_value *inner) { val->inner = realloc(val->inner, ++val->count * sizeof(*val->inner)); val->inner[val->count-1] = inner; + inner->outer.set = val; return val; } static inline void free_set_value(set_value *val) { - free_set_func(val->func); - free_decl_vars(val->vars); + if (val->func) { + free_set_func(val->func); + } + if (val->vars) { + free_decl_vars(val->vars); + } if (val->inner) { size_t i; for (i = 0; i < val->count; ++i) { diff --git a/src/parser_proc.y b/src/parser_proc.y index 80a0519..5713c85 100644 --- a/src/parser_proc.y +++ b/src/parser_proc.y @@ -440,6 +440,11 @@ set_value(val) ::= set_func(func) LPAREN decl_var(var) COMMA num_exp(num_) RPARE val = init_set_value(func, init_decl_vars(var)); val->num = num_; } +set_value(val) ::= set_func(func_) LPAREN decl_var(var) COMMA ELLIPSIS(T) RPAREN. { + free_set_func(func_); + val = init_set_value(init_set_func(T->type, T->text), init_decl_vars(var)); + val->func->token = T; +} set_value(val) ::= set_func(func_) LPAREN decl_var(var) COMMA set_vals(vals) RPAREN. { val = vals; val->func = func_; -- 2.30.2 From 5c82e8c40c87314d9bd93c42d36f194413eae619 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Thu, 7 Jan 2016 10:36:44 +0100 Subject: [PATCH 13/16] fix leak --- psi.d/netdb.psi | 1 + 1 file changed, 1 insertion(+) diff --git a/psi.d/netdb.psi b/psi.d/netdb.psi index df34547..0820c20 100644 --- a/psi.d/netdb.psi +++ b/psi.d/netdb.psi @@ -32,4 +32,5 @@ function psi\getaddrinfo(string $node, string $service, array $hints, object &$r to_string(ai_canonname), to_array(ai_next, ...) ); + free freeaddrinfo(res); } \ No newline at end of file -- 2.30.2 From cfebc76ed7426836f21296cca9a14b422bfa04cf Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 12 Jan 2016 13:15:48 +0100 Subject: [PATCH 14/16] flush --- m4/sys_socket.m4 | 1 + psi.d/glob.psi | 2 +- psi.d/netdb.psi | 32 ++++++++++++++++-- psi.d/stdio.psi | 2 +- psi.d/time.psi | 2 +- psi.d/uname.psi | 2 +- src/context.c | 52 ++++++++++++++++++----------- src/module.c | 70 +++++++++++++++++++++++++++------------ src/parser.h | 39 ++++++++++++++++------ tests/iconv/iconv001.phpt | 6 ++-- 10 files changed, 145 insertions(+), 63 deletions(-) diff --git a/m4/sys_socket.m4 b/m4/sys_socket.m4 index 331bd16..3d403cd 100644 --- a/m4/sys_socket.m4 +++ b/m4/sys_socket.m4 @@ -31,6 +31,7 @@ AC_DEFUN(PSI_CHECK_SYS_SOCKET, [ ) PSI_CONST(AF_INET, int) + PSI_CONST(AF_INET6, int) PSI_CONST(AF_UNIX, int) PSI_CONST(AF_UNSPEC, int) PSI_CONST(MSG_CTRUNC, int) diff --git a/psi.d/glob.psi b/psi.d/glob.psi index 02d1c3d..ce6f5a7 100644 --- a/psi.d/glob.psi +++ b/psi.d/glob.psi @@ -9,7 +9,7 @@ function psi\glob(string $pattern, int $flags, array &$glob = NULL) : int { to_int(gl_pathc), to_int(gl_offs), to_int(gl_flags), - to_array(**gl_pathv, gl_pathc + gl_offs, to_string(*gl_pathv)) + to_array(gl_pathv, gl_pathc + gl_offs, to_string(gl_pathv)) ); free globfree(buf); } diff --git a/psi.d/netdb.psi b/psi.d/netdb.psi index 0820c20..dd81ed8 100644 --- a/psi.d/netdb.psi +++ b/psi.d/netdb.psi @@ -11,18 +11,46 @@ function psi\endservent() : void { return void(endservent); } +function psi\sethostent(bool $stayopen) : void { + let stayopen = intval($stayopen); + return void(sethostent); +} +function psi\setnetset(bool $stayopen) : void { + let stayopen = intval($stayopen); + return void(setnetent); +} +function psi\setprotoent(bool $stayopen) : void { + let stayopen = intval($stayopen); + return void(setprotoent); +} +function psi\setservent(bool $stayopen) : void { + let stayopen = intval($stayopen); + return void(setservent); +} + +function psi\gethostent() : array { + return to_array(gethostent, + to_string(h_name), + to_array(h_aliases, to_string(h_aliases)), + to_int(h_addrtype), + to_int(h_length), + to_array(h_addr_list, to_string(h_addr_list, h_length)) + ); +} + function psi\gai_strerror(int $errcode) : string { let errcode = intval($errcode); return to_string(gai_strerror); } +// extern int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res); function psi\getaddrinfo(string $node, string $service, array $hints, object &$res = NULL) : int { let node = strval($node); let service = strval($service); let hints = arrval($hints); let res = &NULL; return to_int(getaddrinfo); - set $res = to_array(*res, + set $res = to_array(**res, to_int(ai_flags), to_int(ai_family), to_int(ai_socktype), @@ -30,7 +58,7 @@ function psi\getaddrinfo(string $node, string $service, array $hints, object &$r to_int(ai_addrlen), to_string(ai_addr, ai_addrlen), to_string(ai_canonname), - to_array(ai_next, ...) + to_array(*ai_next, ...) ); free freeaddrinfo(res); } \ No newline at end of file diff --git a/psi.d/stdio.psi b/psi.d/stdio.psi index 43987de..6909354 100644 --- a/psi.d/stdio.psi +++ b/psi.d/stdio.psi @@ -2,7 +2,7 @@ function psi\fopen(string $path, string $mode) : object { let path = pathval($path); let mode = strval($mode); - return to_object(*fopen); + return to_object(fopen); } // extern int fclose(FILE *stream); diff --git a/psi.d/time.psi b/psi.d/time.psi index ae16b0a..ff81e93 100644 --- a/psi.d/time.psi +++ b/psi.d/time.psi @@ -77,7 +77,7 @@ function psi\nanosleep(array $rq = NULL, array &$rm = NULL) : int { function psi\times(array &$tms = NULL) : int { let buf = calloc(1, psi\SIZEOF_STRUCT_TMS); return to_int(times); - set $tms = to_array(*buf, + set $tms = to_array(buf, to_int(tms_utime), to_int(tms_stime), to_int(tms_cutime), diff --git a/psi.d/uname.psi b/psi.d/uname.psi index 6c6a6b0..b7aed96 100644 --- a/psi.d/uname.psi +++ b/psi.d/uname.psi @@ -8,4 +8,4 @@ function psi\uname(array &$u = NULL) : int { to_string(version), to_string(machine), to_string(domainname)); -} \ No newline at end of file +} diff --git a/src/context.c b/src/context.c index ee79c8f..c3f1cb1 100644 --- a/src/context.c +++ b/src/context.c @@ -151,6 +151,12 @@ static struct psi_predef_const { PSI_MACROS +struct utsname *uname2() { + struct utsname *u = calloc(1, sizeof(*u)); + uname(u); + return u; +} + int psi_glob(const char *pattern, int flags, int (*errfunc) (const char *epath, int eerrno), glob_t *pglob) { @@ -169,6 +175,7 @@ static struct psi_func_redir { void (*func)(void); } psi_func_redirs[] = { {"glob", (void (*)(void)) psi_glob}, + {"uname2", (void (*)(void)) uname2}, PSI_REDIRS {0} }; @@ -527,6 +534,8 @@ static inline int validate_set_value_handler(set_value *set) { case PSI_T_ELLIPSIS: if (set->outer.set && set->outer.set->func->type == PSI_T_TO_ARRAY) { set->func->handler = psi_to_recursive; + set->inner = set->outer.set->inner; + set->count = set->outer.set->count; break; } /* no break */ @@ -589,13 +598,15 @@ static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg if (ref_type->type == PSI_T_STRUCT) { /* to_array(struct, to_...) */ - for (i = 0; i < set->count; ++i) { - decl_var *sub_var = set->inner[i]->vars->vars[0]; - decl_arg *sub_ref = locate_struct_member(ref_type->strct, sub_var); - - if (sub_ref) { - if (!validate_set_value_ex(data, set->inner[i], sub_ref, ref_type->strct->args)) { - return 0; + if (!set->outer.set || set->outer.set->inner != set->inner) { + for (i = 0; i < set->count; ++i) { + decl_var *sub_var = set->inner[i]->vars->vars[0]; + decl_arg *sub_ref = locate_struct_member(ref_type->strct, sub_var); + + if (sub_ref) { + if (!validate_set_value_ex(data, set->inner[i], sub_ref, ref_type->strct->args)) { + return 0; + } } } } @@ -886,25 +897,26 @@ static inline int validate_impl_free_stmts(PSI_Data *data, impl *impl) { free_call->func, impl->func->name); return 0; } - if (!impl->decl->args) { - data->error(free_call->token, PSI_WARNING, - "Declaration '%s' of implementation '%s'" - " does not have any arguments to free", - impl->decl->func->var->name, impl->func->name); - } + + /* now check for known vars */ for (l = 0; l < free_call->vars->count; ++l) { int check = 0; decl_var *free_var = free_call->vars->vars[l]; - for (k = 0; k < impl->decl->args->count; ++k) { - decl_arg *free_arg = impl->decl->args->args[k]; + if (!strcmp(free_var->name, impl->decl->func->var->name)) { + check = 1; + free_var->arg = impl->decl->func; + } else if (impl->decl->args) { + for (k = 0; k < impl->decl->args->count; ++k) { + decl_arg *free_arg = impl->decl->args->args[k]; - if (!strcmp(free_var->name, free_arg->var->name)) { - check = 1; - free_var->arg = free_arg; - break; + if (!strcmp(free_var->name, free_arg->var->name)) { + check = 1; + free_var->arg = free_arg; + break; + } } } @@ -1318,7 +1330,7 @@ static inline void dump_num_exp(int fd, num_exp *exp) { } static inline void dump_impl_set_value(int fd, set_value *set, unsigned level) { - size_t i, j; + size_t i; if (level > 1) { /* only if not directly after `set ...` */ diff --git a/src/module.c b/src/module.c index 607015d..152c949 100644 --- a/src/module.c +++ b/src/module.c @@ -293,6 +293,7 @@ void psi_to_double(zval *return_value, set_value *set, impl_val *ret_val) void psi_to_string(zval *return_value, set_value *set, impl_val *ret_val) { + char *str; decl_var *var = set->vars->vars[0]; token_t t = real_decl_type(var->arg->type)->type; @@ -304,26 +305,27 @@ void psi_to_string(zval *return_value, set_value *set, impl_val *ret_val) RETVAL_DOUBLE(deref_impl_val(ret_val, var)->dval); break; default: - case PSI_T_VOID: - case PSI_T_INT8: - case PSI_T_UINT8: if (!var->arg->var->pointer_level) { RETVAL_STRINGL(&ret_val->cval, 1); } else { ret_val = deref_impl_val(ret_val, var); - if (ret_val && ret_val->ptr) { + if (var->arg->var->array_size) { + str = (char *) ret_val; + } else { + str = ret_val->ptr; + } + if (str) { if (set->num) { - RETVAL_STRINGL(ret_val->ptr, psi_long_num_exp(set->num, set->outer.val)); + zend_long n = psi_long_num_exp(set->num, set->outer.val); + RETVAL_STRINGL(str, n); } else { - RETVAL_STRING(ret_val->ptr); + RETVAL_STRING(str); } } else { RETVAL_EMPTY_STRING(); } } return; - psi_to_int(return_value, set, ret_val); - break; } convert_to_string(return_value); } @@ -332,7 +334,7 @@ void psi_to_string(zval *return_value, set_value *set, impl_val *ret_val) static impl_val *iterate(impl_val *val, size_t size, unsigned i, impl_val *tmp) { memset(tmp, 0, sizeof(*tmp)); - memcpy(tmp, ((void*) val->ptr) + size * i, size); + memcpy(tmp, ((void*) val) + size * i, size); return tmp; } @@ -388,7 +390,7 @@ void *psi_array_to_struct(decl_struct *s, HashTable *arr) void psi_to_recursive(zval *return_value, set_value *set, impl_val *r_val) { - set->outer.set->func->handler(return_value, set->outer.set, r_val->ptr); + set->outer.set->func->handler(return_value, set, r_val); } void psi_to_array(zval *return_value, set_value *set, impl_val *r_val) @@ -398,7 +400,7 @@ void psi_to_array(zval *return_value, set_value *set, impl_val *r_val) token_t t = real_decl_type(var->arg->type)->type; impl_val tmp, *ret_val = deref_impl_val(r_val, var); - if ((intptr_t) ret_val->ptr <= (intptr_t) 0) { + if ((intptr_t) ret_val <= (intptr_t) 0) { RETURN_NULL(); } @@ -413,13 +415,13 @@ void psi_to_array(zval *return_value, set_value *set, impl_val *r_val) set_value *sub_set = set->inner[i]; decl_var *sub_var = sub_set->vars->vars[0]; - sub_set->outer.val = r_val; + sub_set->outer.val = ret_val; if (sub_var->arg) { impl_val *tmp = NULL, *val; zval ztmp; - val = deref_impl_val(struct_member_ref(sub_var->arg, ret_val, &tmp), sub_var); + val = struct_member_ref(sub_var->arg, ret_val, &tmp); sub_set->func->handler(&ztmp, sub_set, val); add_assoc_zval(return_value, sub_var->name, &ztmp); @@ -455,20 +457,32 @@ void psi_to_array(zval *return_value, set_value *set, impl_val *r_val) } return; } else if (set->num) { - /* to_array(arr_var, num_expr, to_int(*arr_var)) - */ + /* to_array(arr_var, num_expr, to_int(*arr_var)) */ zval ele; + char *ptr; zend_long i, n = psi_long_num_exp(set->num, set->outer.val); + size_t size = psi_t_size(var->arg->var->pointer_level ? PSI_T_POINTER : t); + set_value *sub_set = set->inner[0]; + sub_set->outer.val = set->outer.val; for (i = 0; i < n; ++i) { - size_t size = psi_t_size(var->arg->var->pointer_level ? PSI_T_POINTER : t); - impl_val *ptr = iterate(ret_val, size, i, &tmp); - - set->inner[0]->func->handler(&ele, set->inner[0], ptr); + ptr = (char *) ret_val->ptr + i * size; + sub_set->func->handler(&ele, sub_set, (void *) ptr); add_next_index_zval(return_value, &ele); } } else { - ZEND_ASSERT(0); + /* to_array(arr_var, to_int(*arr_var)) */ + zval ele; + char *ptr = ret_val->ptr; + size_t size = psi_t_size(var->arg->var->pointer_level ? PSI_T_POINTER : t); + set_value *sub_set = set->inner[0]; + + sub_set->outer.val = set->outer.val; + while (*(void **) ptr) { + sub_set->func->handler(&ele, sub_set, (void *) ptr); + add_next_index_zval(return_value, &ele); + ptr += size; + } } } @@ -588,6 +602,9 @@ static inline void *psi_do_calloc(let_calloc *alloc) zend_long n = psi_long_num_exp(alloc->nmemb, NULL), s = psi_long_num_exp(alloc->size, NULL); void *mem = safe_emalloc(n, s, sizeof(void *)); memset(mem, 0, n * s + sizeof(void *)); +#if 0 + fprintf(stderr, "calloc: %p\n", mem); +#endif return mem; } @@ -681,7 +698,12 @@ static inline void *psi_do_let(let_stmt *let) switch (let->val ? let->val->kind : PSI_LET_NULL) { case PSI_LET_TMP: - arg_val->ptr = deref_impl_val(let->val->data.var->arg->val.ptr, let->var); + memcpy(arg_val, deref_impl_val(let->val->data.var->arg->let->ptr, let->val->data.var), sizeof(*arg_val)); +#if 0 + fprintf(stderr, "LET TMP: %p -> %p\n", + let->val->data.var->arg->let->ptr, + arg_val->ptr); +#endif break; case PSI_LET_NULL: if (darg->var->array_size) { @@ -715,8 +737,10 @@ static inline void *psi_do_let(let_stmt *let) static inline void psi_do_set(zval *return_value, set_value *set) { + decl_arg *set_arg = set->vars->vars[0]->arg; + zval_dtor(return_value); - set->func->handler(return_value, set, set->vars->vars[0]->arg->ptr); + set->func->handler(return_value, set, set_arg->let ? set_arg->let->ptr : set_arg->ptr); } static inline void psi_do_return(zval *return_value, return_stmt *ret) @@ -830,6 +854,8 @@ static inline int psi_calc_num_exp_value(num_exp *exp, impl_val *strct, impl_val case PSI_T_NAME: if (strct) { ref = struct_member_ref(exp->u.dvar->arg, strct, &tmp); + } else if (exp->u.dvar->arg->let) { + ref = exp->u.dvar->arg->let->ptr; } else { ref = exp->u.dvar->arg->ptr; } diff --git a/src/parser.h b/src/parser.h index 2ea0ec8..5129097 100644 --- a/src/parser.h +++ b/src/parser.h @@ -833,7 +833,7 @@ static inline void free_set_value(set_value *val) { if (val->vars) { free_decl_vars(val->vars); } - if (val->inner) { + if (val->inner && (!val->outer.set || val->outer.set->inner != val->inner)) { size_t i; for (i = 0; i < val->count; ++i) { free_set_value(val->inner[i]); @@ -1145,7 +1145,16 @@ static inline void add_decl_lib(decl_libs *libs, void *dlopened) { static inline impl_val *deref_impl_val(impl_val *ret_val, decl_var *var) { unsigned i; - if (var->arg->var != var) for (i = 1; i < var->pointer_level; ++i) { + ZEND_ASSERT(var->arg->var != var); +#if 0 + fprintf(stderr, "deref: %s pl=%u:%u as=%u:%u %p\n", + var->name, var->pointer_level, var->arg->var->pointer_level, + var->array_size, var->arg->var->array_size, ret_val); +#endif + for (i = 0; i < var->pointer_level; ++i) { +#if 0 + fprintf(stderr, "-- %p %p %p\n", ret_val, *(void**)ret_val, ret_val->ptr); +#endif ret_val = *(void **) ret_val; } return ret_val; @@ -1155,11 +1164,21 @@ static inline impl_val *enref_impl_val(void *ptr, decl_var *var) { impl_val *val, *val_ptr; unsigned i; + ZEND_ASSERT(var->arg->var == var); +#if 0 + fprintf(stderr, "enref: %s pl=%u:%u as=%u:%u\n", + var->name, var->pointer_level, var->arg->var->pointer_level, + var->array_size, var->arg->var->array_size); +#endif if (!var->pointer_level && real_decl_type(var->arg->type)->type != PSI_T_STRUCT) { return ptr; } + val = val_ptr = calloc(var->pointer_level + 1, sizeof(void *)); - for (i = 1; i < var->pointer_level; ++i) { + for (i = !var->arg->var->array_size; i < var->pointer_level; ++i) { +#if 0 + fprintf(stderr, "++\n"); +#endif val_ptr->ptr = (void **) val_ptr + 1; val_ptr = val_ptr->ptr; } @@ -1168,16 +1187,14 @@ static inline impl_val *enref_impl_val(void *ptr, decl_var *var) { } static inline impl_val *struct_member_ref(decl_arg *set_arg, impl_val *struct_ptr, impl_val **to_free) { - void *ptr = (char *) struct_ptr->ptr + set_arg->layout->pos; - impl_val *val = enref_impl_val(ptr, set_arg->var); - - if (val != ptr) { - *to_free = val; - } - - return val; + void *ptr = (char *) struct_ptr + set_arg->layout->pos; +#if 0 + fprintf(stderr, "struct member %s: %p\n", set_arg->var->name, ptr); +#endif + return ptr; } + #define PSI_ERROR 16 #define PSI_WARNING 32 typedef void (*psi_error_cb)(PSI_Token *token, int type, const char *msg, ...); diff --git a/tests/iconv/iconv001.phpt b/tests/iconv/iconv001.phpt index 6227c2a..779ee60 100644 --- a/tests/iconv/iconv001.phpt +++ b/tests/iconv/iconv001.phpt @@ -14,15 +14,13 @@ psi.directory={PWD}/../../psi.d:{PWD} $cd = psi\iconv_open("latin1", "utf8"); $in = "ß"; $rc = psi\iconv($cd, $in, $tr); -var_dump($tr === "\xdf"); -var_dump($in === ""); +if ($tr !== "\xdf") var_dump($tr); +if ($in !== "") var_dump($in); var_dump(psi\iconv_close($cd)); ?> ===DONE=== --EXPECT-- ===TEST=== -bool(true) -bool(true) int(0) ===DONE=== -- 2.30.2 From 7ecbe886921997a9ea3c990071c2efb97f13ac21 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 12 Jan 2016 15:38:14 +0100 Subject: [PATCH 15/16] flush --- m4/netdb.m4 | 5 ++++- psi.d/netdb.psi | 18 ++++++++++++++++-- src/context.c | 29 ++++++++++++++++++++++++++++- src/module.c | 33 +++++++++++++++++++++------------ tests/netdb/gai001.phpt | 38 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 107 insertions(+), 16 deletions(-) create mode 100644 tests/netdb/gai001.phpt diff --git a/m4/netdb.m4 b/m4/netdb.m4 index 4043210..b14b54f 100644 --- a/m4/netdb.m4 +++ b/m4/netdb.m4 @@ -57,6 +57,9 @@ AC_DEFUN(PSI_CHECK_NETDB, [ PSI_CONST(NI_NUMERICSCOPE, int) PSI_CONST(NI_DGRAM, int) + PSI_CONST(NI_MAXHOST, int) + PSI_CONST(NI_MAXSERV, int) + PSI_CONST(EAI_AGAIN, int) PSI_CONST(EAI_BADFLAGS, int) PSI_CONST(EAI_FAIL, int) @@ -76,7 +79,7 @@ AC_DEFUN(PSI_CHECK_NETDB, [ PSI_DECL(char *gai_strerror, [(int errcode)]) PSI_DECL(int getaddrinfo, [(char *node, char *service, struct addrinfo *hints, struct addrinfo **res)]) PSI_DECL(struct hostent *gethostent, [(void)]) - PSI_DECL(int getnameinfo, [(struct sockaddr *sa, socklen_t salen, char *host, socklen_t host_len, char *serv, socklen_t servlen, int flags)]) + PSI_DECL(int getnameinfo, [(struct sockaddr *sa, socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags)]) PSI_DECL(struct netent *getnetbyaddr, [(uint32_t net, int type)]) PSI_DECL(struct netent *getnetbyname, [(char *name)]) PSI_DECL(struct netent *getnetent, [(void)]) diff --git a/psi.d/netdb.psi b/psi.d/netdb.psi index dd81ed8..259fcec 100644 --- a/psi.d/netdb.psi +++ b/psi.d/netdb.psi @@ -43,7 +43,7 @@ function psi\gai_strerror(int $errcode) : string { return to_string(gai_strerror); } -// extern int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res); +// extern int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) function psi\getaddrinfo(string $node, string $service, array $hints, object &$res = NULL) : int { let node = strval($node); let service = strval($service); @@ -61,4 +61,18 @@ function psi\getaddrinfo(string $node, string $service, array $hints, object &$r to_array(*ai_next, ...) ); free freeaddrinfo(res); -} \ No newline at end of file +} + +// extern int getnameinfo(struct sockaddr *sa, socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags) +function psi\getnameinfo(string $addr, string &$host = NULL, string &$service = NULL, int $flags = 0) : int { + let sa = strval($addr); + let salen = strlen($addr); + let hostlen = psi\NI_MAXHOST; + let host = calloc(hostlen, psi\SIZEOF_CHAR); + let servlen = psi\NI_MAXSERV; + let serv = calloc(servlen, psi\SIZEOF_CHAR); + let flags = intval($flags); + return to_int(getnameinfo); + set $host = to_string(host); + set $service = to_string(serv); +} diff --git a/src/context.c b/src/context.c index c3f1cb1..4a4f472 100644 --- a/src/context.c +++ b/src/context.c @@ -957,6 +957,33 @@ static inline int validate_impl_stmts(PSI_Data *data, impl *impl) { return 1; } +static inline int validate_impl_args(PSI_Data *data, impl *impl) { + int def = 0; + size_t i; + + for (i = 0; i < impl->func->args->count; ++i) { + impl_arg *iarg = impl->func->args->args[i]; + + if (iarg->def) { + def = 1; + } else if (def) { + data->error(impl->func->token, PSI_WARNING, + "Non-optional argument %zu '$%s' of implementation '%s'" + " follows optional argument", + i+1, iarg->var->name, impl->func->name); + return 0; + } + } + + return 1; +} +static inline int validate_impl(PSI_Data *data, impl *impl) { + if (!validate_impl_args(data, impl)) { + return 0; + } + return validate_impl_stmts(data, impl); +} + PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErrorFunc error) { size_t i; @@ -1153,7 +1180,7 @@ int PSI_ContextValidate(PSI_Context *C, PSI_Parser *P) size_t i; for (i = 0; i < D->impls->count; ++i) { - if (validate_impl_stmts(PSI_DATA(C), D->impls->list[i])) { + if (validate_impl(PSI_DATA(C), D->impls->list[i])) { C->impls = add_impl(C->impls, D->impls->list[i]); } } diff --git a/src/module.c b/src/module.c index 152c949..2257a0d 100644 --- a/src/module.c +++ b/src/module.c @@ -144,6 +144,7 @@ zend_internal_arg_info *psi_internal_arginfo(impl *impl) zend_internal_arg_info *ai = &aip[impl->func->args->count]; ai->name = vararg->var->name; + ai->allow_null = 1; ai->type_hint = psi_internal_type(vararg->type); if (vararg->var->reference) { ai->pass_by_reference = 1; @@ -160,9 +161,9 @@ zend_internal_arg_info *psi_internal_arginfo(impl *impl) if (iarg->var->reference) { ai->pass_by_reference = 1; } - if (iarg->var->reference || (iarg->def && iarg->def->type == PSI_T_NULL)) { + //if (iarg->var->reference || (iarg->def && iarg->def->type == PSI_T_NULL)) { ai->allow_null = 1; - } + //} } return aip; @@ -636,7 +637,7 @@ static inline ZEND_RESULT_CODE psi_let_val(token_t let_func, impl_arg *iarg, imp case PSI_T_STRVAL: if (iarg->type->type == PSI_T_STRING) { if (iarg->val.zend.str) { - arg_val->ptr = estrdup(iarg->val.zend.str->val); + arg_val->ptr = estrndup(iarg->val.zend.str->val, iarg->val.zend.str->len); *to_free = arg_val->ptr; } else { arg_val->ptr = ""; @@ -767,6 +768,22 @@ static inline void psi_do_free(free_stmt *fre) } } +static inline void psi_clean_array_struct(decl_arg *darg) { + if (darg->let + && darg->let->val->kind == PSI_LET_FUNC + && darg->let->val->data.func->type == PSI_T_ARRVAL) { + decl_type *type = real_decl_type(darg->type); + + if (type->type == PSI_T_STRUCT) { + void **ptr = (void **) ((char *) darg->mem + type->strct->size); + + while (*ptr) { + efree(*ptr++); + } + } + } +} + static inline void psi_do_clean(impl *impl) { size_t i; @@ -787,15 +804,7 @@ static inline void psi_do_clean(impl *impl) decl_arg *darg = impl->decl->args->args[i]; if (darg->mem) { - decl_type *type = real_decl_type(darg->type); - - if (type->type == PSI_T_STRUCT) { - void **ptr = (void **) ((char *) darg->mem + type->strct->size); - - while (*ptr) { - efree(*ptr++); - } - } + psi_clean_array_struct(darg); efree(darg->mem); darg->mem = NULL; } diff --git a/tests/netdb/gai001.phpt b/tests/netdb/gai001.phpt new file mode 100644 index 0000000..42e83fc --- /dev/null +++ b/tests/netdb/gai001.phpt @@ -0,0 +1,38 @@ +--TEST-- +getaddrinfo +--INI-- +psi.directory={PWD}:{PWD}/../../psi.d +--SKIPIF-- + +--FILE-- +===TEST=== + +===DONE=== +--EXPECT-- +===TEST=== +int(0) +string(12) "78.46.223.30" +string(1) "0" +int(0) +string(12) "78.46.223.30" +string(1) "0" +int(0) +string(12) "78.46.223.30" +string(1) "0" +===DONE=== \ No newline at end of file -- 2.30.2 From b1720af16e5d7765e2effcd16e23f351c2f82e54 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Thu, 14 Jan 2016 12:20:13 +0100 Subject: [PATCH 16/16] avoid busting bash's stack with a too big if body in configure --- config.m4 | 73 ++++++++++++++++---------------- m4/errno.m4 | 8 ++-- m4/glob.m4 | 4 +- m4/netdb.m4 | 27 ++++++------ m4/psi.m4 | 72 ++++++++++++++++++++++++++++---- m4/psi_const.m4 | 4 +- m4/psi_decl.m4 | 8 ++-- m4/psi_macro.m4 | 2 +- m4/psi_struct.m4 | 4 +- m4/psi_type.m4 | 40 +++++++++--------- m4/stddef.m4 | 4 +- m4/stdint.m4 | 4 +- m4/stdio.m4 | 4 +- m4/stdlib.m4 | 7 ++-- m4/sys_select.m4 | 12 +++--- m4/sys_socket.m4 | 15 ++++--- m4/sys_stat.m4 | 4 +- m4/sys_time.m4 | 4 +- m4/sys_times.m4 | 8 ++-- m4/sys_types.m4 | 4 +- m4/sys_uio.m4 | 8 ++-- m4/sys_utsname.m4 | 8 ++-- m4/syslog.m4 | 42 +++++++++++++++++++ m4/time.m4 | 4 +- m4/wchar.m4 | 92 ++++++++++++++++++++++++++++++++++++++--- psi.d/syslog.psi | 28 +++++++++++++ src/context.c | 11 ++++- tests/netdb/gai001.phpt | 20 ++++----- 28 files changed, 366 insertions(+), 155 deletions(-) create mode 100644 m4/syslog.m4 create mode 100644 psi.d/syslog.psi diff --git a/config.m4 b/config.m4 index bfa56e5..641b16a 100644 --- a/config.m4 +++ b/config.m4 @@ -1,43 +1,44 @@ PHP_ARG_ENABLE(psi, whether to enable PHP System Interface support, [ --enable-psi Enable PHP System Interface support]) +PHP_PSI_SRCDIR=PHP_EXT_SRCDIR(psi) +PHP_PSI_BUILDDIR=PHP_EXT_BUILDDIR(psi) + +m4_foreach(incfile, [ + [ax_check_sign.m4], + [psi.m4], + [psi_type.m4], + [psi_const.m4], + [psi_decl.m4], + [psi_macro.m4], + [psi_struct.m4], + [errno.m4], + [glob.m4], + [stddef.m4], + [stdio.m4], + [stdint.m4], + [stdlib.m4], + [sys_select.m4], + [sys_socket.m4], + [sys_stat.m4], + [sys_time.m4], + [sys_times.m4], + [sys_types.m4], + [sys_uio.m4], + [sys_utsname.m4], + [netdb.m4], + [syslog.m4], + [time.m4], + [wchar.m4]], [ + dnl pecl build + sinclude([m4/]incfile) + dnl php-src build + sinclude([ext/psi/m4/]incfile) +]) + if test "$PHP_PSI" != no; then PHP_CONFIGURE_PART(Configuring PSI) - PHP_PSI_SRCDIR=PHP_EXT_SRCDIR(psi) - PHP_PSI_BUILDDIR=PHP_EXT_BUILDDIR(psi) - - m4_foreach(incfile, [ - [ax_check_sign.m4], - [psi.m4], - [psi_type.m4], - [psi_const.m4], - [psi_decl.m4], - [psi_macro.m4], - [psi_struct.m4], - [errno.m4], - [glob.m4], - [stddef.m4], - [stdio.m4], - [stdint.m4], - [stdlib.m4], - [sys_select.m4], - [sys_socket.m4], - [sys_stat.m4], - [sys_time.m4], - [sys_times.m4], - [sys_types.m4], - [sys_uio.m4], - [sys_utsname.m4], - [netdb.m4], - [syslog.m4], - [time.m4], - [wchar.m4]], [ - dnl pecl build - sinclude([m4/]incfile) - dnl php-src build - sinclude([ext/psi/m4/]incfile) - ]) PSI_LEMON PSI_CHECK_LIBJIT PSI_CHECK_LIBFFI @@ -45,6 +46,7 @@ if test "$PHP_PSI" != no; then AC_FUNC_FNMATCH AC_HEADER_DIRENT + PSI_CONFIG_INIT PSI_CHECK_STD_TYPES PSI_CHECK_STDINT PSI_CHECK_STDDEF @@ -64,6 +66,7 @@ if test "$PHP_PSI" != no; then PSI_CHECK_NETDB PSI_CHECK_SYSLOG PSI_CHECK_WCHAR + PSI_CONFIG_DONE PHP_SUBST(PSI_SHARED_LIBADD) @@ -77,7 +80,6 @@ if test "$PHP_PSI" != no; then AC_DEFINE_UNQUOTED([PSI_DECLS], [$PSI_DECLS], [Predefined functions]) AC_DEFINE_UNQUOTED([PSI_VA_DECLS], [$PSI_VA_DECLS], [Predefined vararg functions]) - PHP_ADD_INCLUDE($PHP_PSI_SRCDIR/src) PHP_ADD_BUILD_DIR($PHP_PSI_BUILDDIR/src) @@ -95,6 +97,5 @@ if test "$PHP_PSI" != no; then PHP_SUBST(PHP_PSI_BUILDDIR) PHP_ADD_MAKEFILE_FRAGMENT - AC_MSG_RESULT() fi diff --git a/m4/errno.m4 b/m4/errno.m4 index 99311b7..be6f996 100644 --- a/m4/errno.m4 +++ b/m4/errno.m4 @@ -1,8 +1,8 @@ -AC_DEFUN(PSI_CHECK_ERRNO, [ +PSI_CHECK_ERRNO() { AC_CHECK_HEADERS(errno.h) - + PSI_EXTVAR(int errno) - + PSI_CONST(E2BIG, int) PSI_CONST(EACCES, int) PSI_CONST(EADDRINUSE, int) @@ -84,4 +84,4 @@ AC_DEFUN(PSI_CHECK_ERRNO, [ PSI_CONST(ETXTBSY, int) PSI_CONST(EWOULDBLOCK, int) PSI_CONST(EXDEV, int) -]) +} diff --git a/m4/glob.m4 b/m4/glob.m4 index fbb036e..343b372 100644 --- a/m4/glob.m4 +++ b/m4/glob.m4 @@ -1,4 +1,4 @@ -AC_DEFUN(PSI_CHECK_GLOB, [ +PSI_CHECK_GLOB() { AC_CHECK_HEADERS(glob.h) PSI_STRUCT(glob_t, [ size_t gl_pathc, @@ -26,4 +26,4 @@ AC_DEFUN(PSI_CHECK_GLOB, [ PSI_CONST(GLOB_ABORTED, int) PSI_CONST(GLOB_NOMATCH, int) PSI_CONST(GLOB_NOSPACE, int) -]) +} diff --git a/m4/netdb.m4 b/m4/netdb.m4 index b14b54f..5049a53 100644 --- a/m4/netdb.m4 +++ b/m4/netdb.m4 @@ -1,6 +1,6 @@ -AC_DEFUN(PSI_CHECK_NETDB, [ +PSI_CHECK_NETDB() { AC_CHECK_HEADERS(netdb.h) - + PSI_STRUCT(struct hostent, [ char *h_name, char **h_aliases, @@ -8,29 +8,29 @@ AC_DEFUN(PSI_CHECK_NETDB, [ int h_length, char **h_addr_list] ) - + PSI_STRUCT(struct netent, [ char *n_name, char **n_aliases, int n_addrtype, uint32_t n_net] ) - + PSI_STRUCT(struct protoent, [ char *p_name, char **p_aliases, int p_proto] ) - + PSI_STRUCT(struct servent, [ char *s_name, char **s_aliases, int s_port, char *s_proto] ) - + PSI_CONST(IPPORT_RESERVED, int) - + PSI_STRUCT(struct addrinfo, [ int ai_flags, int ai_family, @@ -41,7 +41,7 @@ AC_DEFUN(PSI_CHECK_NETDB, [ char *ai_canonname, struct addrinfo *ai_next] ) - + PSI_CONST(AI_PASSIVE, int) PSI_CONST(AI_CANONNAME, int) PSI_CONST(AI_NUMERICHOST, int) @@ -49,17 +49,17 @@ AC_DEFUN(PSI_CHECK_NETDB, [ PSI_CONST(AI_V4MAPPED, int) PSI_CONST(AI_ALL, int) PSI_CONST(AI_ADDRCONFIG, int) - + PSI_CONST(NI_NOFQDN, int) PSI_CONST(NI_NUMERICHOST, int) PSI_CONST(NI_NAMEREQD, int) PSI_CONST(NI_NUMERICSERV, int) PSI_CONST(NI_NUMERICSCOPE, int) PSI_CONST(NI_DGRAM, int) - + PSI_CONST(NI_MAXHOST, int) PSI_CONST(NI_MAXSERV, int) - + PSI_CONST(EAI_AGAIN, int) PSI_CONST(EAI_BADFLAGS, int) PSI_CONST(EAI_FAIL, int) @@ -70,7 +70,7 @@ AC_DEFUN(PSI_CHECK_NETDB, [ PSI_CONST(EAI_SOCKTYPE, int) PSI_CONST(EAI_SYSTEM, int) PSI_CONST(EAI_OVERFLOW, int) - + PSI_DECL(void endhostent, [(void)]) PSI_DECL(void endnetent, [(void)]) PSI_DECL(void endprotoent, [(void)]) @@ -93,5 +93,4 @@ AC_DEFUN(PSI_CHECK_NETDB, [ PSI_DECL(void setnetent, [(int stayopen)]) PSI_DECL(void setprotoent, [(int stayopen)]) PSI_DECL(void setservent, [(int stayopen)]) - -]) \ No newline at end of file +} diff --git a/m4/psi.m4 b/m4/psi.m4 index eecfa61..81aca28 100644 --- a/m4/psi.m4 +++ b/m4/psi.m4 @@ -1,10 +1,68 @@ -PSI_TYPES= -PSI_STRUCTS= -PSI_CONSTS= -PSI_REDIRS= -PSI_MACROS= -PSI_DECLS= -PSI_VA_DECLS= +PSI_TYPES=$PHP_PSI_SRCDIR/php_psi_types.h +PSI_STRUCTS=$PHP_PSI_SRCDIR/php_psi_structs.h +PSI_CONSTS=$PHP_PSI_SRCDIR/php_psi_consts.h +PSI_REDIRS=$PHP_PSI_SRCDIR/php_psi_redirs.h +PSI_MACROS=$PHP_PSI_SRCDIR/php_psi_macros.h +PSI_DECLS=$PHP_PSI_SRCDIR/php_psi_decls.h +PSI_VA_DECLS=$PHP_PSI_SRCDIR/php_psi_va_decls.h + +AC_DEFUN(PSI_CONFIG_INIT, [ + cat >$PSI_TYPES <@ = { +EOF + cat >$PSI_STRUCTS <@ = { +EOF + cat >$PSI_CONSTS <@ = { +EOF + cat >$PSI_REDIRS <@ = { +EOF + cat >$PSI_MACROS $PSI_DECLS <@ = { +EOF + cat >$PSI_VA_DECLS <@ = { +EOF +]) + +AC_DEFUN(PSI_CONFIG_DONE, [ + for i in $PSI_TYPES $PSI_STRUCTS $PSI_CONSTS $PSI_REDIRS $PSI_DECLS $PSI_VA_DECLS; do + cat >>$i <>$PSI_CONSTS <<<" {PSI_T_STRING, \"string\", \"psi\\\\$1\", $2, PSI_T_QUOTED_STRING}, " } # add_int_const(name, value) add_int_const() { - PSI_CONSTS="{PSI_T_INT, \"int\", \"psi\\\\$1\", \"$2\", PSI_T_NUMBER}, $PSI_CONSTS" + cat >>$PSI_CONSTS <<<" {PSI_T_INT, \"int\", \"psi\\\\$1\", \"$2\", PSI_T_NUMBER}, " } dnl PSI_CONST(const name, type) AC_DEFUN(PSI_CONST, [ diff --git a/m4/psi_decl.m4 b/m4/psi_decl.m4 index 69f8edb..c331bbe 100644 --- a/m4/psi_decl.m4 +++ b/m4/psi_decl.m4 @@ -1,5 +1,5 @@ AC_DEFUN(PSI_REDIR, [psi_symbol=ifelse([$2],[],[$1],[$2]) - PSI_REDIRS="{\"$1\", (void(*)(void))$psi_symbol}, $PSI_REDIRS"]) + cat >>$PSI_REDIRS <<<" {\"$1\", (void(*)(void))$psi_symbol}, "]) AC_DEFUN(PSI_FUNC_LIBC_MAIN, [ AC_REQUIRE([AC_PROG_NM]) @@ -61,14 +61,14 @@ AC_DEFUN(PSI_DECL, [ [m4_map_args_sep([PSI_DECL_ARG(m4_normalize(], [))], [], m4_bregexp([$2], [(\(.*\))], [\1]))]) PSI_FUNC(PSI_VAR_NAME($1), [ ifelse([$3], vararg, [ - PSI_VA_DECLS="$psi_decl_args, {0}, $PSI_VA_DECLS" + cat >>$PSI_VA_DECLS <<<" $psi_decl_args, {0}, " ], [ - PSI_DECLS="$psi_decl_args, {0}, $PSI_DECLS" + cat >>$PSI_DECLS <<<" $psi_decl_args, {0}, " ]) ], [ PSI_MACRO($1, $2, [ ifelse([$3], vararg, AC_MSG_ERROR(varargs macro support is not implemented),[]) - PSI_DECLS="$psi_decl_args, {0}, $PSI_DECLS" + cat >>$PSI_DECLS <<<" $psi_decl_args, {0}, " ]) ]) ]) diff --git a/m4/psi_macro.m4 b/m4/psi_macro.m4 index 0ce6f84..0bae220 100644 --- a/m4/psi_macro.m4 +++ b/m4/psi_macro.m4 @@ -28,7 +28,7 @@ AC_DEFUN(PSI_MACRO, [ macro_body="return $macro_name$macro_call;" ]) psi_macro="$macro_type psi_macro_$macro_name$macro_decl { $macro_body }" - PSI_MACROS="$PSI_MACROS $psi_macro" + cat >>$PSI_MACROS <<<"$psi_macro" PSI_REDIR($macro_name, psi_macro_$macro_name) ], [], PSI_INCLUDES) ]) diff --git a/m4/psi_struct.m4 b/m4/psi_struct.m4 index 430baf7..ce04f3d 100644 --- a/m4/psi_struct.m4 +++ b/m4/psi_struct.m4 @@ -17,8 +17,8 @@ AC_DEFUN(PSI_STRUCT, [ psi_struct_name=m4_bregexp([$1], [^\(struct \)?\(\w+\)], [\2]) psi_struct_members="{PSI_T_STRUCT, \"struct\", \"$psi_struct_name\", 0, $AS_TR_SH([ac_cv_sizeof_]$1), 0, 0}" ifelse([$2],,,[m4_map_args_sep([PSI_STRUCT_MEMBER($1, m4_normalize(], [))], [], $2)]) - PSI_STRUCTS="$psi_struct_members, {0}, $PSI_STRUCTS" + cat >>$PSI_STRUCTS <<<" $psi_struct_members, {0}, " if test "$1" = "$psi_struct_name"; then - PSI_TYPES="{PSI_T_STRUCT, \"$1\", \"$1\"}, $PSI_TYPES" + cat >>$PSI_TYPES <<<" {PSI_T_STRUCT, \"$1\", \"$1\"}, " fi ]) diff --git a/m4/psi_type.m4 b/m4/psi_type.m4 index 3b0a22e..70a9ab1 100644 --- a/m4/psi_type.m4 +++ b/m4/psi_type.m4 @@ -7,7 +7,7 @@ psi_type_pair() { local psi_type_upper=`tr a-z A-Z <<<$psi_type_name` local psi_type_bits=`expr $2 \* 8` echo "PSI_T_${psi_type_upper}${psi_type_bits}, \"${psi_type_lower}${psi_type_bits}_t\"" - eval AS_TR_SH([psi_standard_type_]$1)="${psi_type_lower}${psi_type_bits}_t" + #eval AS_TR_SH([psi_standard_type_]$1)="${psi_type_lower}${psi_type_bits}_t" ;; struct*) echo "PSI_T_STRUCT, \"$2\"" @@ -30,7 +30,7 @@ AC_DEFUN(PSI_TYPE, [ int) AX_CHECK_SIGN($1, :, [ psi_basic_type=uint - ], $psi_header) + ], PSI_INCLUDES) ;; sint) psi_basic_type=int @@ -38,7 +38,7 @@ AC_DEFUN(PSI_TYPE, [ esac if test "$2" && test "$AS_TR_SH([ac_cv_sizeof_]$1)" -gt 0; then AS_TR_SH(psi_basic_type_$1)=$psi_basic_type - PSI_TYPES="{`psi_type_pair $psi_basic_type $AS_TR_SH([ac_cv_sizeof_]$1)`, \"$1\"}, $PSI_TYPES" + cat >>$PSI_TYPES <<<" {`psi_type_pair $psi_basic_type $AS_TR_SH([ac_cv_sizeof_]$1)`, \"$1\"}, " fi ]) @@ -58,32 +58,32 @@ AC_DEFUN(PSI_TYPE_BITS, [`expr 8 \* $AS_TR_SH([ac_cv_sizeof_]$1)`]) dnl PSI_TYPE_INDIRECTION(type, size, pointer_level_var, array_size_var) AC_DEFUN(PSI_TYPE_INDIRECTION, [ - AC_MSG_CHECKING(indirection of $1) - m4_define([pointer_level], m4_len(m4_bpatsubst([PSI_VAR_TYPE($1)], [[^*]]))) - m4_define([array_size], [m4_bregexp([PSI_VAR_TYPE($1)], [@<:@\([0-9]+\)@:>@], [\1])]) - - ifelse(array_size.$2,0., [ + dnl AC_MSG_CHECKING(indirection of $1) + m4_define([psi_pointer_level], m4_len(m4_bpatsubst([PSI_VAR_TYPE($1)], [[^*]]))) + m4_define([psi_array_size], [m4_bregexp([PSI_VAR_TYPE($1)], [@<:@\([0-9]+\)@:>@], [\1])]) + + ifelse(psi_array_size.$2,0., [ AC_MSG_ERROR([cannot compute dynamic array size of a non-struct member]) ], [ - ifelse(pointer_level,0,[ - m4_define([type_size],[$]AS_TR_SH([ac_cv_sizeof_]m4_bregexp(PSI_VAR_TYPE([$1]), [^\( \|\w\)+], [\&]))) + ifelse(psi_pointer_level,0,[ + m4_define([psi_type_size],[$]AS_TR_SH([ac_cv_sizeof_]m4_bregexp(PSI_VAR_TYPE([$1]), [^\( \|\w\)+], [\&]))) ],[ - m4_define([type_size],$ac_cv_sizeof_void_p) + m4_define([psi_type_size],$ac_cv_sizeof_void_p) ]) ]) - - m4_case(array_size,,[ - $3=pointer_level + + m4_case(psi_array_size,,[ + $3=psi_pointer_level $4=0] ,0,[ - $3=m4_incr(pointer_level) - $4="`expr $2 / type_size`" + $3=m4_incr(psi_pointer_level) + $4="`expr $2 / psi_type_size`" ], [ - $3=m4_incr(pointer_level) - $4=array_size + $3=m4_incr(psi_pointer_level) + $4=psi_array_size ]) - - AC_MSG_RESULT([[$]$3, [$]$4]) + + dnl AC_MSG_RESULT([[$]$3, [$]$4]) ]) AC_DEFUN(PSI_TYPE_PAIR, [m4_case(m4_bregexp([$1], [^\w+], [\&]), diff --git a/m4/stddef.m4 b/m4/stddef.m4 index 7c99d6c..b6ee82e 100644 --- a/m4/stddef.m4 +++ b/m4/stddef.m4 @@ -1,4 +1,4 @@ -AC_DEFUN(PSI_CHECK_STDDEF, [ +PSI_CHECK_STDDEF() { AC_CHECK_HEADERS(stddef.h) PSI_TYPE(ptrdiff_t, int) PSI_CONST(PTRDIFF_MIN, int) @@ -8,4 +8,4 @@ AC_DEFUN(PSI_CHECK_STDDEF, [ PSI_TYPE(wchar_t, int) PSI_CONST(WCHAR_MIN, int) PSI_CONST(WCHAR_MAX, int) -]) +} diff --git a/m4/stdint.m4 b/m4/stdint.m4 index 65afe65..045279d 100644 --- a/m4/stdint.m4 +++ b/m4/stdint.m4 @@ -1,4 +1,4 @@ -AC_DEFUN(PSI_CHECK_STDINT, [ +PSI_CHECK_STDINT() { AC_CHECK_HEADERS(stdint.h) PSI_TYPE(int_least8_t, int) @@ -67,4 +67,4 @@ AC_DEFUN(PSI_CHECK_STDINT, [ PSI_CONST(INTMAX_MIN, int) PSI_CONST(INTMAX_MAX, int) PSI_CONST(UINTMAX_MAX, int) -]) +} diff --git a/m4/stdio.m4 b/m4/stdio.m4 index 7d601f5..2f079c1 100644 --- a/m4/stdio.m4 +++ b/m4/stdio.m4 @@ -1,4 +1,4 @@ -AC_DEFUN(PSI_CHECK_STDIO, [ +PSI_CHECK_STDIO() { AC_CHECK_HEADER(stdio.h) PSI_STRUCT(FILE) @@ -80,4 +80,4 @@ AC_DEFUN(PSI_CHECK_STDIO, [ PSI_DECL(int snprintf, [(char *str, size_t size, char *format)], vararg) PSI_DECL(int sprintf, [(char *str, char *format)], vararg) PSI_DECL(int sscanf, [(char *str, char *format)], vararg) -]) +} diff --git a/m4/stdlib.m4 b/m4/stdlib.m4 index e521d43..48dbfc9 100644 --- a/m4/stdlib.m4 +++ b/m4/stdlib.m4 @@ -1,6 +1,6 @@ -AC_DEFUN(PSI_CHECK_STDLIB, [ +PSI_CHECK_STDLIB() { AC_CHECK_HEADERS(stdlib.h) - + PSI_STRUCT(div_t, [ int quot, int rem @@ -65,5 +65,4 @@ AC_DEFUN(PSI_CHECK_STDLIB, [ PSI_DECL(int unsetenv, [(char *var)]) PSI_DECL(size_t wcstombs, [(char *dest, wchar_t *src, size_t n)]) PSI_DECL(int wctomb, [(char *s, wchar_t wc)]) -]) - +} diff --git a/m4/sys_select.m4 b/m4/sys_select.m4 index 7ae010e..7c8da10 100644 --- a/m4/sys_select.m4 +++ b/m4/sys_select.m4 @@ -1,17 +1,17 @@ -AC_DEFUN(PSI_CHECK_SYS_SELECT, [ +PSI_CHECK_SYS_SELECT() { AC_CHECK_HEADERS(sys/select.h) - + PSI_STRUCT(fd_set, []) - + PSI_CONST(FD_SETSIZE, int) - + PSI_MACRO(void FD_CLEAR, [(int fd, fd_set *s)]) PSI_MACRO(void FD_COPY, [(fd_set *s1, fd_set *s2)]) PSI_MACRO(void FD_CLR, [(int fd, fd_set *s)]) PSI_MACRO(void FD_SET, [(int fd, fd_set *s)]) PSI_MACRO(int FD_ISSET, [(int fd, fd_set *s)]) PSI_MACRO(void FD_ZERO, [(fd_set *s)]) - + PSI_DECL(int select, [(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout)]) dnl PSI_DECL(int pselect, [(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout, sigset_t *sigmask)]) -]) \ No newline at end of file +} diff --git a/m4/sys_socket.m4 b/m4/sys_socket.m4 index 3d403cd..4d28cdd 100644 --- a/m4/sys_socket.m4 +++ b/m4/sys_socket.m4 @@ -1,9 +1,9 @@ -AC_DEFUN(PSI_CHECK_SYS_SOCKET, [ +PSI_CHECK_SYS_SOCKET() { AC_CHECK_HEADERS(sys/socket.h) - + PSI_TYPE(socklen_t, int) PSI_TYPE(sa_family_t, uint) - + PSI_STRUCT(struct sockaddr, [ sa_family_t sa_family, char sa_data@<:@0@:>@] @@ -29,7 +29,7 @@ AC_DEFUN(PSI_CHECK_SYS_SOCKET, [ int l_onoff, int l_linger] ) - + PSI_CONST(AF_INET, int) PSI_CONST(AF_INET6, int) PSI_CONST(AF_UNIX, int) @@ -67,11 +67,11 @@ AC_DEFUN(PSI_CHECK_SYS_SOCKET, [ PSI_CONST(SO_SNDLOWAT, int) PSI_CONST(SO_SNDTIMEO, int) PSI_CONST(SO_TYPE, int) - + PSI_MACRO(unsigned char *CMSG_DATA, [(struct cmsghdr *m)]) PSI_MACRO(struct cmsghdr *CMSG_NXTHDR, [(struct msghdr *m, struct cmsghdr *c)]) PSI_MACRO(struct cmsghdr *CMSG_FIRSTHDR, [(struct msghdr *m)]) - + PSI_DECL(int accept, [(int socket, struct sockaddr *address, socklen_t *address_len)]) PSI_DECL(int bind, [(int socket, struct sockaddr *address, socklen_t address_len)]) PSI_DECL(int connect, [(int socket, struct sockaddr *address, socklen_t address_len)]) @@ -90,5 +90,4 @@ AC_DEFUN(PSI_CHECK_SYS_SOCKET, [ PSI_DECL(int sockatmark, [(int socket)]) PSI_DECL(int socket, [(int domain, int type, int protocol)]) PSI_DECL(int socketpair, [(int domain, int type, int protocol, int socket_vector@<:@2@:>@)]) - -]) \ No newline at end of file +} diff --git a/m4/sys_stat.m4 b/m4/sys_stat.m4 index b293232..36f08fc 100644 --- a/m4/sys_stat.m4 +++ b/m4/sys_stat.m4 @@ -1,4 +1,4 @@ -AC_DEFUN(PSI_CHECK_SYS_STAT, [ +PSI_CHECK_SYS_STAT() { AC_CHECK_HEADERS([sys/stat.h]) PSI_STRUCT(struct stat, [ @@ -81,4 +81,4 @@ AC_DEFUN(PSI_CHECK_SYS_STAT, [ PSI_DECL(int stat, [(char *path, struct stat *buf)]) PSI_DECL(mode_t umask, [(mode_t mode)]) PSI_DECL(int utimensat, [(int fd, char *path, struct timespec times@<:@2@:>@, int flag)]) -]) +} diff --git a/m4/sys_time.m4 b/m4/sys_time.m4 index 758ca79..1b845dd 100644 --- a/m4/sys_time.m4 +++ b/m4/sys_time.m4 @@ -1,4 +1,4 @@ -AC_DEFUN(PSI_CHECK_SYS_TIME, [ +PSI_CHECK_SYS_TIME() { AC_CHECK_HEADERS(sys/time.h) PSI_CONST(ITIMER_REAL, int) @@ -23,4 +23,4 @@ AC_DEFUN(PSI_CHECK_SYS_TIME, [ PSI_DECL(int gettimeofday, [(struct timeval *tp, struct timezone *tz)]) PSI_DECL(int utimes, [(char *path, struct timeval times@<:@2@:>@)]) PSI_DECL(int utimensat, [(int fd, char *path, struct timespec times@<:@2@:>@)]) -]) +} diff --git a/m4/sys_times.m4 b/m4/sys_times.m4 index cbaa6fe..9f9da56 100644 --- a/m4/sys_times.m4 +++ b/m4/sys_times.m4 @@ -1,12 +1,12 @@ -AC_DEFUN(PSI_CHECK_SYS_TIMES, [ +PSI_CHECK_SYS_TIMES() { AC_CHECK_HEADERS(sys/times.h) - + PSI_STRUCT(struct tms, [ clock_t tms_utime, clock_t tms_stime, clock_t tms_cutime, clock_t tms_cstime] ) - + PSI_DECL(clock_t times, [(struct tms *buf)]) -]) +} diff --git a/m4/sys_types.m4 b/m4/sys_types.m4 index 352d8b5..88315df 100644 --- a/m4/sys_types.m4 +++ b/m4/sys_types.m4 @@ -1,4 +1,4 @@ -AC_DEFUN(PSI_CHECK_SYS_TYPES, [ +PSI_CHECK_SYS_TYPES() { AC_CHECK_HEADERS(sys/types.h) PSI_TYPE(blkcnt_t, int) @@ -21,4 +21,4 @@ AC_DEFUN(PSI_CHECK_SYS_TYPES, [ PSI_TYPE(time_t, int) PSI_TYPE(timer_t, int) PSI_TYPE(uid_t, int) -]) +} diff --git a/m4/sys_uio.m4 b/m4/sys_uio.m4 index d57f901..e7cbce3 100644 --- a/m4/sys_uio.m4 +++ b/m4/sys_uio.m4 @@ -1,11 +1,11 @@ -AC_DEFUN(PSI_CHECK_SYS_UIO, [ +PSI_CHECK_SYS_UIO() { AC_CHECK_HEADERS(sys/uio.h) - + PSI_STRUCT(struct iovec, [ void *iov_base, size_t iov_len] ) - + PSI_DECL(ssize_t readv, [(int fd, struct iovec *iov, int iovcnt)]) PSI_DECL(ssize_t writev, [(int fd, struct iovec *iov, int iovcnt)]) -]) +} diff --git a/m4/sys_utsname.m4 b/m4/sys_utsname.m4 index 475779f..dde0313 100644 --- a/m4/sys_utsname.m4 +++ b/m4/sys_utsname.m4 @@ -1,6 +1,6 @@ -AC_DEFUN(PSI_CHECK_SYS_UTSNAME, [ +PSI_CHECK_SYS_UTSNAME() { AC_CHECK_HEADERS(sys/utsname.h) - + PSI_STRUCT(struct utsname, [ char sysname@<:@0@:>@, char nodename@<:@0@:>@, @@ -9,6 +9,6 @@ AC_DEFUN(PSI_CHECK_SYS_UTSNAME, [ char machine@<:@0@:>@, char domainname@<:@0@:>@ ]) - + PSI_DECL(int uname, [(struct utsname *name)]) -]) \ No newline at end of file +} diff --git a/m4/syslog.m4 b/m4/syslog.m4 new file mode 100644 index 0000000..198f4f8 --- /dev/null +++ b/m4/syslog.m4 @@ -0,0 +1,42 @@ +PSI_CHECK_SYSLOG() { + AC_CHECK_HEADERS(syslog.h) + + PSI_CONST(LOG_PID, int) + PSI_CONST(LOG_CONS, int) + PSI_CONST(LOG_NDELAY, int) + PSI_CONST(LOG_ODELAY, int) + PSI_CONST(LOG_NOWAIT, int) + PSI_CONST(LOG_KERN, int) + PSI_CONST(LOG_USER, int) + PSI_CONST(LOG_MAIL, int) + PSI_CONST(LOG_NEWS, int) + PSI_CONST(LOG_UUCP, int) + PSI_CONST(LOG_DAEMON, int) + PSI_CONST(LOG_AUTH, int) + PSI_CONST(LOG_CRON, int) + PSI_CONST(LOG_LPR, int) + PSI_CONST(LOG_LOCAL0, int) + PSI_CONST(LOG_LOCAL1, int) + PSI_CONST(LOG_LOCAL2, int) + PSI_CONST(LOG_LOCAL3, int) + PSI_CONST(LOG_LOCAL4, int) + PSI_CONST(LOG_LOCAL5, int) + PSI_CONST(LOG_LOCAL6, int) + PSI_CONST(LOG_LOCAL7, int) + PSI_CONST(LOG_EMERG, int) + PSI_CONST(LOG_ALERT, int) + PSI_CONST(LOG_CRIT, int) + PSI_CONST(LOG_ERR, int) + PSI_CONST(LOG_WARNING, int) + PSI_CONST(LOG_NOTICE, int) + PSI_CONST(LOG_INFO, int) + PSI_CONST(LOG_DEBUG, int) + + PSI_MACRO(int LOG_MASK, [(int pri)]) + PSI_MACRO(int LOG_UPTO, [(int pri)]) + + PSI_DECL(void closelog, [(void)]) + PSI_DECL(void openlog, [(char *ident, int option, int facility)]) + PSI_DECL(void syslog, [(int priority, char *format)], vararg) + PSI_DECL(int setlogmask, [(int mask)]) +} diff --git a/m4/time.m4 b/m4/time.m4 index a4cb58e..c6f71b7 100644 --- a/m4/time.m4 +++ b/m4/time.m4 @@ -1,4 +1,4 @@ -AC_DEFUN(PSI_CHECK_TIME, [ +PSI_CHECK_TIME() { AC_CHECK_HEADERS(time.h) PSI_CONST(CLOCKS_PER_SEC, int) @@ -56,4 +56,4 @@ AC_DEFUN(PSI_CHECK_TIME, [ PSI_DECL(int timer_gettime, [(timer_t t, struct itimerspec *ts)]) PSI_DECL(int timer_settime, [(timer_t t, int flags, struct itimerspec *value, struct itimerspec *ovalue)]) PSI_DECL(void tzset, [()]) -]) +} diff --git a/m4/wchar.m4 b/m4/wchar.m4 index ebffee9..83612b3 100644 --- a/m4/wchar.m4 +++ b/m4/wchar.m4 @@ -1,13 +1,95 @@ -AC_DEFUN(PSI_CHECK_WCHAR, [ +PSI_CHECK_WCHAR() { AC_CHECK_HEADERS(wchar.h) PSI_TYPE(wint_t, int) + PSI_TYPE(wctype_t, int) + PSI_STRUCT(mbstate_t) PSI_CONST(WINT_MIN, int) PSI_CONST(WINT_MAX, int) PSI_CONST(WEOF, int) - PSI_DECL(int wprintf, [(wchar_t *format)], vararg) - PSI_DECL(int fwprintf, [(FILE *stream, wchar_t *format)], vararg) - PSI_DECL(int swprintf, [(wchar_t *wcs, size_t maxlen, wchar_t *format)], vararg) -]) + PSI_DECL(wint_t btowc, [(int c)]) + PSI_DECL(wint_t fgetwc, [(FILE *stream)]) + PSI_DECL(wchar_t *fgetws, [(wchar_t *ws, int n, FILE *stream)]) + PSI_DECL(wint_t fputwc, [(wchar_t c, FILE *stream)]) + PSI_DECL(int fputws, [(const wchar_t *ws, FILE *stream)]) + PSI_DECL(int fwide, [(FILE *stream, int mode)]) + PSI_DECL(int fwprintf, [(FILE *stream, const wchar_t *format)], vararg) + PSI_DECL(int fwscanf, [(FILE *stream, const wchar_t *format)], vararg) + PSI_DECL(wint_t getwc, [(FILE *stream)]) + PSI_DECL(wint_t getwchar, [(void)]) + PSI_DECL(int iswalnum, [(wint_t wc)]) + PSI_DECL(int iswalpha, [(wint_t wc)]) + PSI_DECL(int iswcntrl, [(wint_t wc)]) + PSI_DECL(int iswctype, [(wint_t wc, wctype_t class)]) + PSI_DECL(int iswdigit, [(wint_t wc)]) + PSI_DECL(int iswgraph, [(wint_t wc)]) + PSI_DECL(int iswlower, [(wint_t wc)]) + PSI_DECL(int iswprint, [(wint_t wc)]) + PSI_DECL(int iswpunct, [(wint_t wc)]) + PSI_DECL(int iswspace, [(wint_t wc)]) + PSI_DECL(int iswupper, [(wint_t wc)]) + PSI_DECL(int iswxdigit, [(wint_t wc)]) + PSI_DECL(size_t mbrlen, [(const char *s, size_t n, mbstate_t *ps)]) + PSI_DECL(size_t mbrtowc, [(wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)]) + PSI_DECL(int mbsinit, [(const mbstate_t *ps)]) + PSI_DECL(size_t mbsnrtowcs, [(wchar_t *dst, const char **src, size_t nms, size_t len, mbstate_t *ps)]) + PSI_DECL(size_t mbsrtowcs, [(wchar_t *dst, const char **src, size_t len, mbstate_t *ps)]) + PSI_DECL(FILE *open_wmemstream, [(wchar_t **ptr, size_t *size)]) + PSI_DECL(wint_t putwc, [(wchar_t wc, FILE *stream)]) + PSI_DECL(wint_t putwchar, [(wchar_t wc)]) + PSI_DECL(int swprintf, [(wchar_t *wcs, size_t maxlen, const wchar_t *format)], vararg) + PSI_DECL(int swscanf, [(const wchar_t *ws, const wchar_t *format)], vararg) + PSI_DECL(wint_t towlower, [(wint_t wc)]) + PSI_DECL(wint_t towupper, [(wint_t wc)]) + PSI_DECL(wint_t ungetwc, [(wint_t wc, FILE *stream)]) + PSI_DECL(wchar_t *wcpcpy, [(wchar_t *dest, const wchar_t *src)]) + PSI_DECL(wchar_t *wcpncpy, [(wchar_t *dest, const wchar_t *src, size_t n)]) + PSI_DECL(size_t wcrtomb, [(char *s, wchar_t wc, mbstate_t *ps)]) + PSI_DECL(int wcscasecmp, [(const wchar_t *s1, const wchar_t *s2)]) + PSI_DECL(int wcscasecmp_l, [(const wchar_t *s1, const wchar_t *s2, locale_t loc)]) + PSI_DECL(wchar_t *wcscat, [(wchar_t *dest, const wchar_t *src)]) + PSI_DECL(wchar_t *wcschr, [(const wchar_t *wcs, wchar_t wc)]) + PSI_DECL(int wcscmp, [(const wchar_t *s1, const wchar_t *s2)]) + PSI_DECL(int wcscoll, [(const wchar_t *s1, const wchar_t *s2)]) + PSI_DECL(int wcscoll_l, [(const wchar_t *s1, const wchar_t *s2, locale_t loc)]) + PSI_DECL(wchar_t *wcscpy, [(wchar_t *dest, const wchar_t *src)]) + PSI_DECL(size_t wcscspn, [(const wchar_t *wcs, const wchar_t *reject)]) + PSI_DECL(wchar_t *wcsdup, [(const wchar_t *s)]) + PSI_DECL(size_t wcsftime, [(wchar_t *wcs, size_t maxsize, const wchar_t *format, const struct tm *timeptr)]) + PSI_DECL(size_t wcslen, [(const wchar_t *s)]) + PSI_DECL(int wcsncasecmp, [(const wchar_t *s1, const wchar_t *s2, size_t n)]) + PSI_DECL(int wcsncasecmp_l, [(const wchar_t *s1, const wchar_t *s2, size_t n, locale_t loc)]) + PSI_DECL(wchar_t *wcsncat, [(wchar_t *dest, const wchar_t *src, size_t n)]) + PSI_DECL(int wcsncmp, [(const wchar_t *s1, const wchar_t *s2, size_t n)]) + PSI_DECL(wchar_t *wcsncpy, [(wchar_t *dest, const wchar_t *src, size_t n)]) + PSI_DECL(size_t wcsnlen, [(const wchar_t *s, size_t maxlen)]) + PSI_DECL(size_t wcsnrtombs, [(char *dest, const wchar_t **src, size_t nwc, size_t len, mbstate_t *ps)]) + PSI_DECL(wchar_t *wcspbrk, [(const wchar_t *wcs, const wchar_t *accept)]) + PSI_DECL(wchar_t *wcsrchr, [(const wchar_t *wcs, wchar_t wc)]) + PSI_DECL(size_t wcsrtombs, [(char *dest, const wchar_t **src, size_t n, mbstate_t *ps)]) + PSI_DECL(size_t wcsspn, [(const wchar_t *wcs, const wchar_t *accept)]) + PSI_DECL(wchar_t *wcsstr, [(const wchar_t *haystack, const wchar_t *needle)]) + PSI_DECL(double wcstod, [(const wchar_t *nptr, wchar_t **endptr)]) + PSI_DECL(float wcstof, [(const wchar_t *nptr, wchar_t **endptr)]) + PSI_DECL(wchar_t *wcstok, [(wchar_t *wcs, const wchar_t *delim, wchar_t **ptr)]) + PSI_DECL(long wcstol, [(const wchar_t *nptr, wchar_t **endptr, int base)]) + dnl PSI_DECL(long double wcstold, [(const wchar_t *nptr, wchar_t **endptr)]) + dnl PSI_DECL(long long wcstoll, [(const wchar_t *nptr, wchar_t **endptr, int base)]) + PSI_DECL(unsigned long wcstoul, [(const wchar_t *nptr, wchar_t **endptr, int base)]) + dnl PSI_DECL(unsigned long long wcstoull, [(const wchar_t *nptr, wchar_t **endptr, int base)]) + PSI_DECL(int wcswidth, [(const wchar_t *s, size_t n)]) + PSI_DECL(size_t wcsxfrm, [(wchar_t *ws1, const wchar_t *ws2, size_t n)]) + PSI_DECL(size_t wcsxfrm_l, [(wchar_t *ws1, const wchar_t *ws2, size_t n, locale_t loc)]) + PSI_DECL(int wctob, [(wint_t c)]) + PSI_DECL(wctype_t wctype, [(const char *name)]) + PSI_DECL(int wcwidth, [(wchar_t c)]) + PSI_DECL(wchar_t *wmemchr, [(const wchar_t *s, wchar_t c, size_t n)]) + PSI_DECL(int wmemcmp, [(const wchar_t *s1, const wchar_t *s2, size_t n)]) + PSI_DECL(wchar_t *wmemcpy, [(wchar_t *dest, const wchar_t *src, size_t n)]) + PSI_DECL(wchar_t *wmemmove, [(wchar_t *dest, const wchar_t *src, size_t n)]) + PSI_DECL(wchar_t *wmemset, [(wchar_t *wcs, wchar_t wc, size_t n)]) + PSI_DECL(int wprintf, [(const wchar_t *format)], vararg) + PSI_DECL(int wscanf, [(const wchar_t *format)], vararg) +} diff --git a/psi.d/syslog.psi b/psi.d/syslog.psi new file mode 100644 index 0000000..b3510b8 --- /dev/null +++ b/psi.d/syslog.psi @@ -0,0 +1,28 @@ +function psi\openlog(string $ident, int $option, int $facility) : void { + let ident = strval($ident); + let option = intval($option); + let facility = intval($facility); + return void(openlog); +} + +function psi\closelog() : void { + return void(closelog); +} + +function psi\setlogmask(int $mask) : int { + let mask = intval($mask); + return to_int(setlogmask); +} + +function psi\syslog(int $priority, string $format, mixed ...$args) : void { + let priority = intval($priority); + let format = strval($format); + return void(syslog); +} + +// redirected macro +extern int LOG_MASK(int pri); +function psi\LOG_MASK(int $pri) : int { + let pri = intval($pri); + return to_int(LOG_MASK); +} diff --git a/src/context.c b/src/context.c index 4a4f472..fd315ee 100644 --- a/src/context.c +++ b/src/context.c @@ -129,6 +129,15 @@ static struct psi_std_type { {0} }; +#include "php_psi_types.h" +#include "php_psi_consts.h" +#include "php_psi_macros.h" +#include "php_psi_redirs.h" +#include "php_psi_decls.h" +#include "php_psi_va_decls.h" +#include "php_psi_structs.h" + +/* static struct psi_predef_type { token_t type_tag; const char *type_name; @@ -207,7 +216,7 @@ static struct psi_predef_struct { PSI_STRUCTS {0} }; - +*/ static int validate_lib(PSI_Data *data, void **dlopened) { char lib[MAXPATHLEN]; const char *ptr = data->psi.file.ln; diff --git a/tests/netdb/gai001.phpt b/tests/netdb/gai001.phpt index 42e83fc..7e6f953 100644 --- a/tests/netdb/gai001.phpt +++ b/tests/netdb/gai001.phpt @@ -3,12 +3,12 @@ getaddrinfo --INI-- psi.directory={PWD}:{PWD}/../../psi.d --SKIPIF-- - --FILE-- ===TEST=== - ===DONE=== --EXPECT-- ===TEST=== -int(0) -string(12) "78.46.223.30" -string(1) "0" -int(0) -string(12) "78.46.223.30" -string(1) "0" -int(0) -string(12) "78.46.223.30" -string(1) "0" -===DONE=== \ No newline at end of file +===DONE=== -- 2.30.2