{
zend_ffi_symbol *sym;
- if (FFI_G(symbols)) {
+ if (UNEXPECTED(FFI_G(attribute_parsing))) {
+ val->kind = ZEND_FFI_VAL_NAME;
+ val->str = name;
+ val->len = name_len;
+ return;
+ } else if (FFI_G(symbols)) {
sym = zend_hash_str_find_ptr(FFI_G(symbols), name, name_len);
if (sym && sym->kind == ZEND_FFI_SYM_CONST) {
val->i64 = sym->value;
}
break;
case attr_mode:
+ if (n == 0
+ && (val->kind == ZEND_FFI_VAL_NAME)) {
+ const char *str = val->str;
+ size_t len = val->len;
+ if (len > 4
+ && str[0] == '_'
+ && str[1] == '_'
+ && str[len-2] == '_'
+ && str[len-1] == '_') {
+ str += 2;
+ len -= 4;
+ }
+ // TODO: Add support for vector type 'VnXX' ???
+ if (len == 2) {
+ if (str[1] == 'I') {
+ if (dcl->flags & (ZEND_FFI_DCL_TYPE_SPECIFIERS-(ZEND_FFI_DCL_CHAR|ZEND_FFI_DCL_SHORT|ZEND_FFI_DCL_INT|ZEND_FFI_DCL_LONG|ZEND_FFI_DCL_LONG_LONG|ZEND_FFI_DCL_SIGNED|ZEND_FFI_DCL_UNSIGNED))) {
+ /* inappropriate type */
+ } else if (str[0] == 'Q') {
+ dcl->flags &= ~(ZEND_FFI_DCL_CHAR|ZEND_FFI_DCL_SHORT|ZEND_FFI_DCL_INT|ZEND_FFI_DCL_LONG|ZEND_FFI_DCL_LONG_LONG);
+ dcl->flags |= ZEND_FFI_DCL_CHAR;
+ break;
+ } else if (str[0] == 'H') {
+ dcl->flags &= ~(ZEND_FFI_DCL_CHAR|ZEND_FFI_DCL_SHORT|ZEND_FFI_DCL_INT|ZEND_FFI_DCL_LONG|ZEND_FFI_DCL_LONG_LONG);
+ dcl->flags |= ZEND_FFI_DCL_SHORT;
+ break;
+ } else if (str[0] == 'S') {
+ dcl->flags &= ~(ZEND_FFI_DCL_CHAR|ZEND_FFI_DCL_SHORT|ZEND_FFI_DCL_INT|ZEND_FFI_DCL_LONG|ZEND_FFI_DCL_LONG_LONG);
+ dcl->flags |= ZEND_FFI_DCL_INT;
+ break;
+ } else if (str[0] == 'D') {
+ dcl->flags &= ~(ZEND_FFI_DCL_CHAR|ZEND_FFI_DCL_SHORT|ZEND_FFI_DCL_INT|ZEND_FFI_DCL_LONG|ZEND_FFI_DCL_LONG_LONG);
+ if (sizeof(long) == 8) {
+ dcl->flags |= ZEND_FFI_DCL_LONG;
+ } else {
+ dcl->flags |= ZEND_FFI_DCL_LONG_LONG;
+ }
+ break;
+ }
+ } else if (str[1] == 'F') {
+ if (dcl->flags & (ZEND_FFI_DCL_TYPE_SPECIFIERS-(ZEND_FFI_DCL_LONG|ZEND_FFI_DCL_FLOAT|ZEND_FFI_DCL_DOUBLE))) {
+ /* inappropriate type */
+ } else if (str[0] == 'S') {
+ dcl->flags &= ~(ZEND_FFI_DCL_LONG|ZEND_FFI_DCL_FLOAT|ZEND_FFI_DCL_DOUBLE);
+ dcl->flags |= ZEND_FFI_DCL_FLOAT;
+ break;
+ } else if (str[0] == 'D') {
+ dcl->flags &= ~(ZEND_FFI_DCL_LONG|ZEND_FFI_DCL_FLOAT|ZEND_FFI_DCL_DOUBLE);
+ dcl->flags |= ZEND_FFI_DCL_DOUBLE;
+ break;
+ }
+ }
+ }
+ }
+ zend_ffi_parser_error("unsupported 'mode' value at line %d", FFI_G(line));
// TODO: ???
case attr_unsupported:
zend_ffi_parser_error("unsupported attribute '%.*s' at line %d", name_len, name, FFI_G(line));
{size_t name_len;}
{int n;}
{zend_ffi_val val;}
+ {zend_bool orig_attribute_parsing;}
( ID(&name, &name_len)
( /* empty */
{zend_ffi_add_attribute(dcl, name, name_len);}
| "("
+ {orig_attribute_parsing = FFI_G(attribute_parsing);}
+ {FFI_G(attribute_parsing) = 1;}
assignment_expression(&val)
{zend_ffi_add_attribute_value(dcl, name, name_len, 0, &val);}
{n = 0;}
assignment_expression(&val)
{zend_ffi_add_attribute_value(dcl, name, name_len, ++n, &val);}
)*
+ {FFI_G(attribute_parsing) = orig_attribute_parsing;}
")"
)
| "const"
int zend_ffi_parse_decl(const char *str, size_t len) {
if (SETJMP(FFI_G(bailout))==0) {
FFI_G(allow_vla) = 0;
+ FFI_G(attribute_parsing) = 0;
yy_buf = (unsigned char*)str;
yy_end = yy_buf + len;
parse();
if (SETJMP(FFI_G(bailout))==0) {
FFI_G(allow_vla) = 0;
+ FFI_G(attribute_parsing) = 0;
yy_pos = yy_text = yy_buf = (unsigned char*)str;
yy_end = yy_buf + len;
yy_line = 1;
size_t name_len;
int n;
zend_ffi_val val;
+ zend_bool orig_attribute_parsing;
if (sym == YY_ID || sym == YY_CONST || sym == YY___CONST || sym == YY___CONST__) {
if (sym == YY_ID) {
sym = parse_ID(sym, &name, &name_len);
zend_ffi_add_attribute(dcl, name, name_len);
} else if (sym == YY__LPAREN) {
sym = get_sym();
+ orig_attribute_parsing = FFI_G(attribute_parsing);
+ FFI_G(attribute_parsing) = 1;
sym = parse_assignment_expression(sym, &val);
zend_ffi_add_attribute_value(dcl, name, name_len, 0, &val);
n = 0;
sym = parse_assignment_expression(sym, &val);
zend_ffi_add_attribute_value(dcl, name, name_len, ++n, &val);
}
+ FFI_G(attribute_parsing) = orig_attribute_parsing;
if (sym != YY__RPAREN) {
yy_error_sym("')' expected, got", sym);
}
int zend_ffi_parse_decl(const char *str, size_t len) {
if (SETJMP(FFI_G(bailout))==0) {
FFI_G(allow_vla) = 0;
+ FFI_G(attribute_parsing) = 0;
yy_buf = (unsigned char*)str;
yy_end = yy_buf + len;
parse();
if (SETJMP(FFI_G(bailout))==0) {
FFI_G(allow_vla) = 0;
+ FFI_G(attribute_parsing) = 0;
yy_pos = yy_text = yy_buf = (unsigned char*)str;
yy_end = yy_buf + len;
yy_line = 1;
HashTable *symbols;
HashTable *tags;
zend_bool allow_vla;
+ zend_bool attribute_parsing;
zend_bool persistent;
uint32_t default_type_attr;
ZEND_END_MODULE_GLOBALS(ffi)
ZEND_FFI_VAL_LONG_DOUBLE,
ZEND_FFI_VAL_CHAR,
ZEND_FFI_VAL_STRING,
+ ZEND_FFI_VAL_NAME, /* attribute value */
} zend_ffi_val_kind;
#ifdef HAVE_LONG_DOUBLE
--- /dev/null
+--TEST--
+FFI 044: mode attribute
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--INI--
+ffi.enable=1
+--FILE--
+<?php
+$ffi = FFI::cdef("
+typedef int a __attribute__ ((__mode__ (__QI__)));
+typedef int b __attribute__ ((__mode__ (__HI__)));
+typedef int c __attribute__ ((__mode__ (__SI__)));
+typedef int d __attribute__ ((__mode__ (__DI__)));
+typedef float e __attribute__ ((__mode__ (__SF__)));
+typedef float f __attribute__ ((__mode__ (__DF__)));
+");
+var_dump(FFI::sizeof($ffi->new("a")));
+var_dump(FFI::sizeof($ffi->new("b")));
+var_dump(FFI::sizeof($ffi->new("c")));
+var_dump(FFI::sizeof($ffi->new("d")));
+var_dump(FFI::sizeof($ffi->new("e")));
+var_dump(FFI::sizeof($ffi->new("f")));
+?>
+--EXPECT--
+int(1)
+int(2)
+int(4)
+int(8)
+int(4)
+int(8)