1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Dmitry Stogov <dmitry@zend.com> |
14 +----------------------------------------------------------------------+
15 */
16
17 #ifndef PHP_FFI_H
18 #define PHP_FFI_H
19
20 extern zend_module_entry ffi_module_entry;
21 #define phpext_ffi_ptr &ffi_module_entry
22
23 typedef enum _zend_ffi_api_restriction {
24 ZEND_FFI_DISABLED = 0, /* completely disabled */
25 ZEND_FFI_ENABLED = 1, /* enabled everywhere */
26 ZEND_FFI_PRELOAD = 2, /* enabled only in preloaded scripts and CLI */
27 } zend_ffi_api_restriction;
28
29 typedef struct _zend_ffi_type zend_ffi_type;
30
31 ZEND_BEGIN_MODULE_GLOBALS(ffi)
32 zend_ffi_api_restriction restriction;
33 bool is_cli;
34
35 /* predefined ffi_types */
36 HashTable types;
37
38 /* preloading */
39 char *preload;
40 HashTable *scopes; /* list of preloaded scopes */
41
42 /* callbacks */
43 HashTable *callbacks;
44
45 /* weak type references */
46 HashTable *weak_types;
47
48 /* ffi_parser */
49 JMP_BUF bailout;
50 unsigned const char *buf;
51 unsigned const char *end;
52 unsigned const char *pos;
53 unsigned const char *text;
54 int line;
55 HashTable *symbols;
56 HashTable *tags;
57 bool allow_vla;
58 bool attribute_parsing;
59 bool persistent;
60 uint32_t default_type_attr;
61 ZEND_END_MODULE_GLOBALS(ffi)
62
63 ZEND_EXTERN_MODULE_GLOBALS(ffi)
64
65 #ifdef PHP_WIN32
66 # define PHP_FFI_API __declspec(dllexport)
67 #elif defined(__GNUC__) && __GNUC__ >= 4
68 # define PHP_FFI_API __attribute__ ((visibility("default")))
69 #else
70 # define PHP_FFI_API
71 #endif
72
73 #define FFI_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(ffi, v)
74
75 #define ZEND_FFI_DCL_VOID (1<<0)
76 #define ZEND_FFI_DCL_CHAR (1<<1)
77 #define ZEND_FFI_DCL_SHORT (1<<2)
78 #define ZEND_FFI_DCL_INT (1<<3)
79 #define ZEND_FFI_DCL_LONG (1<<4)
80 #define ZEND_FFI_DCL_LONG_LONG (1<<5)
81 #define ZEND_FFI_DCL_FLOAT (1<<6)
82 #define ZEND_FFI_DCL_DOUBLE (1<<7)
83 #define ZEND_FFI_DCL_SIGNED (1<<8)
84 #define ZEND_FFI_DCL_UNSIGNED (1<<9)
85 #define ZEND_FFI_DCL_BOOL (1<<10)
86 #define ZEND_FFI_DCL_COMPLEX (1<<11)
87
88 #define ZEND_FFI_DCL_STRUCT (1<<12)
89 #define ZEND_FFI_DCL_UNION (1<<13)
90 #define ZEND_FFI_DCL_ENUM (1<<14)
91 #define ZEND_FFI_DCL_TYPEDEF_NAME (1<<15)
92
93 #define ZEND_FFI_DCL_TYPE_SPECIFIERS \
94 (ZEND_FFI_DCL_VOID|ZEND_FFI_DCL_CHAR|ZEND_FFI_DCL_SHORT \
95 |ZEND_FFI_DCL_INT|ZEND_FFI_DCL_LONG|ZEND_FFI_DCL_LONG_LONG \
96 |ZEND_FFI_DCL_FLOAT|ZEND_FFI_DCL_DOUBLE|ZEND_FFI_DCL_SIGNED \
97 |ZEND_FFI_DCL_UNSIGNED|ZEND_FFI_DCL_BOOL|ZEND_FFI_DCL_COMPLEX \
98 |ZEND_FFI_DCL_STRUCT|ZEND_FFI_DCL_UNION|ZEND_FFI_DCL_ENUM \
99 |ZEND_FFI_DCL_TYPEDEF_NAME)
100
101 #define ZEND_FFI_DCL_TYPEDEF (1<<16)
102 #define ZEND_FFI_DCL_EXTERN (1<<17)
103 #define ZEND_FFI_DCL_STATIC (1<<18)
104 #define ZEND_FFI_DCL_AUTO (1<<19)
105 #define ZEND_FFI_DCL_REGISTER (1<<20)
106
107 #define ZEND_FFI_DCL_STORAGE_CLASS \
108 (ZEND_FFI_DCL_TYPEDEF|ZEND_FFI_DCL_EXTERN|ZEND_FFI_DCL_STATIC \
109 |ZEND_FFI_DCL_AUTO|ZEND_FFI_DCL_REGISTER)
110
111 #define ZEND_FFI_DCL_CONST (1<<21)
112 #define ZEND_FFI_DCL_RESTRICT (1<<22)
113 #define ZEND_FFI_DCL_VOLATILE (1<<23)
114 #define ZEND_FFI_DCL_ATOMIC (1<<24)
115
116 #define ZEND_FFI_DCL_TYPE_QUALIFIERS \
117 (ZEND_FFI_DCL_CONST|ZEND_FFI_DCL_RESTRICT|ZEND_FFI_DCL_VOLATILE \
118 |ZEND_FFI_DCL_ATOMIC)
119
120 #define ZEND_FFI_DCL_INLINE (1<<25)
121 #define ZEND_FFI_DCL_NO_RETURN (1<<26)
122
123 #define ZEND_FFI_ABI_DEFAULT 0
124
125 #define ZEND_FFI_ABI_CDECL 1 // FFI_DEFAULT_ABI
126 #define ZEND_FFI_ABI_FASTCALL 2 // FFI_FASTCALL
127 #define ZEND_FFI_ABI_THISCALL 3 // FFI_THISCALL
128 #define ZEND_FFI_ABI_STDCALL 4 // FFI_STDCALL
129 #define ZEND_FFI_ABI_PASCAL 5 // FFI_PASCAL
130 #define ZEND_FFI_ABI_REGISTER 6 // FFI_REGISTER
131 #define ZEND_FFI_ABI_MS 7 // FFI_MS_CDECL
132 #define ZEND_FFI_ABI_SYSV 8 // FFI_SYSV
133 #define ZEND_FFI_ABI_VECTORCALL 9 // FFI_VECTORCALL
134
135 #define ZEND_FFI_ATTR_CONST (1<<0)
136 #define ZEND_FFI_ATTR_INCOMPLETE_TAG (1<<1)
137 #define ZEND_FFI_ATTR_VARIADIC (1<<2)
138 #define ZEND_FFI_ATTR_INCOMPLETE_ARRAY (1<<3)
139 #define ZEND_FFI_ATTR_VLA (1<<4)
140 #define ZEND_FFI_ATTR_UNION (1<<5)
141 #define ZEND_FFI_ATTR_PACKED (1<<6)
142 #define ZEND_FFI_ATTR_MS_STRUCT (1<<7)
143 #define ZEND_FFI_ATTR_GCC_STRUCT (1<<8)
144
145 #define ZEND_FFI_ATTR_PERSISTENT (1<<9)
146 #define ZEND_FFI_ATTR_STORED (1<<10)
147
148 #define ZEND_FFI_STRUCT_ATTRS \
149 (ZEND_FFI_ATTR_UNION|ZEND_FFI_ATTR_PACKED|ZEND_FFI_ATTR_MS_STRUCT \
150 |ZEND_FFI_ATTR_GCC_STRUCT)
151
152 #define ZEND_FFI_ENUM_ATTRS \
153 (ZEND_FFI_ATTR_PACKED)
154
155 #define ZEND_FFI_ARRAY_ATTRS \
156 (ZEND_FFI_ATTR_CONST|ZEND_FFI_ATTR_VLA|ZEND_FFI_ATTR_INCOMPLETE_ARRAY)
157
158 #define ZEND_FFI_FUNC_ATTRS \
159 (ZEND_FFI_ATTR_VARIADIC)
160
161 #define ZEND_FFI_POINTER_ATTRS \
162 (ZEND_FFI_ATTR_CONST)
163
164 typedef struct _zend_ffi_dcl {
165 uint32_t flags;
166 uint32_t align;
167 uint16_t attr;
168 uint16_t abi;
169 zend_ffi_type *type;
170 } zend_ffi_dcl;
171
172 #define ZEND_FFI_ATTR_INIT {0, 0, 0, 0, NULL}
173
174 typedef enum _zend_ffi_val_kind {
175 ZEND_FFI_VAL_EMPTY,
176 ZEND_FFI_VAL_ERROR,
177 ZEND_FFI_VAL_INT32,
178 ZEND_FFI_VAL_INT64,
179 ZEND_FFI_VAL_UINT32,
180 ZEND_FFI_VAL_UINT64,
181 ZEND_FFI_VAL_FLOAT,
182 ZEND_FFI_VAL_DOUBLE,
183 ZEND_FFI_VAL_LONG_DOUBLE,
184 ZEND_FFI_VAL_CHAR,
185 ZEND_FFI_VAL_STRING,
186 ZEND_FFI_VAL_NAME, /* attribute value */
187 } zend_ffi_val_kind;
188
189 #ifdef HAVE_LONG_DOUBLE
190 typedef long double zend_ffi_double;
191 #else
192 typedef double zend_ffi_double;
193 #endif
194
195 typedef struct _zend_ffi_val {
196 zend_ffi_val_kind kind;
197 union {
198 uint64_t u64;
199 int64_t i64;
200 zend_ffi_double d;
201 signed char ch;
202 struct {
203 const char *str;
204 size_t len;
205 };
206 };
207 } zend_ffi_val;
208
209 zend_result zend_ffi_parse_decl(const char *str, size_t len);
210 zend_result zend_ffi_parse_type(const char *str, size_t len, zend_ffi_dcl *dcl);
211 void zend_ffi_cleanup_dcl(zend_ffi_dcl *dcl);
212
213 /* parser callbacks */
214 void ZEND_NORETURN zend_ffi_parser_error(const char *msg, ...);
215 bool zend_ffi_is_typedef_name(const char *name, size_t name_len);
216 void zend_ffi_resolve_typedef(const char *name, size_t name_len, zend_ffi_dcl *dcl);
217 void zend_ffi_resolve_const(const char *name, size_t name_len, zend_ffi_val *val);
218 void zend_ffi_declare_tag(const char *name, size_t name_len, zend_ffi_dcl *dcl, bool incomplete);
219 void zend_ffi_make_enum_type(zend_ffi_dcl *dcl);
220 void zend_ffi_add_enum_val(zend_ffi_dcl *enum_dcl, const char *name, size_t name_len, zend_ffi_val *val, int64_t *min, int64_t *max, int64_t *last);
221 void zend_ffi_make_struct_type(zend_ffi_dcl *dcl);
222 void zend_ffi_add_field(zend_ffi_dcl *struct_dcl, const char *name, size_t name_len, zend_ffi_dcl *field_dcl);
223 void zend_ffi_add_anonymous_field(zend_ffi_dcl *struct_dcl, zend_ffi_dcl *field_dcl);
224 void zend_ffi_add_bit_field(zend_ffi_dcl *struct_dcl, const char *name, size_t name_len, zend_ffi_dcl *field_dcl, zend_ffi_val *bits);
225 void zend_ffi_adjust_struct_size(zend_ffi_dcl *dcl);
226 void zend_ffi_make_pointer_type(zend_ffi_dcl *dcl);
227 void zend_ffi_make_array_type(zend_ffi_dcl *dcl, zend_ffi_val *len);
228 void zend_ffi_make_func_type(zend_ffi_dcl *dcl, HashTable *args, zend_ffi_dcl *nested_dcl);
229 void zend_ffi_add_arg(HashTable **args, const char *name, size_t name_len, zend_ffi_dcl *arg_dcl);
230 void zend_ffi_declare(const char *name, size_t name_len, zend_ffi_dcl *dcl);
231 void zend_ffi_add_attribute(zend_ffi_dcl *dcl, const char *name, size_t name_len);
232 void zend_ffi_add_attribute_value(zend_ffi_dcl *dcl, const char *name, size_t name_len, int n, zend_ffi_val *val);
233 void zend_ffi_add_msvc_attribute_value(zend_ffi_dcl *dcl, const char *name, size_t name_len, zend_ffi_val *val);
234 void zend_ffi_set_abi(zend_ffi_dcl *dcl, uint16_t abi);
235 void zend_ffi_nested_declaration(zend_ffi_dcl *dcl, zend_ffi_dcl *nested_dcl);
236 void zend_ffi_align_as_type(zend_ffi_dcl *dcl, zend_ffi_dcl *align_dcl);
237 void zend_ffi_align_as_val(zend_ffi_dcl *dcl, zend_ffi_val *align_val);
238 void zend_ffi_validate_type_name(zend_ffi_dcl *dcl);
239
240 void zend_ffi_expr_conditional(zend_ffi_val *val, zend_ffi_val *op2, zend_ffi_val *op3);
241 void zend_ffi_expr_bool_or(zend_ffi_val *val, zend_ffi_val *op2);
242 void zend_ffi_expr_bool_and(zend_ffi_val *val, zend_ffi_val *op2);
243 void zend_ffi_expr_bw_or(zend_ffi_val *val, zend_ffi_val *op2);
244 void zend_ffi_expr_bw_xor(zend_ffi_val *val, zend_ffi_val *op2);
245 void zend_ffi_expr_bw_and(zend_ffi_val *val, zend_ffi_val *op2);
246 void zend_ffi_expr_is_equal(zend_ffi_val *val, zend_ffi_val *op2);
247 void zend_ffi_expr_is_not_equal(zend_ffi_val *val, zend_ffi_val *op2);
248 void zend_ffi_expr_is_less(zend_ffi_val *val, zend_ffi_val *op2);
249 void zend_ffi_expr_is_greater(zend_ffi_val *val, zend_ffi_val *op2);
250 void zend_ffi_expr_is_less_or_equal(zend_ffi_val *val, zend_ffi_val *op2);
251 void zend_ffi_expr_is_greater_or_equal(zend_ffi_val *val, zend_ffi_val *op2);
252 void zend_ffi_expr_shift_left(zend_ffi_val *val, zend_ffi_val *op2);
253 void zend_ffi_expr_shift_right(zend_ffi_val *val, zend_ffi_val *op2);
254 void zend_ffi_expr_add(zend_ffi_val *val, zend_ffi_val *op2);
255 void zend_ffi_expr_sub(zend_ffi_val *val, zend_ffi_val *op2);
256 void zend_ffi_expr_mul(zend_ffi_val *val, zend_ffi_val *op2);
257 void zend_ffi_expr_div(zend_ffi_val *val, zend_ffi_val *op2);
258 void zend_ffi_expr_mod(zend_ffi_val *val, zend_ffi_val *op2);
259 void zend_ffi_expr_cast(zend_ffi_val *val, zend_ffi_dcl *dcl);
260 void zend_ffi_expr_plus(zend_ffi_val *val);
261 void zend_ffi_expr_neg(zend_ffi_val *val);
262 void zend_ffi_expr_bw_not(zend_ffi_val *val);
263 void zend_ffi_expr_bool_not(zend_ffi_val *val);
264 void zend_ffi_expr_sizeof_val(zend_ffi_val *val);
265 void zend_ffi_expr_sizeof_type(zend_ffi_val *val, zend_ffi_dcl *dcl);
266 void zend_ffi_expr_alignof_val(zend_ffi_val *val);
267 void zend_ffi_expr_alignof_type(zend_ffi_val *val, zend_ffi_dcl *dcl);
268
zend_ffi_val_error(zend_ffi_val * val)269 static zend_always_inline void zend_ffi_val_error(zend_ffi_val *val) /* {{{ */
270 {
271 val->kind = ZEND_FFI_VAL_ERROR;
272 }
273 /* }}} */
274
275 void zend_ffi_val_number(zend_ffi_val *val, int base, const char *str, size_t str_len);
276 void zend_ffi_val_float_number(zend_ffi_val *val, const char *str, size_t str_len);
277 void zend_ffi_val_string(zend_ffi_val *val, const char *str, size_t str_len);
278 void zend_ffi_val_character(zend_ffi_val *val, const char *str, size_t str_len);
279
280 #endif /* PHP_FFI_H */
281