#include "php.h"
-#include <stdio.h>
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-#ifdef STDC_HEADERS
-# include <stdlib.h>
-# include <stddef.h>
-#else
-# ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
-#endif
-#ifdef HAVE_STRING_H
-# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
-# include <memory.h>
-# endif
-# include <string.h>
-#endif
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
-#ifdef HAVE_INTTYPES_H
-# include <inttypes.h>
-#endif
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#ifdef HAVE_ERRNO_H
-# include <errno.h>
-#endif
-#ifdef HAVE_GLOB_H
-# include <glob.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-#ifdef HAVE_ARPA_NAMESER_H
-# include <arpa/nameser.h>
-#endif
-#ifdef HAVE_NETDB_H
-# include <netdb.h>
-#endif
-#ifdef HAVE_RESOLV_H
-# include <resolv.h>
-#endif
-#ifdef HAVE_SYS_SELECT_H
-# include <sys/select.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
-#ifdef HAVE_SYS_TIMES_H
-# include <sys/times.h>
-#endif
-#ifdef HAVE_SYS_UIO_H
-# include <sys/uio.h>
-#endif
-#ifdef HAVE_SYS_UTSNAME_H
-# include <sys/utsname.h>
-#endif
-#ifdef HAVE_TIME_H
-# include <time.h>
-#endif
-#ifdef HAVE_SYSLOG_H
-# include <syslog.h>
-#endif
-#ifdef HAVE_WCHAR_H
-# include <wchar.h>
-#endif
+#include "php_psi_stdinc.h"
#ifdef HAVE_DIRENT_H
# include <dirent.h>
} 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"},
{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];
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;
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;
s->size = darg->layout->pos + darg->layout->len;
}
}
+
+ psi_sort_struct_args(s);
+
return 1;
}
"default", /* \ */
"extern", /* > - all the same */
"cdecl", /* / */
+ "mscdecl",
"stdcall",
"fastcall",
};
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;
}
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;
}
}
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;
+ }
}
}
}
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");
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;
+ }
}
}
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;
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]);
}
}
exp = exp->operand;
}
}
+
static inline void dump_impl_set_value(int fd, set_value *set, unsigned level) {
size_t i;
/* 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];
}
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);
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");
}
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();
}