From: Michael Wallner Date: Mon, 18 Jan 2016 11:14:33 +0000 (+0100) Subject: flush X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=772c1e688a51b32331fae7993429b3a03d766d8d;p=m6w6%2Fext-psi flush --- diff --git a/TODO b/TODO index d658c42..ee63abe 100644 --- a/TODO +++ b/TODO @@ -4,3 +4,5 @@ * check out jit-dynamic * fix arginfo with nullable types * pemalloc +* unions +* callbacks and function pointers diff --git a/config.m4 b/config.m4 index 817887d..9cd22a3 100644 --- a/config.m4 +++ b/config.m4 @@ -1,6 +1,12 @@ PHP_ARG_ENABLE(psi, whether to enable PHP System Interface support, [ --enable-psi Enable PHP System Interface support]) +PHP_ARG_WITH(psi-libjit, where to find libjit, +[ --with-psi-libjit=DIR PSI: path to libjit], [ ], [ ]) + +PHP_ARG_WITH(psi-libffi, where to find libffi, +[ --with-psi-libffi=DIR PSI: path to libffi], [ ], [ ]) + PHP_PSI_SRCDIR=PHP_EXT_SRCDIR(psi) PHP_PSI_BUILDDIR=PHP_EXT_BUILDDIR(psi) diff --git a/m4/psi.m4 b/m4/psi.m4 index 4729740..ae6c81a 100644 --- a/m4/psi.m4 +++ b/m4/psi.m4 @@ -1,3 +1,4 @@ +dnl Generated headers with pre-defined types, structs, consts and decls. PSI_STDINC=$PHP_PSI_SRCDIR/php_psi_stdinc.h PSI_TYPES=$PHP_PSI_SRCDIR/php_psi_types.h PSI_STRUCTS=$PHP_PSI_SRCDIR/php_psi_structs.h @@ -7,6 +8,10 @@ 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 +dnl PSI_CONFIG_INIT() +dnl Creates stubs of the headers with pre-defined types etc. +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 ]) +dnl PSI_CONFIG_DONE() +dnl Finish the headers with the pre-defined types etc. AC_DEFUN(PSI_CONFIG_DONE, [ cat >$PSI_STDINC < -#endif -EOF -} - +dnl PSI_INCLUDES() +dnl Expands to a complete list of include statements including +dnl AC_INCLUDES_DEFAULT(). AC_DEFUN(PSI_INCLUDES, [AC_INCLUDES_DEFAULT() #ifdef HAVE_ERRNO_H # include @@ -141,12 +141,18 @@ AC_DEFUN(PSI_INCLUDES, [AC_INCLUDES_DEFAULT() #endif ]) +dnl PSI_LEMON() +dnl Declare $LEMON precious, and check for a `lemon` in $PATH. AC_DEFUN(PSI_LEMON, [ AC_ARG_VAR(LEMON, The lemon parser generator of the SQLite project) AC_PATH_PROG(LEMON, lemon, ./lemon) PHP_SUBST(LEMON) ]) +dnl PSI_PKG_CONFIG() +dnl Check for `pkg-config` and add possible libjit and libffi directories to +dnl $PKG_CONFIG_PATH, because those libs often ship with headers etc. in +dnl arch-dependent locations. AC_DEFUN([PSI_PKG_CONFIG], [ if test -z "$PKG_CONFIG" then @@ -155,13 +161,25 @@ AC_DEFUN([PSI_PKG_CONFIG], [ export PKG_CONFIG_PATH="$PHP_PSI_LIBFFI/lib/pkgconfig:$PHP_PSI_LIBJIT/lib/pkgconfig:$PKG_CONFIG_PATH" ]) +dnl PSI_SH_TEST_SIZEOF(type) +dnl `if` condition to test if $ac_cv_sizeof_$1 is greater than 0. +AC_DEFUN([PSI_SH_TEST_SIZEOF], [test -n "$AS_TR_SH([ac_cv_sizeof_]$1)" && test "$AS_TR_SH([ac_cv_sizeof_]$1)" -gt 0]) + +dnl PSI_CHECK_SIZEOF(type, special-includes) +dnl AC_CHECK_SIZEOF wrapper with PSI_INCLUDES +dnl Defines psi\\SIZEOF_ pre-defined constant in $PSI_CONSTS. AC_DEFUN(PSI_CHECK_SIZEOF, [ - AC_CHECK_SIZEOF($1, [], $2) - if test "$AS_TR_SH([ac_cv_sizeof_]$1)"; then - add_int_const "AS_TR_CPP([SIZEOF_]$1)" "$AS_TR_SH([ac_cv_sizeof_]$1)" + AC_CHECK_SIZEOF($1, [], PSI_INCLUDES + $2) + if PSI_SH_TEST_SIZEOF($1); then + psi_add_int_const "AS_TR_CPP([SIZEOF_]$1)" "$AS_TR_SH([ac_cv_sizeof_]$1)" fi ]) +dnl PSI_CHECK_OFFSETOF(struct, element) +dnl Check the offset of a struct element, implemented in the similar manner +dnl like AC_CHECK_SIZEOF. +dnl AC_DEFINEs OFFSETOF__. AC_DEFUN(PSI_CHECK_OFFSETOF, [ _AC_CACHE_CHECK_INT( [offset of $2 in $1], @@ -177,9 +195,23 @@ AC_DEFUN(PSI_CHECK_OFFSETOF, [ ) ]) +dnl PSI_COMPUTE_STR(variable, string or expression) +dnl Compute a string constant value in a similar manner like AC_COMPUTE_INT. +AC_DEFUN(PSI_COMPUTE_STR, [ + AC_TRY_RUN( + PSI_INCLUDES + [int main() { + return EOF == fputs($2, fopen("conftest.out", "w")); + } + ], [ + eval $1=\\\"`cat conftest.out`\\\" + ]) +]) + +dnl PSI_CHECK_LIBJIT() +dnl Check for libjit in $PHP_PSI_LIBJIT or standard locations +dnl AC_DEFINEs HAVE_LIBJIT. AC_DEFUN(PSI_CHECK_LIBJIT, [ - PHP_ARG_WITH(psi-libjit, where to find libjit, - [ --with-psi-libjit=DIR PSI: path to libjit], [ ], [ ]) AC_CACHE_CHECK(for libjit, psi_cv_libjit_dir, [ for psi_cv_libjit_dir in $PHP_PSI_LIBJIT {/usr{,/local},/opt}{,/libjit} do @@ -200,8 +232,15 @@ AC_DEFUN(PSI_CHECK_LIBJIT, [ fi ]) -PHP_ARG_WITH(psi-libffi, where to find libffi, -[ --with-psi-libffi=DIR PSI: path to libffi], [ ], [ ]) +dnl PSI_CHECK_LIBFFI() +dnl Check for libffi with `pkg-config`. If that fails, `configure` looks into +dnl $PHP_PSI_LIBFFI or standard locations to find libjit deps. +dnl Checks for availability of recent closure API: +dnl \ffi_closure_alloc and \ffi_prep_closure. +dnl Checks for availability of recent vararg API: +dnl \ffi_prep_cif_var. +dnl AC_DEFINEs HAVE_LIBFFI, PSI_HAVE_FFI_CLOSURE_ALLOC, +dnl PSI_HAVE_FFI_PREP_CLOSURE and PSI_HAVE_FFO_PREP_VIF_VAR. AC_DEFUN(PSI_CHECK_LIBFFI, [ AC_REQUIRE([PSI_PKG_CONFIG])dnl @@ -212,6 +251,7 @@ AC_DEFUN(PSI_CHECK_LIBFFI, [ else psi_cv_libffi=false fi]) + if $psi_cv_libffi then AC_MSG_CHECKING(for libffi) @@ -257,15 +297,3 @@ AC_DEFUN(PSI_CHECK_LIBFFI, [ ], [ ], -L$psi_cv_libffi_dir/$PHP_LIBDIR) ]) - -dnl PSI_COMPUTE_STR(variable, string or expression) -AC_DEFUN(PSI_COMPUTE_STR, [ - AC_TRY_RUN( - PSI_INCLUDES - [int main() { - return EOF == fputs($2, fopen("conftest.out", "w")); - } - ], [ - eval $1=\\\"`cat conftest.out`\\\" - ]) -]) diff --git a/m4/psi_const.m4 b/m4/psi_const.m4 index 79373d3..71adb03 100644 --- a/m4/psi_const.m4 +++ b/m4/psi_const.m4 @@ -1,12 +1,18 @@ -# add_str_const(name, value) -add_str_const() { +# psi_add_str_const(name, value) +# Add a pre-defined string constant to $PSI_CONSTS +psi_add_str_const() { cat >>$PSI_CONSTS <<<" {PSI_T_STRING, \"string\", \"psi\\\\$1\", $2, PSI_T_QUOTED_STRING}, " } -# add_int_const(name, value) -add_int_const() { + +# psi_add_int_const(name, value) +# Add a pre-defined int constant to $PSI_CONSTS +psi_add_int_const() { cat >>$PSI_CONSTS <<<" {PSI_T_INT, \"int\", \"psi\\\\$1\", \"$2\", PSI_T_NUMBER}, " } + dnl PSI_CONST(const name, type) +dnl Check the value of a str/int constant and add it to the list of pre-defined +dnl constants. AC_DEFUN(PSI_CONST, [ AC_CACHE_CHECK(value of $1, psi_cv_const_$1, [ psi_const_val= @@ -29,10 +35,10 @@ AC_DEFUN(PSI_CONST, [ then case $2 in str*) - add_str_const "$1" "$psi_cv_const_$1" + psi_add_str_const "$1" "$psi_cv_const_$1" ;; int) - add_int_const "$1" "$psi_cv_const_$1" + psi_add_int_const "$1" "$psi_cv_const_$1" ;; esac fi diff --git a/m4/psi_decl.m4 b/m4/psi_decl.m4 index c331bbe..92da292 100644 --- a/m4/psi_decl.m4 +++ b/m4/psi_decl.m4 @@ -1,6 +1,30 @@ -AC_DEFUN(PSI_REDIR, [psi_symbol=ifelse([$2],[],[$1],[$2]) - cat >>$PSI_REDIRS <<<" {\"$1\", (void(*)(void))$psi_symbol}, "]) +# psi_add_redir(name, symbol) +# Add a function redirection to $PSI_REDIRS. +psi_add_redir() { + cat >>$PSI_REDIRS <<<" {\"$1\", (void(*)(void))$2}, " +} +# psi_add_decl(decl, options) +# Add a pre-defined decl to $PSI_VA_DECLS/$PSI_DECLS. +psi_add_decl() { + case "$2" in + *vararg*) + cat >>$PSI_VA_DECLS <<<" $1, {0}, " + ;; + *) + cat >>$PSI_DECLS <<<" $1, {0}, " + ;; + esac +} + +dnl PSI_REDIR(name, custom symbol) +dnl Create a function redirection to an optional custom symbol. +AC_DEFUN(PSI_REDIR, [ + psi_add_redir $1 ifelse([$2],[],[$1],[$2]) +]) + +dnl PSI_FUNC_LIBC_MAIN() +dnl Check for the platforms default stub in executables. AC_DEFUN(PSI_FUNC_LIBC_MAIN, [ AC_REQUIRE([AC_PROG_NM]) AC_REQUIRE([AC_PROG_AWK]) @@ -14,6 +38,7 @@ AC_DEFUN(PSI_FUNC_LIBC_MAIN, [ ]) dnl PSI_FUNC(fn, action-if-yes, action-if-no) +dnl Check for a possible function redirection. AC_DEFUN(PSI_FUNC, [ AC_REQUIRE([PSI_FUNC_LIBC_MAIN]) psi_symbol=$1 @@ -40,6 +65,8 @@ AC_DEFUN(PSI_FUNC, [ esac ]) +dnl PSI_DECL_ARG(decl arg) +dnl INTERNAL: build psi_decl_args AC_DEFUN(PSI_DECL_ARG, [ m4_define([member_name], PSI_VAR_NAME($1)) m4_define([member_type], PSI_VAR_TYPE($1)) @@ -52,6 +79,9 @@ AC_DEFUN(PSI_DECL_ARG, [ ]) dnl PSI_DECL(type func, args, flags) +dnl Check for a function or macro declaration. +dnl Adds a pre-defined (vararg) decl to $PSI_VA_DECLS/$PSI_DECLS. +dnl Calls PSI_MACRO if PSI_FUNC fails. AC_DEFUN(PSI_DECL, [ psi_decl_args= PSI_DECL_ARG($1) @@ -60,15 +90,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, [ - cat >>$PSI_VA_DECLS <<<" $psi_decl_args, {0}, " - ], [ - cat >>$PSI_DECLS <<<" $psi_decl_args, {0}, " - ]) + psi_add_decl "$psi_decl_args" $3 ], [ PSI_MACRO($1, $2, [ - ifelse([$3], vararg, AC_MSG_ERROR(varargs macro support is not implemented),[]) - cat >>$PSI_DECLS <<<" $psi_decl_args, {0}, " + ifelse([$3], vararg, [ + AC_MSG_ERROR(varargs macro support is not implemented) + ],[ + psi_add_decl "$psi_decl_args" + ]) ]) ]) ]) diff --git a/m4/psi_macro.m4 b/m4/psi_macro.m4 index 0bae220..337a7e5 100644 --- a/m4/psi_macro.m4 +++ b/m4/psi_macro.m4 @@ -1,3 +1,9 @@ +# psi_add_macro(macro) +# Add a pre-defined macro function to $PSI_MACROS. +psi_add_macro() { + cat >>$PSI_MACROS <<<"$1" +} + dnl PSI_MACRO(macro, decl args, action-if-true) AC_DEFUN(PSI_MACRO, [ AC_CHECK_DECL(PSI_VAR_NAME($1)$2, [ @@ -27,8 +33,7 @@ AC_DEFUN(PSI_MACRO, [ ], [ macro_body="return $macro_name$macro_call;" ]) - psi_macro="$macro_type psi_macro_$macro_name$macro_decl { $macro_body }" - cat >>$PSI_MACROS <<<"$psi_macro" + psi_add_macro "$macro_type psi_macro_$macro_name$macro_decl { $macro_body }" PSI_REDIR($macro_name, psi_macro_$macro_name) ], [], PSI_INCLUDES) ]) diff --git a/m4/psi_struct.m4 b/m4/psi_struct.m4 index ce04f3d..fcee59c 100644 --- a/m4/psi_struct.m4 +++ b/m4/psi_struct.m4 @@ -1,24 +1,36 @@ +# psi_add_struct(struct members) +# Add a pre-defined struct to $PSI_STRUCTS. +psi_add_struct() { + cat >>$PSI_STRUCTS <<<" $1, {0}, " +} + +dnl PSI_STRUCT_MEMBER(struct name, decl member) +dnl INTERNAL: build $psi_struct_members AC_DEFUN(PSI_STRUCT_MEMBER, [ m4_define([member_name], PSI_VAR_NAME($2)) m4_define([member_type], PSI_VAR_TYPE($2)) - PSI_CHECK_SIZEOF(AS_TR_SH($1)[_]member_name, PSI_INCLUDES + PSI_CHECK_SIZEOF(AS_TR_SH($1)[_]member_name, [#define ]AS_TR_SH($1)[_]member_name (($1 *)0)->member_name ) - if test -n "$AS_TR_SH([ac_cv_sizeof_$1][_]member_name)" \ - && test "$AS_TR_SH([ac_cv_sizeof_$1][_]member_name)" -gt 0; then + if PSI_SH_TEST_SIZEOF($1 member_name); then PSI_CHECK_OFFSETOF($1, member_name) PSI_TYPE_INDIRECTION($2, [$AS_TR_SH([ac_cv_sizeof_]$1[_]member_name)], pl, as) psi_struct_members="[$psi_struct_members, {]PSI_TYPE_PAIR(member_type)[, \"]member_name[\", $]AS_TR_SH([ac_cv_offsetof_]$1[_]member_name)[, $]AS_TR_SH([ac_cv_sizeof_]$1[_]member_name), $pl, $as[}]" fi ]) +dnl PSI_STRUCT(struct name, struct members) +dnl Check a struct and its members and add a pre-defined struct and possibly a +dnl pre-defined type for this struct. +dnl Calls PSI_CHECK_SIZEOF for the struct and each member. +dnl Calls PSI_CHECK_OFFSETOF and PSI_TYPE_INDIRECTON for each member. AC_DEFUN(PSI_STRUCT, [ - PSI_CHECK_SIZEOF($1, PSI_INCLUDES) + PSI_CHECK_SIZEOF($1) 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)]) - cat >>$PSI_STRUCTS <<<" $psi_struct_members, {0}, " + psi_add_struct "$psi_struct_members" if test "$1" = "$psi_struct_name"; then - cat >>$PSI_TYPES <<<" {PSI_T_STRUCT, \"$1\", \"$1\"}, " + psi_add_type "{PSI_T_STRUCT, \"$1\", \"$1\"}" fi ]) diff --git a/m4/psi_type.m4 b/m4/psi_type.m4 index 85750d9..dad3b67 100644 --- a/m4/psi_type.m4 +++ b/m4/psi_type.m4 @@ -1,4 +1,12 @@ +# psi_add_type(type triplet) +# Add a pre-defined type to $PSI_TYPES. +psi_add_type() { + cat >>$PSI_TYPES <<<" $1, " +} + # psi_type_pair(type, size) +# Output a PSI_T_, \"\" tuple. +# Uses stdint types when possible. psi_type_pair() { local psi_type_name=`tr -cd A-Za-z0-9_ <<<$1` local psi_type_lower=`tr A-Z a-z <<<$psi_type_name` @@ -7,7 +15,6 @@ 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" ;; struct*) echo "PSI_T_STRUCT, \"$2\"" @@ -22,30 +29,39 @@ psi_type_pair() { } dnl PSI_TYPE(type name, basic type) +dnl Check for a specific type, optionally referring to a basic type. +dnl Calls AC_TYPE_ (if defined) and PSI_CHECK_SIZEOF. +dnl If the basic type is just specified as "int" (in contrast to "sint" or +dnl "uint"), AX_CHECK_SIGN is used to discover signedness of the type. +dnl Defines a pre-defined type in $PSI_TYPES. AC_DEFUN(PSI_TYPE, [ ifdef(AS_TR_CPP(AC_TYPE_$1), AS_TR_CPP(AC_TYPE_$1)) PSI_CHECK_SIZEOF($1, PSI_INCLUDES) psi_basic_type=AS_TR_SH($2) case $psi_basic_type in int) - AX_CHECK_SIGN($1, :, [ - psi_basic_type=uint - ], PSI_INCLUDES) + AX_CHECK_SIGN($1, :, [psi_basic_type=uint], PSI_INCLUDES) ;; sint) psi_basic_type=int ;; esac - if test "$2" && test "$AS_TR_SH([ac_cv_sizeof_]$1)" -gt 0; then + if test "$2" && PSI_SH_TEST_SIZEOF($1); then AS_TR_SH(psi_basic_type_$1)=$psi_basic_type - cat >>$PSI_TYPES <<<" {`psi_type_pair $psi_basic_type $AS_TR_SH([ac_cv_sizeof_]$1)`, \"$1\"}, " + psi_add_type "{`psi_type_pair $psi_basic_type $AS_TR_SH([ac_cv_sizeof_]$1)`, \"$1\"}" + #cat >>$PSI_TYPES <<<"{`psi_type_pair $psi_basic_type $AS_TR_SH([ac_cv_sizeof_]$1)`, \"$1\"}, " fi ]) +dnl PSI_OPAQUE_TYPE(type name) +dnl Checks a type for being a scalar, a struct or a pointer type. +dnl Calls AC_TYPE_ (if defined) and PSI_CHECK_SIZEOF. +dnl Defines a pre-defined type in $PSI_TYPES and a pre-defined struct in +dnl $PSI_STRUCTS if the type is a struct. AC_DEFUN(PSI_OPAQUE_TYPE, [ ifdef(AS_TR_CPP(AC_TYPE_$1), AS_TR_CPP(AC_TYPE_$1)) PSI_CHECK_SIZEOF($1, PSI_INCLUDES) - if test "$AS_TR_SH([ac_cv_sizeof_]$1)" -gt 0; then + if PSI_SH_TEST_SIZEOF($1); then psi_type_class= AC_CACHE_CHECK(type class of $1, AS_TR_SH([psi_cv_type_class_]$1), [ AC_TRY_COMPILE(PSI_INCLUDES, [char test@<:@($1)1@:>@;], [ @@ -65,13 +81,16 @@ AC_DEFUN(PSI_OPAQUE_TYPE, [ ]) case "$AS_TR_SH([psi_cv_type_class_]$1)" in scalar) - PSI_TYPE($1, int) + 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\"}" + #cat >>$PSI_TYPES <<<" {`psi_type_pair $psi_basic_type $AS_TR_SH([ac_cv_sizeof_]$1)`, \"$1\"}, " ;; struct) PSI_STRUCT($1) ;; pointer*) - cat >>$PSI_TYPES <<<" {PSI_T_POINTER, \"void\", \"$1\"}, " + psi_add_type "{PSI_T_POINTER, \"void\", \"$1\"}" + #cat >>$PSI_TYPES <<<" {PSI_T_POINTER, \"void\", \"$1\"}, " ;; *) AC_MSG_WARN(could not detect type class of $1) @@ -80,23 +99,17 @@ AC_DEFUN(PSI_OPAQUE_TYPE, [ fi ]) -dnl unsigned char* buf[16] -> unsigned char* -dnl AC_DEFUN(PSI_VAR_TYPE, [m4_bregexp([$1], [\(\(struct \)?[^ ]+\)[ *]+[^ ]+$], [\1])]) +dnl PSI_VAR_TYPE(decl arg) +dnl Extracts the type of a decl arg, e.g. dnl unsigned char* buf[16] -> unsigned char*. AC_DEFUN(PSI_VAR_TYPE, [m4_bregexp([$1], [^\(const \)?\(.*\) \([*]*\)[^ ]+$], [\2\3])]) -dnl unsigned char* buf[16] -> buf + +dnl PSI_VAR_NAME(decl arg) +dnl Extracts the var name of a decl arg, e.g. unsigned char* buf[16] -> buf. AC_DEFUN(PSI_VAR_NAME, [m4_bregexp(m4_bregexp([$1], [\([^ ]+\)$], [\1]), [\w+], [\&])]) -dnl PSI_TYPE_SIZE(type, pointer level, array size) -AC_DEFUN(PSI_TYPE_SIZE, [ifelse( - [$3], 0, - [ifelse([$2], 0, $AS_TR_SH([ac_cv_sizeof_]$1), $ac_cv_sizeof_void_p)], - [ifelse([$2], 1, [`expr $3 \* $AS_TR_SH([ac_cv_sizeof_]$1)`], $ac_cv_sizeof_void_p)] -)]) -dnl PSI_TYPE_BITS(type) -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) +dnl PSI_TYPE_INDIRECTION(decl arg, size, pointer_level_var, array_size_var) +dnl Calculates and assigns pointer_level and array_size of a decl arg to sh vars. AC_DEFUN(PSI_TYPE_INDIRECTION, [ - 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])]) @@ -120,15 +133,18 @@ AC_DEFUN(PSI_TYPE_INDIRECTION, [ $3=m4_incr(psi_pointer_level) $4=psi_array_size ]) - - dnl AC_MSG_RESULT([[$]$3, [$]$4]) ]) +dnl PSI_TYPE_PAIR(type) +dnl Expand to a PSI_T_, \\"\\" tuple. +dnl FIXME: There is also psi_type_pair()? AC_DEFUN(PSI_TYPE_PAIR, [m4_case(m4_bregexp([$1], [^\w+], [\&]), [void], [PSI_T_VOID, \"void\"], [struct], [PSI_T_STRUCT, \"m4_bregexp([$1], [^struct \(\w+\)], [\1])\"], [PSI_T_NAME, \"m4_bregexp([$1], [^\(\w+ \)*\w+], [\&])\"])]) +dnl PSI_CHECK_STD_TYPES() +dnl Checks for standard ANSI-C and stdint types. AC_DEFUN(PSI_CHECK_STD_TYPES, [ AC_CHECK_HEADERS(stdint.h) @@ -186,9 +202,10 @@ AC_DEFUN(PSI_CHECK_STD_TYPES, [ PSI_TYPE(unsigned long, uint) PSI_TYPE(unsigned long int, uint) PSI_TYPE(long long, int) - PSI_TYPE(long long int, 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) + dnl this must come after the check fo "unsigned long long int"; autoconf, wth? + PSI_TYPE(long long int, int) ]) diff --git a/m4/stdint.m4 b/m4/stdint.m4 index 045279d..c21c129 100644 --- a/m4/stdint.m4 +++ b/m4/stdint.m4 @@ -1,25 +1,25 @@ PSI_CHECK_STDINT() { AC_CHECK_HEADERS(stdint.h) - PSI_TYPE(int_least8_t, int) - PSI_TYPE(int_least16_t, int) - PSI_TYPE(int_least32_t, int) - PSI_TYPE(int_least64_t, int) + PSI_TYPE(int_least8_t, sint) + PSI_TYPE(int_least16_t, sint) + PSI_TYPE(int_least32_t, sint) + PSI_TYPE(int_least64_t, sint) PSI_TYPE(uint_least8_t, uint) PSI_TYPE(uint_least16_t, uint) PSI_TYPE(uint_least32_t, uint) PSI_TYPE(uint_least64_t, uint) - PSI_TYPE(int_fast8_t, int) - PSI_TYPE(int_fast16_t, int) - PSI_TYPE(int_fast32_t, int) - PSI_TYPE(int_fast64_t, int) + PSI_TYPE(int_fast8_t, sint) + PSI_TYPE(int_fast16_t, sint) + PSI_TYPE(int_fast32_t, sint) + PSI_TYPE(int_fast64_t, sint) PSI_TYPE(uint_fast8_t, uint) PSI_TYPE(uint_fast16_t, uint) PSI_TYPE(uint_fast32_t, uint) PSI_TYPE(uint_fast64_t, uint) - PSI_TYPE(intptr_t, int) + PSI_TYPE(intptr_t, sint) PSI_TYPE(uintptr_t, uint) - PSI_TYPE(intmax_t, int) + PSI_TYPE(intmax_t, sint) PSI_TYPE(uintmax_t, uint) PSI_CONST(INT8_MIN, int) diff --git a/m4/wchar.m4 b/m4/wchar.m4 index 6c5430b..2d0a1ae 100644 --- a/m4/wchar.m4 +++ b/m4/wchar.m4 @@ -2,7 +2,6 @@ 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) diff --git a/m4/wctype.m4 b/m4/wctype.m4 index 319c2fc..627b919 100644 --- a/m4/wctype.m4 +++ b/m4/wctype.m4 @@ -1,6 +1,7 @@ PSI_CHECK_WCTYPE() { AC_CHECK_HEADERS(wctype.h) + PSI_TYPE(wctype_t, int) PSI_TYPE(wctrans_t, int) PSI_DECL(int iswalnum, [(wint_t wc)]) diff --git a/src/context.c b/src/context.c index d2293fe..3f94d42 100644 --- a/src/context.c +++ b/src/context.c @@ -40,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"}, @@ -124,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; @@ -1272,7 +1279,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"); } diff --git a/src/parser.h b/src/parser.h index 8c25e88..b27fdaf 100644 --- a/src/parser.h +++ b/src/parser.h @@ -13,6 +13,8 @@ #define BSIZE 256 #define PSI_T_POINTER PSI_T_ASTERISK +#define PSI_T_LONG_DOUBLE (PSI_T_DOUBLE << 16) + typedef int token_t; /* in php_psi.h */ @@ -82,7 +84,7 @@ static inline decl_type *init_decl_type_ex(token_t type, int argc, ...) { pos = all; ptr = realloc(ptr, 1 + (all += len)); } else { - ptr = malloc(ptr, 1 + (all = len)); + ptr = malloc(1 + (all = len)); } memcpy(ptr + pos, arg, len); } @@ -1303,7 +1305,7 @@ 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, PSI_TokenAllocSize(token_len, fname_len); + T = calloc(1, PSI_TokenAllocSize(token_len, fname_len)); T->type = token_typ; T->size = token_len; T->text = &T->buf[0]; @@ -1343,7 +1345,7 @@ static inline PSI_Token *PSI_TokenCat(unsigned argc, ...) { 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) + memcpy(T->file - 1, arg->text, arg->size + 1); T->file = &T->buf[T->size + 1]; } else { T = PSI_TokenCopy(arg); diff --git a/src/parser.re b/src/parser.re index 3375a0b..70ab698 100644 --- a/src/parser.re +++ b/src/parser.re @@ -263,7 +263,10 @@ token_t PSI_ParserScan(PSI_Parser *P) 'MIXED' {RETURN(PSI_T_MIXED);} 'VOID' {RETURN(PSI_T_VOID);} 'BOOL' {RETURN(PSI_T_BOOL);} + 'CHAR' {RETURN(PSI_T_CHAR);} + 'SHORT' {RETURN(PSI_T_SHORT);} 'INT' {RETURN(PSI_T_INT);} + 'LONG' {RETURN(PSI_T_LONG);} 'FLOAT' {RETURN(PSI_T_FLOAT);} 'DOUBLE' {RETURN(PSI_T_DOUBLE);} 'INT8_T' {RETURN(PSI_T_INT8);} @@ -275,6 +278,7 @@ token_t PSI_ParserScan(PSI_Parser *P) 'INT64_T' {RETURN(PSI_T_INT64);} 'UINT64_T' {RETURN(PSI_T_UINT64);} 'UNSIGNED' {RETURN(PSI_T_UNSIGNED);} + 'SIGNED' {RETURN(PSI_T_SIGNED);} 'STRING' {RETURN(PSI_T_STRING);} 'ARRAY' {RETURN(PSI_T_ARRAY);} 'OBJECT' {RETURN(PSI_T_OBJECT);} diff --git a/src/parser_proc.h b/src/parser_proc.h index 30ad543..7fe90fd 100644 --- a/src/parser_proc.h +++ b/src/parser_proc.h @@ -9,60 +9,64 @@ #define PSI_T_LET 9 #define PSI_T_RETURN 10 #define PSI_T_LIB 11 -#define PSI_T_INT 12 -#define PSI_T_UNSIGNED 13 -#define PSI_T_EOF 14 -#define PSI_T_QUOTED_STRING 15 -#define PSI_T_EOS 16 -#define PSI_T_STRUCT 17 -#define PSI_T_LBRACE 18 -#define PSI_T_RBRACE 19 -#define PSI_T_COLON 20 -#define PSI_T_LPAREN 21 -#define PSI_T_NUMBER 22 -#define PSI_T_RPAREN 23 -#define PSI_T_BOOL 24 -#define PSI_T_FLOAT 25 -#define PSI_T_STRING 26 -#define PSI_T_CONST 27 -#define PSI_T_NSNAME 28 -#define PSI_T_EQUALS 29 -#define PSI_T_TYPEDEF 30 -#define PSI_T_VOID 31 -#define PSI_T_LBRACKET 32 -#define PSI_T_RBRACKET 33 -#define PSI_T_COMMA 34 -#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 +#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_INT8 41 +#define PSI_T_UINT8 42 +#define PSI_T_INT16 43 +#define PSI_T_UINT16 44 +#define PSI_T_INT32 45 +#define PSI_T_UINT32 46 +#define PSI_T_INT64 47 +#define PSI_T_UINT64 48 +#define PSI_T_FUNCTION 49 +#define PSI_T_NULL 50 +#define PSI_T_TRUE 51 +#define PSI_T_FALSE 52 +#define PSI_T_DOLLAR 53 +#define PSI_T_CALLOC 54 +#define PSI_T_OBJVAL 55 +#define PSI_T_ARRVAL 56 +#define PSI_T_PATHVAL 57 +#define PSI_T_STRLEN 58 +#define PSI_T_STRVAL 59 +#define PSI_T_FLOATVAL 60 +#define PSI_T_INTVAL 61 +#define PSI_T_BOOLVAL 62 +#define PSI_T_TO_OBJECT 63 +#define PSI_T_TO_ARRAY 64 +#define PSI_T_TO_STRING 65 +#define PSI_T_TO_INT 66 +#define PSI_T_TO_FLOAT 67 +#define PSI_T_TO_BOOL 68 +#define PSI_T_MIXED 69 +#define PSI_T_ARRAY 70 +#define PSI_T_OBJECT 71 +#define PSI_T_AMPERSAND 72 diff --git a/src/parser_proc.y b/src/parser_proc.y index d82a90f..b4150ae 100644 --- a/src/parser_proc.y +++ b/src/parser_proc.y @@ -28,7 +28,7 @@ void psi_error(int, const char *, int, const char *, ...); %nonassoc NAME. %left PLUS MINUS. %left SLASH ASTERISK. -%fallback NAME TEMP FREE SET LET RETURN LIB INT LONG SIGNED UNSIGNED. +%fallback NAME TEMP FREE SET LET RETURN LIB CHAR SHORT INT LONG SIGNED UNSIGNED. file ::= blocks. @@ -104,8 +104,8 @@ decl_typedef(def) ::= TYPEDEF decl_type(type) NAME(ALIAS) EOS. { 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)); +decl_typedef(def) ::= TYPEDEF VOID(V) indirection(i) NAME(ALIAS) EOS. { + def = init_decl_typedef(ALIAS->text, init_decl_type(i?PSI_T_POINTER:V->type, V->text)); def->token = ALIAS; def->type->token = V; } @@ -237,38 +237,47 @@ struct_layout(layout) ::= COLON COLON LPAREN NUMBER(POS) COMMA NUMBER(SIZ) RPARE free(SIZ); } -%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($$);} -decl_type(type_) ::= decl_type_token(T). { - type_ = init_decl_type(T->type, T->text); - type_->token = T; +/* un/signed, urgh */ +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); } -/* unsigned, urgh */ -decl_type(type_) ::= UNSIGNED(U) NAME(N). { +decl_scalar_type(type_) ::= SHORT(S). { + type_ = S; +} +decl_scalar_type(type_) ::= LONG(L) INT(I). { + type_ = PSI_TokenCat(2, L, I); + free(L); + free(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_) ::= LONG(L1) LONG(L2). { + type_ = PSI_TokenCat(2, L1, L2); + free(L1); + free(L2); +} +decl_type(type_) ::= UNSIGNED(U) decl_scalar_type(N). { PSI_Token *T = PSI_TokenCat(2, U, N); type_ = init_decl_type(T->type, T->text); type_->token = T; free(U); free(N); } -decl_type(type_) ::= SIGNED NAME(T). { +decl_type(type_) ::= SIGNED(S) decl_scalar_type(N). { + PSI_Token *T = PSI_TokenCat(2, S, N); type_ = init_decl_type(T->type, T->text); type_->token = T; - type_->name = realloc(type_->name, T->size + sizeof("signed")); - memmove(type_->name + sizeof("signed"), type_->name, T->size); - memcpy(type_->name, "signed", sizeof("signed")-1); - type_->name[sizeof("signed")] = ' '; - type_->name[T->size + sizeof("signed")] = 0; -} -/* we have to support plain int, long 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; -} -decl_type(type_) ::= LONG INT(T). { - type_ = init_decl_type(PSI_T_NAME, T->text); - type_->token = T; + free(S); + free(N); } /* structs ! */ decl_type(type_) ::= STRUCT(S) NAME(T). { @@ -276,6 +285,21 @@ decl_type(type_) ::= STRUCT(S) NAME(T). { 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($$);} +decl_type(type_) ::= decl_type_token(T). { + type_ = init_decl_type(T->type, T->text); + type_->token = T; +} + %type const_decl_type {decl_type*} %destructor const_decl_type {free_decl_type($$);}