php_psi_macros.h
php_psi_redirs.h
php_psi_stdinc.h
+php_psi_stdtypes.h
php_psi_structs.h
php_psi_types.h
php_psi_va_decls.h
* pemalloc
* unions
* callbacks and function pointers
+* full struct typedefs
\ No newline at end of file
dnl Generated headers with pre-defined types, structs, consts and decls.
PSI_STDINC=$PHP_PSI_SRCDIR/php_psi_stdinc.h
+PSI_STDTYPES=$PHP_PSI_SRCDIR/php_psi_stdtypes.h
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
dnl These headers are included by src/context.c.
dnl This macro must be called prior any checks for a type, struct, decl etc.
AC_DEFUN(PSI_CONFIG_INIT, [
- cat >$PSI_TYPES <<EOF
+ cat >$PSI_STDTYPES <<EOF
/* generated by configure */
static struct psi_predef_type {
token_t type_tag;
const char *type_name;
const char *alias;
-} psi_predef_types@<:@@:>@ = {
+} psi_std_types@<:@@:>@ = {
+ {PSI_T_INT8, "int8_t", NULL},
+ {PSI_T_INT16, "int16_t", NULL},
+ {PSI_T_INT32, "int32_t", NULL},
+ {PSI_T_INT64, "int64_t", NULL},
+ {PSI_T_UINT8, "uint8_t", NULL},
+ {PSI_T_UINT16, "uint16_t", NULL},
+ {PSI_T_UINT32, "uint32_t", NULL},
+ {PSI_T_UINT64, "uint64_t", NULL},
+EOF
+ cat >$PSI_TYPES <<EOF
+/* generated by configure */
+static struct psi_predef_type psi_predef_types@<:@@:>@ = {
EOF
cat >$PSI_STRUCTS <<EOF
/* generated by configure */
/* generated by configure */
PSI_INCLUDES
EOF
- for i in $PSI_TYPES $PSI_STRUCTS $PSI_CONSTS $PSI_REDIRS $PSI_DECLS $PSI_VA_DECLS; do
+ for i in $PSI_STDTYPES $PSI_TYPES $PSI_STRUCTS $PSI_CONSTS $PSI_REDIRS $PSI_DECLS $PSI_VA_DECLS; do
cat >>$i <<EOF
{0}
};
cat >>$PSI_TYPES <<<" $1, "
}
+psi_add_stdtype() {
+ cat >>$PSI_STDTYPES <<<" $1, "
+}
+
# psi_type_pair(type, size)
# Output a PSI_T_<TYPE>, \"<TYPENAME>\" tuple.
# Uses stdint types when possible.
esac
if test "$2" && PSI_SH_TEST_SIZEOF($1); then
AS_TR_SH(psi_basic_type_$1)=$psi_basic_type
- psi_add_type "{`psi_type_pair $psi_basic_type $AS_TR_SH([ac_cv_sizeof_]$1)`, \"$1\"}"
+ psi_add_type "{`psi_type_pair $psi_basic_type PSI_SH_SIZEOF($1)`, \"$1\"}"
+ fi
+])
+
+AC_DEFUN(PSI_STDTYPE, [
+ ifdef(AS_TR_CPP(AC_TYPE_$1), AS_TR_CPP(AC_TYPE_$1))
+ PSI_CHECK_SIZEOF($1)
+ if PSI_SH_TEST_SIZEOF($1); then
+ m4_case([$1],
+ [float],[psi_add_stdtype "{PSI_T_FLOAT, \"float\", NULL}"],
+ [double],[psi_add_stdtype "{PSI_T_DOUBLE, \"double\", NULL}"],
+ [long double],[psi_add_stdtype "{PSI_T_LONG_DOUBLE, \"long double\", NULL}"],
+ [
+ AX_CHECK_SIGN($1, psi_basic_type=int, psi_basic_type=uint, PSI_INCLUDES)
+ AS_TR_SH(psi_basic_type_$1)=$psi_basic_type
+ psi_add_stdtype "{`psi_type_pair $psi_basic_type PSI_SH_SIZEOF($1)`, \"$1\"}"
+ ])
fi
])
case "$AS_TR_SH([psi_cv_type_class_]$1)" in
scalar)
AX_CHECK_SIGN($1, [psi_basic_type=int], [psi_basic_type=uint], PSI_INCLUDES)
- psi_add_type "{`psi_type_pair $psi_basic_type $AS_TR_SH([ac_cv_sizeof_]$1)`, \"$1\"}"
+ psi_add_type "{`psi_type_pair $psi_basic_type PSI_SH_SIZEOF($1)`, \"$1\"}"
;;
struct)
PSI_STRUCT($1)
AC_TYPE_UINT64_T
PSI_CHECK_SIZEOF(uint64_t)
AC_CHECK_ALIGNOF(uint64_t)
+
+ PSI_CHECK_SIZEOF(void *)
+ AC_CHECK_ALIGNOF(void *)
- PSI_TYPE(float)
+ PSI_STDTYPE(float)
AC_CHECK_ALIGNOF(float)
- PSI_TYPE(double)
+ PSI_STDTYPE(double)
AC_CHECK_ALIGNOF(double)
- PSI_TYPE(long double)
+ PSI_STDTYPE(long double)
AC_CHECK_ALIGNOF(long double)
- PSI_TYPE(void *)
- AC_CHECK_ALIGNOF(void *)
- PSI_TYPE(char, int)
- PSI_TYPE(signed char, int)
- PSI_TYPE(unsigned char, uint)
- PSI_TYPE(short, int)
- PSI_TYPE(short int, int)
- PSI_TYPE(signed short, int)
- PSI_TYPE(signed short int, int)
- PSI_TYPE(unsigned short, uint)
- PSI_TYPE(unsigned short int, uint)
- PSI_TYPE(int, int)
- PSI_TYPE(signed int, int)
- PSI_TYPE(signed, int)
- PSI_TYPE(unsigned int, uint)
- PSI_TYPE(unsigned, uint)
- PSI_TYPE(long, int)
- PSI_TYPE(long int, int)
- PSI_TYPE(signed long int, int)
- PSI_TYPE(unsigned long, uint)
- PSI_TYPE(unsigned long int, uint)
- PSI_TYPE(long long, int)
- PSI_TYPE(signed long long, int)
- PSI_TYPE(signed long long int, int)
- PSI_TYPE(unsigned long long, uint)
- PSI_TYPE(unsigned long long int, uint)
+ PSI_STDTYPE(char, int)
+ PSI_STDTYPE(signed char, int)
+ PSI_STDTYPE(unsigned char, uint)
+ PSI_STDTYPE(short, int)
+ PSI_STDTYPE(short int, int)
+ PSI_STDTYPE(signed short, int)
+ PSI_STDTYPE(signed short int, int)
+ PSI_STDTYPE(unsigned short, uint)
+ PSI_STDTYPE(unsigned short int, uint)
+ PSI_STDTYPE(int, int)
+ PSI_STDTYPE(signed int, int)
+ PSI_STDTYPE(signed, int)
+ PSI_STDTYPE(unsigned int, uint)
+ PSI_STDTYPE(unsigned, uint)
+ PSI_STDTYPE(long, int)
+ PSI_STDTYPE(long int, int)
+ PSI_STDTYPE(signed long int, int)
+ PSI_STDTYPE(unsigned long, uint)
+ PSI_STDTYPE(unsigned long int, uint)
+ PSI_STDTYPE(long long, int)
+ PSI_STDTYPE(signed long long, int)
+ PSI_STDTYPE(signed long long int, int)
+ PSI_STDTYPE(unsigned long long, uint)
+ PSI_STDTYPE(unsigned long long int, uint)
dnl this must come after the check fo "unsigned long long int"; autoconf, wth?
- PSI_TYPE(long long int, int)
+ PSI_STDTYPE(long long int, int)
])
#include "libjit.h"
#include "libffi.h"
-static struct psi_std_type {
- token_t type_tag;
- const char *type_name;
-} 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"},
- {PSI_T_INT64, "int64_t"},
- {PSI_T_UINT8, "uint8_t"},
- {PSI_T_UINT16, "uint16_t"},
- {PSI_T_UINT32, "uint32_t"},
- {PSI_T_UINT64, "uint64_t"},
- {0}
-};
-
+#include "php_psi_stdtypes.h"
#include "php_psi_types.h"
#include "php_psi_consts.h"
#include "php_psi_macros.h"
static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) {
size_t i;
- struct psi_std_type *stdtyp;
+ struct psi_predef_type *stdtyp;
if (type->real) {
return 1;
}
}
for (stdtyp = &psi_std_types[0]; stdtyp->type_tag; ++stdtyp) {
- if (!strcmp(type->name, stdtyp->type_name)) {
+ if (!strcmp(type->name, stdtyp->alias ?: stdtyp->type_name)) {
type->type = stdtyp->type_tag;
return 1;
}
}
}
-static inline void dump_impl_set_value(int fd, set_value *set, unsigned level) {
+static inline void dump_impl_set_value(int fd, set_value *set, unsigned level, int last) {
size_t i;
if (level > 1) {
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);
+ dump_impl_set_value(fd, set->inner[i], level+1, i == (set->count - 1));
}
/* only if inner stmts, i.e. with new lines, were dumped */
dump_level(fd, level);
}
if (level > 1) {
- dprintf(fd, "),\n");
+ dprintf(fd, ")%s\n", last ? "" : ",");
} else {
dprintf(fd, ");\n");
}
for (i = 0; i < C->structs->count; ++i) {
decl_struct *strct = C->structs->list[i];
- dprintf(fd, "struct %s::(%zu) {\n", strct->name, strct->size);
- if (strct->args) for (j = 0; j < strct->args->count; ++j) {
- decl_arg *sarg = strct->args->args[j];
+ dprintf(fd, "struct %s::(%zu)", strct->name, strct->size);
+ if (strct->args && strct->args->count) {
+ dprintf(fd, " {\n");
+ for (j = 0; j < strct->args->count; ++j) {
+ decl_arg *sarg = strct->args->args[j];
- dprintf(fd, "\t");
- dump_decl_arg(fd, sarg);
- dprintf(fd, "::(%zu, %zu);\n", sarg->layout->pos, sarg->layout->len);
+ dprintf(fd, "\t");
+ dump_decl_arg(fd, sarg);
+ dprintf(fd, "::(%zu, %zu);\n", sarg->layout->pos, sarg->layout->len);
+ }
+ dprintf(fd, "}");
+ } else {
+ dprintf(fd, ";");
}
- dprintf(fd, "}\n");
+ dprintf(fd, "\n");
+
}
dprintf(fd, "\n");
}
return_stmt *ret = impl->stmts->ret.list[j];
dprintf(fd, "\treturn ");
- dump_impl_set_value(fd, ret->set, 1);
+ dump_impl_set_value(fd, ret->set, 1, 0);
}
for (j = 0; j < impl->stmts->set.count; ++j) {
set_stmt *set = impl->stmts->set.list[j];
dprintf(fd, "\tset $%s = ", set->var->name);
- dump_impl_set_value(fd, set->val, 1);
+ dump_impl_set_value(fd, set->val, 1, 0);
}
for (j = 0; j < impl->stmts->fre.count; ++j) {
free_stmt *fre = impl->stmts->fre.list[j];
va_list argv;
va_start(argv, msg);
- psi_verror(type, t?t->file:"Unknown", t?*t->line:0, 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, ...)
typedef struct PSI_Token {
token_t type;
- unsigned size, *line;
+ unsigned size, line;
char *text, *file;
char buf[1];
} PSI_Token;
} PSI_Parser;
static inline size_t PSI_TokenAllocSize(size_t token_len, size_t fname_len) {
- return sizeof(PSI_Token) + token_len + fname_len + sizeof(unsigned) + 2;
+ return sizeof(PSI_Token) + token_len + fname_len + 2;
}
static inline PSI_Token *PSI_TokenAlloc(PSI_Parser *P) {
T->size = token_len;
T->text = &T->buf[0];
T->file = &T->buf[token_len + 1];
- T->line = (void *) &T->buf[fname_len + token_len + 2];
+ T->line = P->line;
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;
}
PSI_Token *arg = va_arg(argv, PSI_Token *);
if (T) {
- size_t fname_len = strlen(T->file);
+ size_t token_len = T->size, fname_len = strlen(T->file);
- T = realloc(T, PSI_TokenAllocSize(T->size + arg->size, fname_len));
- memmove(&T->buf[T->size + 1], T->file, fname_len + 1);
- memcpy(T->file - 1, arg->text, arg->size + 1);
+ T = realloc(T, PSI_TokenAllocSize(T->size += arg->size + 1, fname_len));
+ T->text = &T->buf[0];
T->file = &T->buf[T->size + 1];
+ T->buf[token_len] = ' ';
+ memmove(&T->buf[T->size + 1], &T->buf[token_len + 1], fname_len + 1);
+ memcpy(&T->buf[token_len + 1], arg->text, arg->size + 1);
} else {
T = PSI_TokenCopy(arg);
T->type = PSI_T_NAME;
+#include <stddef.h>
#include <stdio.h>
#include <assert.h>
#define PSI_T_LET 9
#define PSI_T_RETURN 10
#define PSI_T_LIB 11
-#define PSI_T_CHAR 12
-#define PSI_T_SHORT 13
-#define PSI_T_INT 14
-#define PSI_T_LONG 15
-#define PSI_T_SIGNED 16
-#define PSI_T_UNSIGNED 17
-#define PSI_T_EOF 18
-#define PSI_T_QUOTED_STRING 19
-#define PSI_T_EOS 20
-#define PSI_T_STRUCT 21
-#define PSI_T_LBRACE 22
-#define PSI_T_RBRACE 23
-#define PSI_T_COLON 24
-#define PSI_T_LPAREN 25
-#define PSI_T_NUMBER 26
-#define PSI_T_RPAREN 27
-#define PSI_T_BOOL 28
-#define PSI_T_FLOAT 29
-#define PSI_T_STRING 30
-#define PSI_T_CONST 31
-#define PSI_T_NSNAME 32
-#define PSI_T_EQUALS 33
-#define PSI_T_TYPEDEF 34
-#define PSI_T_VOID 35
-#define PSI_T_LBRACKET 36
-#define PSI_T_RBRACKET 37
-#define PSI_T_COMMA 38
-#define PSI_T_ELLIPSIS 39
-#define PSI_T_DOUBLE 40
+#define PSI_T_STRING 12
+#define PSI_T_EOF 13
+#define PSI_T_EOS 14
+#define PSI_T_QUOTED_STRING 15
+#define PSI_T_STRUCT 16
+#define PSI_T_LBRACE 17
+#define PSI_T_RBRACE 18
+#define PSI_T_COLON 19
+#define PSI_T_LPAREN 20
+#define PSI_T_NUMBER 21
+#define PSI_T_RPAREN 22
+#define PSI_T_BOOL 23
+#define PSI_T_INT 24
+#define PSI_T_FLOAT 25
+#define PSI_T_CONST 26
+#define PSI_T_NSNAME 27
+#define PSI_T_EQUALS 28
+#define PSI_T_TYPEDEF 29
+#define PSI_T_VOID 30
+#define PSI_T_LBRACKET 31
+#define PSI_T_RBRACKET 32
+#define PSI_T_COMMA 33
+#define PSI_T_ELLIPSIS 34
+#define PSI_T_CHAR 35
+#define PSI_T_SHORT 36
+#define PSI_T_LONG 37
+#define PSI_T_DOUBLE 38
+#define PSI_T_UNSIGNED 39
+#define PSI_T_SIGNED 40
#define PSI_T_INT8 41
#define PSI_T_UINT8 42
#define PSI_T_INT16 43
%include {
+#include <stddef.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
%syntax_error {
++P->errors;
if (TOKEN && TOKEN->type != PSI_T_EOF) {
- psi_error(PSI_WARNING, TOKEN->file, *TOKEN->line, "PSI syntax error: Unexpected token '%s'", TOKEN->text);
+ psi_error(PSI_WARNING, TOKEN->file, TOKEN->line, "PSI syntax error: Unexpected token '%s'", TOKEN->text);
} else {
psi_error(PSI_WARNING, P->psi.file.fn, P->line, "PSI syntax error: Unexpected end of input");
}
%nonassoc NAME.
%left PLUS MINUS.
%left SLASH ASTERISK.
-%fallback NAME TEMP FREE SET LET RETURN LIB CHAR SHORT INT LONG SIGNED UNSIGNED.
+%fallback NAME TEMP FREE SET LET RETURN LIB STRING.
file ::= blocks.
blocks ::= blocks block.
block ::= EOF.
+block ::= EOS.
block ::= LIB(T) QUOTED_STRING(libname) EOS. {
if (P->psi.file.ln) {
P->structs = add_decl_struct(P->structs, strct);
}
+struct_name(n) ::= STRUCT NAME(N). {
+ n = N;
+}
+
+%type decl_struct_args {decl_args*}
+%destructor decl_struct_args {free_decl_args($$);}
+decl_struct_args(args_) ::= LBRACE struct_args(args) RBRACE. {
+ args_ = args;
+}
+decl_struct_args(args_) ::= EOS. {
+ args_ = init_decl_args(NULL);
+}
+
+
%type decl_struct {decl_struct*}
%destructor decl_struct {free_decl_struct($$);}
-decl_struct(strct) ::= STRUCT NAME(N) struct_size(size_) LBRACE struct_args(args) RBRACE. {
+decl_struct(strct) ::= struct_name(N) struct_size(size_) decl_struct_args(args). {
strct = init_decl_struct(N->text, args);
strct->size = size_;
strct->token = N;
%type decl_typedef {decl_typedef*}
%destructor decl_typedef {free_decl_typedef($$);}
-decl_typedef(def) ::= TYPEDEF decl_type(type) NAME(ALIAS) EOS. {
+decl_typedef(def) ::= TYPEDEF decl_typedef_body(def_) EOS. {
+ def = def_;
+}
+%type decl_typedef_body {decl_typedef*}
+%destructor decl_typedef_body {free_decl_typedef($$);}
+decl_typedef_body(def) ::= decl_type(type) NAME(ALIAS). {
def = init_decl_typedef(ALIAS->text, type);
def->token = ALIAS;
}
+
/* support opaque types */
-decl_typedef(def) ::= TYPEDEF VOID(V) indirection(i) NAME(ALIAS) EOS. {
+decl_typedef_body(def) ::= VOID(V) indirection(i) NAME(ALIAS). {
def = init_decl_typedef(ALIAS->text, init_decl_type(i?PSI_T_POINTER:V->type, V->text));
def->token = ALIAS;
def->type->token = V;
}
-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(S);
-}
-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->token = ALIAS;
- def->type->token = PSI_TokenCopy(s->token);
- def->type->strct = s;
-}
%type decl {decl*}
%destructor decl {free_decl($$);}
decl_scalar_type(type_) ::= CHAR(C). {
type_ = C;
}
-decl_scalar_type(type_) ::= SHORT(S) INT(I). {
- type_ = PSI_TokenCat(2, S, I);
- free(S);
- free(I);
+decl_scalar_type(type_) ::= SHORT(S) decl_scalar_type_short(s). {
+ if (s) {
+ type_ = PSI_TokenCat(2, S, s);
+ free(S);
+ free(s);
+ } else {
+ type_ = S;
+ }
}
-decl_scalar_type(type_) ::= SHORT(S). {
- type_ = S;
+decl_scalar_type_short(s) ::= . {
+ s = NULL;
}
-decl_scalar_type(type_) ::= LONG(L) INT(I). {
- type_ = PSI_TokenCat(2, L, I);
- free(L);
- free(I);
+
+decl_scalar_type_short(s) ::= INT(I). {
+ s = I;
}
-decl_scalar_type(type_) ::= LONG(L1) LONG(L2) INT(I). {
- type_ = PSI_TokenCat(3, L1, L2, I);
- free(L1);
- free(L2);
- free(I);
+decl_scalar_type(type_) ::= INT(I). {
+ type_ = I;
}
-decl_scalar_type(type_) ::= LONG(L1) LONG(L2). {
- type_ = PSI_TokenCat(2, L1, L2);
- free(L1);
- free(L2);
+decl_scalar_type(type_) ::= LONG(L) decl_scalar_type_long(l). {
+ if (l) {
+ type_ = PSI_TokenCat(2, L, l);
+ free(L);
+ free(l);
+ } else {
+ type_ = L;
+ }
+}
+decl_scalar_type_long(l) ::= . {
+ l = NULL;
+}
+decl_scalar_type_long(l) ::= DOUBLE(D). {
+ l = D;
+}
+decl_scalar_type_long(l) ::= LONG(L) decl_scalar_type_long_long(ll). {
+ if (ll) {
+ l = PSI_TokenCat(2, L, ll);
+ free(L);
+ free(ll);
+ } else {
+ l = L;
+ }
+}
+decl_scalar_type_long_long(ll) ::= . {
+ ll = NULL;
+}
+decl_scalar_type_long_long(ll) ::= INT(I). {
+ ll = I;
}
decl_type(type_) ::= UNSIGNED(U) decl_scalar_type(N). {
PSI_Token *T = PSI_TokenCat(2, U, N);
free(S);
free(N);
}
+decl_type(type_) ::= UNSIGNED(U). {
+ type_ = init_decl_type(PSI_T_NAME, U->text);
+ type_->token = U;
+}
+decl_type(type_) ::= SIGNED(S). {
+ type_ = init_decl_type(PSI_T_NAME, S->text);
+ type_->token = S;
+}
+decl_type(type_) ::= decl_scalar_type(N). {
+ type_ = init_decl_type(N->type, N->text);
+ type_->token = N;
+}
/* structs ! */
decl_type(type_) ::= STRUCT(S) NAME(T). {
type_ = init_decl_type(S->type, T->text);
type_->token = T;
free(S);
}
-decl_type(type_) ::= LONG(L) DOUBLE(D). {
- PSI_Token *T = PSI_TokenCat(2, L, D);
- type_ = init_decl_type(T->type, T->text);
- type_->token = T;
- free(L);
- free(D);
-}
%token_class decl_type_token FLOAT DOUBLE INT8 UINT8 INT16 UINT16 INT32 UINT32 INT64 UINT64 NAME.
%type decl_type {decl_type*}
%destructor decl_type {free_decl_type($$);}
--- /dev/null
+--TEST--
+parse dump
+--SKIPIF--
+<?php
+extension_loaded("psi") or die("skip - need ext/psi");
+?>
+--FILE--
+===TEST===
+<?php
+echo shell_exec("PSI_DUMP=1 ".PHP_BINARY." -r '' > ".__DIR__."/dump.psi");
+var_dump(file_exists(__DIR__."/dump.psi"));
+echo shell_exec(PHP_BINARY." -d psi.directory=".__DIR__." -r ''");
+?>
+===DONE===
+--EXPECT--
+===TEST===
+bool(true)
+===DONE===
+--CLEAN--
+<?php
+@unlink(__DIR__."/dump.psi");
+?>
\ No newline at end of file