1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 The PHP Group |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 3.01 of the PHP license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.php.net/license/3_01.txt |
11 : | If you did not receive a copy of the PHP license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@php.net so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Author: Thies C. Arntzen <thies@thieso.net> |
16 : +----------------------------------------------------------------------+
17 : */
18 :
19 : /* $Id: assert.c 284153 2009-07-15 23:55:50Z stas $ */
20 :
21 : /* {{{ includes */
22 : #include "php.h"
23 : #include "php_assert.h"
24 : #include "php_ini.h"
25 : /* }}} */
26 :
27 : ZEND_BEGIN_MODULE_GLOBALS(assert)
28 : long active;
29 : long bail;
30 : long warning;
31 : long quiet_eval;
32 : zval *callback;
33 : char *cb;
34 : ZEND_END_MODULE_GLOBALS(assert)
35 :
36 : ZEND_DECLARE_MODULE_GLOBALS(assert)
37 :
38 : #ifdef ZTS
39 : #define ASSERTG(v) TSRMG(assert_globals_id, zend_assert_globals *, v)
40 : #else
41 : #define ASSERTG(v) (assert_globals.v)
42 : #endif
43 :
44 : #define SAFE_STRING(s) ((s)?(s):"")
45 :
46 : enum {
47 : ASSERT_ACTIVE=1,
48 : ASSERT_CALLBACK,
49 : ASSERT_BAIL,
50 : ASSERT_WARNING,
51 : ASSERT_QUIET_EVAL
52 : };
53 :
54 : static PHP_INI_MH(OnChangeCallback) /* {{{ */
55 17637 : {
56 17637 : if (EG(in_execution)) {
57 2 : if (ASSERTG(callback)) {
58 2 : zval_ptr_dtor(&ASSERTG(callback));
59 2 : ASSERTG(callback) = NULL;
60 : }
61 2 : if (new_value && (ASSERTG(callback) || new_value_length)) {
62 2 : MAKE_STD_ZVAL(ASSERTG(callback));
63 2 : ZVAL_STRINGL(ASSERTG(callback), new_value, new_value_length, 1);
64 : }
65 : } else {
66 17635 : if (ASSERTG(cb)) {
67 1 : pefree(ASSERTG(cb), 1);
68 : }
69 17645 : if (new_value && new_value_length) {
70 10 : ASSERTG(cb) = pemalloc(new_value_length + 1, 1);
71 10 : memcpy(ASSERTG(cb), new_value, new_value_length);
72 10 : ASSERTG(cb)[new_value_length] = '\0';
73 : } else {
74 17625 : ASSERTG(cb) = NULL;
75 : }
76 : }
77 17637 : return SUCCESS;
78 : }
79 : /* }}} */
80 :
81 : PHP_INI_BEGIN()
82 : STD_PHP_INI_ENTRY("assert.active", "1", PHP_INI_ALL, OnUpdateLong, active, zend_assert_globals, assert_globals)
83 : STD_PHP_INI_ENTRY("assert.bail", "0", PHP_INI_ALL, OnUpdateLong, bail, zend_assert_globals, assert_globals)
84 : STD_PHP_INI_ENTRY("assert.warning", "1", PHP_INI_ALL, OnUpdateLong, warning, zend_assert_globals, assert_globals)
85 : PHP_INI_ENTRY("assert.callback", NULL, PHP_INI_ALL, OnChangeCallback)
86 : STD_PHP_INI_ENTRY("assert.quiet_eval", "0", PHP_INI_ALL, OnUpdateLong, quiet_eval, zend_assert_globals, assert_globals)
87 : PHP_INI_END()
88 :
89 : static void php_assert_init_globals(zend_assert_globals *assert_globals_p TSRMLS_DC) /* {{{ */
90 17633 : {
91 17633 : assert_globals_p->callback = NULL;
92 17633 : assert_globals_p->cb = NULL;
93 17633 : }
94 : /* }}} */
95 :
96 : PHP_MINIT_FUNCTION(assert) /* {{{ */
97 17633 : {
98 17633 : ZEND_INIT_MODULE_GLOBALS(assert, php_assert_init_globals, NULL);
99 :
100 17633 : REGISTER_INI_ENTRIES();
101 :
102 17633 : REGISTER_LONG_CONSTANT("ASSERT_ACTIVE", ASSERT_ACTIVE, CONST_CS|CONST_PERSISTENT);
103 17633 : REGISTER_LONG_CONSTANT("ASSERT_CALLBACK", ASSERT_CALLBACK, CONST_CS|CONST_PERSISTENT);
104 17633 : REGISTER_LONG_CONSTANT("ASSERT_BAIL", ASSERT_BAIL, CONST_CS|CONST_PERSISTENT);
105 17633 : REGISTER_LONG_CONSTANT("ASSERT_WARNING", ASSERT_WARNING, CONST_CS|CONST_PERSISTENT);
106 17633 : REGISTER_LONG_CONSTANT("ASSERT_QUIET_EVAL", ASSERT_QUIET_EVAL, CONST_CS|CONST_PERSISTENT);
107 :
108 17633 : return SUCCESS;
109 : }
110 : /* }}} */
111 :
112 : PHP_MSHUTDOWN_FUNCTION(assert) /* {{{ */
113 17665 : {
114 17665 : if (ASSERTG(cb)) {
115 9 : pefree(ASSERTG(cb), 1);
116 9 : ASSERTG(cb) = NULL;
117 : }
118 17665 : return SUCCESS;
119 : }
120 : /* }}} */
121 :
122 : PHP_RSHUTDOWN_FUNCTION(assert) /* {{{ */
123 17651 : {
124 17651 : if (ASSERTG(callback)) {
125 8 : zval_ptr_dtor(&ASSERTG(callback));
126 8 : ASSERTG(callback) = NULL;
127 : }
128 :
129 17651 : return SUCCESS;
130 : }
131 : /* }}} */
132 :
133 : PHP_MINFO_FUNCTION(assert) /* {{{ */
134 43 : {
135 43 : DISPLAY_INI_ENTRIES();
136 43 : }
137 : /* }}} */
138 :
139 : /* {{{ proto int assert(string|bool assertion)
140 : Checks if assertion is false */
141 : PHP_FUNCTION(assert)
142 121 : {
143 : zval **assertion;
144 : int val;
145 121 : char *myeval = NULL;
146 : char *compiled_string_description;
147 :
148 121 : if (! ASSERTG(active)) {
149 5 : RETURN_TRUE;
150 : }
151 :
152 116 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &assertion) == FAILURE) {
153 2 : return;
154 : }
155 :
156 114 : if (Z_TYPE_PP(assertion) == IS_STRING) {
157 : zval retval;
158 25 : int old_error_reporting = 0; /* shut up gcc! */
159 :
160 25 : myeval = Z_STRVAL_PP(assertion);
161 :
162 25 : if (ASSERTG(quiet_eval)) {
163 8 : old_error_reporting = EG(error_reporting);
164 8 : EG(error_reporting) = 0;
165 : }
166 :
167 25 : compiled_string_description = zend_make_compiled_string_description("assert code" TSRMLS_CC);
168 25 : if (zend_eval_stringl(myeval, Z_STRLEN_PP(assertion), &retval, compiled_string_description TSRMLS_CC) == FAILURE) {
169 3 : efree(compiled_string_description);
170 3 : php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Failure evaluating code: %s%s", PHP_EOL, myeval);
171 2 : if (ASSERTG(bail)) {
172 1 : zend_bailout();
173 : }
174 1 : RETURN_FALSE;
175 : }
176 22 : efree(compiled_string_description);
177 :
178 22 : if (ASSERTG(quiet_eval)) {
179 7 : EG(error_reporting) = old_error_reporting;
180 : }
181 :
182 22 : convert_to_boolean(&retval);
183 22 : val = Z_LVAL(retval);
184 : } else {
185 89 : convert_to_boolean_ex(assertion);
186 89 : val = Z_LVAL_PP(assertion);
187 : }
188 :
189 111 : if (val) {
190 89 : RETURN_TRUE;
191 : }
192 :
193 22 : if (!ASSERTG(callback) && ASSERTG(cb)) {
194 5 : MAKE_STD_ZVAL(ASSERTG(callback));
195 5 : ZVAL_STRING(ASSERTG(callback), ASSERTG(cb), 1);
196 : }
197 :
198 22 : if (ASSERTG(callback)) {
199 : zval *args[3];
200 : zval *retval;
201 : int i;
202 18 : uint lineno = zend_get_executed_lineno(TSRMLS_C);
203 18 : char *filename = zend_get_executed_filename(TSRMLS_C);
204 :
205 18 : MAKE_STD_ZVAL(args[0]);
206 18 : MAKE_STD_ZVAL(args[1]);
207 18 : MAKE_STD_ZVAL(args[2]);
208 :
209 18 : ZVAL_STRING(args[0], SAFE_STRING(filename), 1);
210 18 : ZVAL_LONG (args[1], lineno);
211 18 : ZVAL_STRING(args[2], SAFE_STRING(myeval), 1);
212 :
213 18 : MAKE_STD_ZVAL(retval);
214 18 : ZVAL_FALSE(retval);
215 :
216 : /* XXX do we want to check for error here? */
217 18 : call_user_function(CG(function_table), NULL, ASSERTG(callback), retval, 3, args TSRMLS_CC);
218 :
219 72 : for (i = 0; i <= 2; i++) {
220 54 : zval_ptr_dtor(&(args[i]));
221 : }
222 18 : zval_ptr_dtor(&retval);
223 : }
224 :
225 22 : if (ASSERTG(warning)) {
226 9 : if (myeval) {
227 4 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Assertion \"%s\" failed", myeval);
228 : } else {
229 5 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Assertion failed");
230 : }
231 : }
232 :
233 22 : if (ASSERTG(bail)) {
234 2 : zend_bailout();
235 : }
236 : }
237 : /* }}} */
238 :
239 : /* {{{ proto mixed assert_options(int what [, mixed value])
240 : Set/get the various assert flags */
241 : PHP_FUNCTION(assert_options)
242 42 : {
243 42 : zval **value = NULL;
244 : long what;
245 : int oldint;
246 42 : int ac = ZEND_NUM_ARGS();
247 :
248 42 : if (zend_parse_parameters(ac TSRMLS_CC, "l|Z", &what, &value) == FAILURE) {
249 4 : return;
250 : }
251 :
252 38 : switch (what) {
253 : case ASSERT_ACTIVE:
254 5 : oldint = ASSERTG(active);
255 5 : if (ac == 2) {
256 4 : convert_to_long_ex(value);
257 4 : ASSERTG(active) = Z_LVAL_PP(value);
258 : }
259 5 : RETURN_LONG(oldint);
260 : break;
261 :
262 : case ASSERT_BAIL:
263 4 : oldint = ASSERTG(bail);
264 4 : if (ac == 2) {
265 3 : convert_to_long_ex(value);
266 3 : ASSERTG(bail) = Z_LVAL_PP(value);
267 : }
268 4 : RETURN_LONG(oldint);
269 : break;
270 :
271 : case ASSERT_QUIET_EVAL:
272 4 : oldint = ASSERTG(quiet_eval);
273 4 : if (ac == 2) {
274 3 : convert_to_long_ex(value);
275 3 : ASSERTG(quiet_eval) = Z_LVAL_PP(value);
276 : }
277 4 : RETURN_LONG(oldint);
278 : break;
279 :
280 : case ASSERT_WARNING:
281 6 : oldint = ASSERTG(warning);
282 6 : if (ac == 2) {
283 5 : convert_to_long_ex(value);
284 5 : ASSERTG(warning) = Z_LVAL_PP(value);
285 : }
286 6 : RETURN_LONG(oldint);
287 : break;
288 :
289 : case ASSERT_CALLBACK:
290 19 : if (ASSERTG(callback) != NULL) {
291 13 : RETVAL_ZVAL(ASSERTG(callback), 1, 0);
292 6 : } else if (ASSERTG(cb)) {
293 3 : RETVAL_STRING(ASSERTG(cb), 1);
294 : } else {
295 3 : RETVAL_NULL();
296 : }
297 19 : if (ac == 2) {
298 10 : if (ASSERTG(callback)) {
299 7 : zval_ptr_dtor(&ASSERTG(callback));
300 : }
301 10 : ASSERTG(callback) = *value;
302 10 : zval_add_ref(value);
303 : }
304 19 : return;
305 : break;
306 :
307 : default:
308 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown value %ld", what);
309 : break;
310 : }
311 :
312 0 : RETURN_FALSE;
313 : }
314 : /* }}} */
315 :
316 : /*
317 : * Local variables:
318 : * tab-width: 4
319 : * c-basic-offset: 4
320 : * End:
321 : * vim600: sw=4 ts=4 fdm=marker
322 : * vim<600: sw=4 ts=4
323 : */
|