1 /*
2  * Copyright 2015-2017 MongoDB, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef PHONGO_COMPAT_H
18 #define PHONGO_COMPAT_H
19 
20 #include <php.h>
21 #include <Zend/zend_string.h>
22 #include <Zend/zend_portability.h>
23 
24 #ifdef PHP_WIN32
25 #include "config.w32.h"
26 #else
27 #include <php_config.h>
28 #endif
29 
30 #ifndef PHP_FE_END
31 #define PHP_FE_END       \
32 	{                    \
33 		NULL, NULL, NULL \
34 	}
35 #endif
36 
37 #ifndef HASH_KEY_NON_EXISTENT
38 #define HASH_KEY_NON_EXISTENT HASH_KEY_NON_EXISTANT
39 #endif
40 
41 #if defined(__GNUC__)
42 #define ARG_UNUSED __attribute__((unused))
43 #else
44 #define ARG_UNUSED
45 #endif
46 
47 #if defined(__GNUC__)
48 #define PHONGO_GNUC_CHECK_VERSION(major, minor) \
49 	((__GNUC__ > (major)) ||                    \
50 	 ((__GNUC__ == (major)) && (__GNUC_MINOR__ >= (minor))))
51 #else
52 #define PHONGO_GNUC_CHECK_VERSION(major, minor) 0
53 #endif
54 
55 #if PHONGO_GNUC_CHECK_VERSION(7, 0)
56 #define PHONGO_BREAK_INTENTIONALLY_MISSING __attribute__((fallthrough));
57 #elif defined(__clang__) && __clang_major__ >= 12
58 #define PHONGO_BREAK_INTENTIONALLY_MISSING __attribute__((fallthrough));
59 #else
60 #define PHONGO_BREAK_INTENTIONALLY_MISSING
61 #endif
62 
63 #if PHP_VERSION_ID >= 80000
64 #define PHONGO_COMPAT_OBJ_P(val) Z_OBJ_P(val)
65 #define phongo_compat_object_handler_type zend_object
66 #define PHONGO_COMPAT_GET_OBJ(val) val
67 #define PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(type) php_phongo_handler_##type.compare = php_phongo_##type##_compare_objects;
68 #else /* PHP_VERSION_ID < 80000 */
69 #define PHONGO_COMPAT_OBJ_P(val) val
70 #define phongo_compat_object_handler_type zval
71 #define PHONGO_COMPAT_GET_OBJ(val) Z_OBJ_P(val)
72 #define PHONGO_COMPAT_SET_COMPARE_OBJECTS_HANDLER(type) php_phongo_handler_##type.compare_objects = php_phongo_##type##_compare_objects;
73 #define ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2)
74 #endif /* PHP_VERSION_ID >= 80000 */
75 
76 #if SIZEOF_ZEND_LONG == 8
77 #define PHONGO_LONG_FORMAT PRId64
78 #elif SIZEOF_ZEND_LONG == 4
79 #define PHONGO_LONG_FORMAT PRId32
80 #else
81 #error Unsupported architecture (integers are neither 32-bit nor 64-bit)
82 #endif
83 #define PHONGO_ALLOC_OBJECT_T(_obj_t, _class_type) (_obj_t*) ecalloc(1, sizeof(_obj_t) + zend_object_properties_size(_class_type))
84 #define ADD_ASSOC_STRING(_zv, _key, _value) add_assoc_string_ex(_zv, ZEND_STRL(_key), (char*) (_value));
85 #define ADD_ASSOC_STRINGL(_zv, _key, _value, _len) add_assoc_stringl_ex(_zv, ZEND_STRL(_key), (char*) (_value), _len);
86 #define ADD_ASSOC_STRING_EX(_zv, _key, _key_len, _value, _value_len) add_assoc_stringl_ex(_zv, _key, _key_len, (char*) (_value), _value_len);
87 #define ADD_ASSOC_LONG_EX(_zv, _key, _value) add_assoc_long_ex(_zv, ZEND_STRL(_key), _value);
88 #define ADD_ASSOC_ZVAL_EX(_zv, _key, _value) add_assoc_zval_ex(_zv, ZEND_STRL(_key), _value);
89 #define ADD_ASSOC_ZVAL(_zv, _key, _value) add_assoc_zval(_zv, _key, _value);
90 #define ADD_ASSOC_NULL_EX(_zv, _key) add_assoc_null_ex(_zv, ZEND_STRL(_key));
91 #define ADD_ASSOC_BOOL_EX(_zv, _key, _value) add_assoc_bool_ex(_zv, ZEND_STRL(_key), _value);
92 #define ZVAL_INT64_STRING(_zv, _value)                              \
93 	do {                                                            \
94 		char tmp[24];                                               \
95 		int  tmp_len;                                               \
96 		tmp_len = snprintf(tmp, sizeof(tmp), "%" PRId64, (_value)); \
97 		ZVAL_STRINGL((_zv), tmp, tmp_len);                          \
98 	} while (0)
99 #define ADD_ASSOC_INT64_AS_STRING(_zv, _key, _value) \
100 	do {                                             \
101 		zval z_int;                                  \
102 		ZVAL_INT64_STRING(&z_int, (_value));         \
103 		ADD_ASSOC_ZVAL_EX((_zv), (_key), &z_int);    \
104 	} while (0)
105 #define ADD_NEXT_INDEX_STRINGL(_zv, _value, _len) add_next_index_stringl(_zv, _value, _len);
106 #define PHONGO_RETVAL_SMART_STR(val) RETVAL_STRINGL(ZSTR_VAL((val).s), ZSTR_LEN((val).s));
107 #define ZVAL_STATIC_INIT \
108 	{                    \
109 		{                \
110 			0            \
111 		}                \
112 	}
113 
114 #if SIZEOF_ZEND_LONG == 8
115 #define ADD_INDEX_INT64(_zv, _index, _value) add_index_long((_zv), (_index), (_value))
116 #define ADD_NEXT_INDEX_INT64(_zv, _value) add_next_index_long((_zv), (_value))
117 #define ADD_ASSOC_INT64(_zv, _key, _value) add_assoc_long((_zv), (_key), (_value))
118 #define ZVAL_INT64(_zv, _value) ZVAL_LONG((_zv), (_value))
119 #elif SIZEOF_ZEND_LONG == 4
120 #define ADD_INDEX_INT64(_zv, _index, _value)            \
121 	if ((_value) > INT32_MAX || (_value) < INT32_MIN) { \
122 		zval zchild;                                    \
123 		php_phongo_bson_new_int64(&zchild, (_value));   \
124 		add_index_zval((_zv), (_index), &zchild);       \
125 	} else {                                            \
126 		add_index_long((_zv), (_index), (_value));      \
127 	}
128 #define ADD_NEXT_INDEX_INT64(_zv, _value)               \
129 	if ((_value) > INT32_MAX || (_value) < INT32_MIN) { \
130 		zval zchild;                                    \
131 		php_phongo_bson_new_int64(&zchild, (_value));   \
132 		add_next_index_zval((_zv), &zchild);            \
133 	} else {                                            \
134 		add_next_index_long((_zv), (_value));           \
135 	}
136 #define ADD_ASSOC_INT64(_zv, _key, _value)              \
137 	if ((_value) > INT32_MAX || (_value) < INT32_MIN) { \
138 		zval zchild;                                    \
139 		php_phongo_bson_new_int64(&zchild, (_value));   \
140 		add_assoc_zval((_zv), (_key), &zchild);         \
141 	} else {                                            \
142 		add_assoc_long((_zv), (_key), (_value));        \
143 	}
144 #define ZVAL_INT64(_zv, _value)                         \
145 	if ((_value) > INT32_MAX || (_value) < INT32_MIN) { \
146 		php_phongo_bson_new_int64((_zv), (_value));     \
147 	} else {                                            \
148 		ZVAL_LONG((_zv), (_value));                     \
149 	}
150 #else /* SIZEOF_ZEND_LONG != 8 && SIZEOF_ZEND_LONG != 4 */
151 #error Unsupported architecture (integers are neither 32-bit nor 64-bit)
152 #endif /* SIZEOF_ZEND_LONG */
153 
154 #if PHP_VERSION_ID < 70300
155 #define ZVAL_COPY_DEREF(z, v)                     \
156 	do {                                          \
157 		zval* _z3 = (v);                          \
158 		if (Z_OPT_REFCOUNTED_P(_z3)) {            \
159 			if (UNEXPECTED(Z_OPT_ISREF_P(_z3))) { \
160 				_z3 = Z_REFVAL_P(_z3);            \
161 				if (Z_OPT_REFCOUNTED_P(_z3)) {    \
162 					Z_ADDREF_P(_z3);              \
163 				}                                 \
164 			} else {                              \
165 				Z_ADDREF_P(_z3);                  \
166 			}                                     \
167 		}                                         \
168 		ZVAL_COPY_VALUE(z, _z3);                  \
169 	} while (0)
170 #endif /* PHP_VERSION_ID < 70300 */
171 
172 void      phongo_add_exception_prop(const char* prop, int prop_len, zval* value);
173 zend_bool php_phongo_zend_hash_apply_protection_begin(HashTable* ht);
174 zend_bool php_phongo_zend_hash_apply_protection_end(HashTable* ht);
175 
176 #endif /* PHONGO_COMPAT_H */
177 
178 /*
179  * Local variables:
180  * tab-width: 4
181  * c-basic-offset: 4
182  * End:
183  * vim600: noet sw=4 ts=4 fdm=marker
184  * vim<600: noet sw=4 ts=4
185  */
186