X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=blobdiff_plain;f=src%2Fcontext.c;h=3ab1d218797685340360eda838aad56a9f610c52;hp=a75368eb108dc240741937bfc90b0b912c83bc8c;hb=ac133e1eb5215f4da26898eb191a24fad848db0f;hpb=19f0eb5807fb8d0f3aa305f2476f094e66a02709 diff --git a/src/context.c b/src/context.c index a75368e..3ab1d21 100644 --- a/src/context.c +++ b/src/context.c @@ -4,85 +4,7 @@ #include "php.h" -#include -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_SYS_STAT_H -# include -#endif -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif -#ifdef HAVE_STRING_H -# if !defined STDC_HEADERS && defined HAVE_MEMORY_H -# include -# endif -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif -#ifdef HAVE_INTTYPES_H -# include -#endif -#ifdef HAVE_STDINT_H -# include -#endif -#ifdef HAVE_UNISTD_H -# include -#endif - -#ifdef HAVE_ERRNO_H -# include -#endif -#ifdef HAVE_GLOB_H -# include -#endif -#ifdef HAVE_NETINET_IN_H -# include -#endif -#ifdef HAVE_ARPA_NAMESER_H -# include -#endif -#ifdef HAVE_NETDB_H -# include -#endif -#ifdef HAVE_RESOLV_H -# include -#endif -#ifdef HAVE_SYS_SELECT_H -# include -#endif -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -#ifdef HAVE_SYS_TIME_H -# include -#endif -#ifdef HAVE_SYS_TIMES_H -# include -#endif -#ifdef HAVE_SYS_UIO_H -# include -#endif -#ifdef HAVE_SYS_UTSNAME_H -# include -#endif -#ifdef HAVE_TIME_H -# include -#endif -#ifdef HAVE_SYSLOG_H -# include -#endif -#ifdef HAVE_WCHAR_H -# include -#endif +#include "php_psi_stdinc.h" #ifdef HAVE_DIRENT_H # include @@ -118,6 +40,9 @@ static struct psi_std_type { } psi_std_types[] = { {PSI_T_FLOAT, "float"}, {PSI_T_DOUBLE, "double"}, +#ifdef HAVE_LONG_DOUBLE + {PSI_T_LONG_DOUBLE, "long double"}, +#endif {PSI_T_INT8, "int8_t"}, {PSI_T_INT16, "int16_t"}, {PSI_T_INT32, "int32_t"}, @@ -129,77 +54,13 @@ static struct psi_std_type { {0} }; -static struct psi_predef_type { - token_t type_tag; - const char *type_name; - const char *alias; -} psi_predef_types[] = { - PSI_TYPES - {0} -}; - -static struct psi_predef_const { - token_t type_tag; - const char *type_name; - const char *var_name; - const char *val_text; - token_t val_type_tag; -} psi_predef_consts[] = { - PSI_CONSTS - {0} -}; - -PSI_MACROS - -int psi_glob(const char *pattern, int flags, - int (*errfunc) (const char *epath, int eerrno), - glob_t *pglob) { - size_t offs = flags & GLOB_DOOFFS ? pglob->gl_offs : 0; - int rv = glob(pattern, flags, errfunc, pglob); - if (pglob->gl_pathv) { - while (offs--) { - pglob->gl_pathv[offs] = NULL; - } - } - return rv; -} - -static struct psi_func_redir { - const char *name; - void (*func)(void); -} psi_func_redirs[] = { - {"glob", (void (*)(void)) psi_glob}, - PSI_REDIRS - {0} -}; - -static struct psi_predef_decl { - token_t type_tag; - const char *type_name; - const char *var_name; - size_t pointer_level; - size_t array_size; -} psi_predef_decls[] = { - 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; - const char *type_name; - const char *var_name; - size_t offset; - size_t size; - size_t pointer_level; - size_t array_size; -} psi_predef_structs[] = { - PSI_STRUCTS - {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 int validate_lib(PSI_Data *data, void **dlopened) { char lib[MAXPATHLEN]; @@ -266,6 +127,10 @@ static inline int locate_decl_type_struct(decl_structs *structs, decl_type *type static inline int validate_decl_type(PSI_Data *data, decl_type *type) { switch (type->type) { + case PSI_T_CHAR: + case PSI_T_SHORT: + case PSI_T_INT: + case PSI_T_LONG: case PSI_T_NAME: if (!data->defs || !locate_decl_type_alias(data->defs, type)) { return 0; @@ -308,6 +173,35 @@ static inline int validate_decl_arg(PSI_Data *data, decl_arg *arg) { return 1; } +static int psi_sort_struct_arg_cmp(const void *_a, const void *_b) { + decl_arg *a = *(decl_arg **)_a, *b = *(decl_arg **)_b; + + if (a->layout->pos == b->layout->pos) { + if (a->layout->len == b->layout->len) { + return 0; + } else if (a->layout->len > b->layout->len) { + return -1; + } else { + return 1; + } + } else if (a->layout->pos > b->layout->pos) { + return 1; + } else { + return -1; + } +} +static void psi_sort_struct_arg_swp(void *a, void *b) { + decl_arg **_a = a, **_b = b, *_c; + + _c = *_b; + *_b = *_a; + *_a = _c; +} +static inline void psi_sort_struct_args(decl_struct *s) { + zend_insert_sort(s->args->args, s->args->count, sizeof(*s->args->args), + psi_sort_struct_arg_cmp, psi_sort_struct_arg_swp); +} + static inline int validate_decl_struct(PSI_Data *data, decl_struct *s) { size_t i; @@ -349,6 +243,9 @@ static inline int validate_decl_struct(PSI_Data *data, decl_struct *s) { s->size = darg->layout->pos + darg->layout->len; } } + + psi_sort_struct_args(s); + return 1; } @@ -356,6 +253,7 @@ static const char * const abi_ccs[] = { "default", /* \ */ "extern", /* > - all the same */ "cdecl", /* / */ + "mscdecl", "stdcall", "fastcall", }; @@ -523,6 +421,14 @@ 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; + set->inner = set->outer.set->inner; + set->count = set->outer.set->count; + break; + } + /* no break */ default: return 0; } @@ -547,14 +453,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; } } @@ -582,14 +488,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); - - 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; + 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; + } } } } @@ -598,7 +505,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"); @@ -881,25 +787,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; + } } } @@ -940,6 +847,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; @@ -1136,7 +1070,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]); } } @@ -1311,6 +1245,7 @@ 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; @@ -1318,7 +1253,12 @@ static inline void dump_impl_set_value(int fd, set_value *set, unsigned level) { /* 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]; @@ -1327,11 +1267,15 @@ 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); } - if (set->inner) { + if (set->inner && set->func->type != PSI_T_ELLIPSIS) { dprintf(fd, ",\n"); for (i = 0; i < set->count; ++i) { dump_impl_set_value(fd, set->inner[i], level+1); @@ -1367,7 +1311,8 @@ void PSI_ContextDump(PSI_Context *C, int fd) dprintf(fd, "typedef "); dump_decl_type(fd, tdef->type); - dprintf(fd, " %s;\n", tdef->alias); + dprintf(fd, " %s%s;\n", tdef->type->type == PSI_T_POINTER ? "*":"", + tdef->alias); } dprintf(fd, "\n"); } @@ -1478,6 +1423,9 @@ void PSI_ContextDump(PSI_Context *C, int fd) dprintf(fd, "%s($%s)", let->val->data.func->name, let->val->data.func->var->name); break; + case PSI_LET_NUMEXP: + dump_num_exp(fd, let->val->data.num); + break; EMPTY_SWITCH_DEFAULT_CASE(); }