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 284154 2009-07-15 23:57:10Z stas $ */
20 :
21 : /* {{{ includes/startup/misc */
22 :
23 : #include "php.h"
24 : #include "php_assert.h"
25 : #include "php_ini.h"
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 13569 : {
56 13569 : 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 13567 : if (ASSERTG(cb)) {
67 1 : pefree(ASSERTG(cb), 1);
68 : }
69 13577 : 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 13557 : ASSERTG(cb) = NULL;
75 : }
76 : }
77 13569 : return SUCCESS;
78 : }
79 :
80 : PHP_INI_BEGIN()
81 : STD_PHP_INI_ENTRY("assert.active", "1", PHP_INI_ALL, OnUpdateLong, active, zend_assert_globals, assert_globals)
82 : STD_PHP_INI_ENTRY("assert.bail", "0", PHP_INI_ALL, OnUpdateLong, bail, zend_assert_globals, assert_globals)
83 : STD_PHP_INI_ENTRY("assert.warning", "1", PHP_INI_ALL, OnUpdateLong, warning, zend_assert_globals, assert_globals)
84 : PHP_INI_ENTRY ("assert.callback", NULL, PHP_INI_ALL, OnChangeCallback)
85 : STD_PHP_INI_ENTRY("assert.quiet_eval", "0", PHP_INI_ALL, OnUpdateLong, quiet_eval, zend_assert_globals, assert_globals)
86 : PHP_INI_END()
87 :
88 : static void php_assert_init_globals(zend_assert_globals *assert_globals_p TSRMLS_DC)
89 13565 : {
90 13565 : assert_globals_p->callback = NULL;
91 13565 : assert_globals_p->cb = NULL;
92 13565 : }
93 :
94 : PHP_MINIT_FUNCTION(assert)
95 13565 : {
96 13565 : ZEND_INIT_MODULE_GLOBALS(assert, php_assert_init_globals, NULL);
97 :
98 13565 : REGISTER_INI_ENTRIES();
99 :
100 13565 : REGISTER_LONG_CONSTANT("ASSERT_ACTIVE", ASSERT_ACTIVE, CONST_CS|CONST_PERSISTENT);
101 13565 : REGISTER_LONG_CONSTANT("ASSERT_CALLBACK", ASSERT_CALLBACK, CONST_CS|CONST_PERSISTENT);
102 13565 : REGISTER_LONG_CONSTANT("ASSERT_BAIL", ASSERT_BAIL, CONST_CS|CONST_PERSISTENT);
103 13565 : REGISTER_LONG_CONSTANT("ASSERT_WARNING", ASSERT_WARNING, CONST_CS|CONST_PERSISTENT);
104 13565 : REGISTER_LONG_CONSTANT("ASSERT_QUIET_EVAL", ASSERT_QUIET_EVAL, CONST_CS|CONST_PERSISTENT);
105 :
106 13565 : return SUCCESS;
107 : }
108 :
109 : PHP_MSHUTDOWN_FUNCTION(assert)
110 13597 : {
111 13597 : if (ASSERTG(cb)) {
112 9 : pefree(ASSERTG(cb), 1);
113 9 : ASSERTG(cb) = NULL;
114 : }
115 13597 : return SUCCESS;
116 : }
117 :
118 : PHP_RSHUTDOWN_FUNCTION(assert)
119 13584 : {
120 13584 : if (ASSERTG(callback)) {
121 7 : zval_ptr_dtor(&ASSERTG(callback));
122 7 : ASSERTG(callback) = NULL;
123 : }
124 :
125 13584 : return SUCCESS;
126 : }
127 :
128 : PHP_MINFO_FUNCTION(assert)
129 6 : {
130 6 : DISPLAY_INI_ENTRIES();
131 6 : }
132 :
133 : /* }}} */
134 : /* {{{ internal functions */
135 : /* }}} */
136 : /* {{{ proto int assert(string|bool assertion)
137 : Checks if assertion is false */
138 :
139 : PHP_FUNCTION(assert)
140 42 : {
141 : zval **assertion;
142 : int val;
143 42 : char *myeval = NULL;
144 : char *compiled_string_description;
145 :
146 42 : if (! ASSERTG(active)) {
147 5 : RETURN_TRUE;
148 : }
149 :
150 37 : if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &assertion) == FAILURE) {
151 2 : WRONG_PARAM_COUNT;
152 : }
153 :
154 35 : if (Z_TYPE_PP(assertion) == IS_STRING) {
155 : zval retval;
156 25 : int old_error_reporting = 0; /* shut up gcc! */
157 :
158 25 : myeval = Z_STRVAL_PP(assertion);
159 :
160 25 : if (ASSERTG(quiet_eval)) {
161 8 : old_error_reporting = EG(error_reporting);
162 8 : EG(error_reporting) = 0;
163 : }
164 :
165 25 : compiled_string_description = zend_make_compiled_string_description("assert code" TSRMLS_CC);
166 25 : if (zend_eval_string(myeval, &retval, compiled_string_description TSRMLS_CC) == FAILURE) {
167 3 : efree(compiled_string_description);
168 3 : php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Failure evaluating code: %s%s", PHP_EOL, myeval);
169 2 : if (ASSERTG(bail)) {
170 1 : zend_bailout();
171 : }
172 1 : RETURN_FALSE;
173 : }
174 22 : efree(compiled_string_description);
175 :
176 22 : if (ASSERTG(quiet_eval)) {
177 7 : EG(error_reporting) = old_error_reporting;
178 : }
179 :
180 22 : convert_to_boolean(&retval);
181 22 : val = Z_LVAL(retval);
182 : } else {
183 10 : convert_to_boolean_ex(assertion);
184 10 : val = Z_LVAL_PP(assertion);
185 : }
186 :
187 32 : if (val) {
188 11 : RETURN_TRUE;
189 : }
190 :
191 21 : if (!ASSERTG(callback) && ASSERTG(cb)) {
192 5 : MAKE_STD_ZVAL(ASSERTG(callback));
193 5 : ZVAL_STRING(ASSERTG(callback), ASSERTG(cb), 1);
194 : }
195 :
196 21 : if (ASSERTG(callback)) {
197 : zval *args[3];
198 : zval *retval;
199 : int i;
200 17 : uint lineno = zend_get_executed_lineno(TSRMLS_C);
201 17 : char *filename = zend_get_executed_filename(TSRMLS_C);
202 :
203 17 : MAKE_STD_ZVAL(args[0]);
204 17 : MAKE_STD_ZVAL(args[1]);
205 17 : MAKE_STD_ZVAL(args[2]);
206 :
207 17 : ZVAL_STRING(args[0], SAFE_STRING(filename), 1);
208 17 : ZVAL_LONG (args[1], lineno);
209 17 : ZVAL_STRING(args[2], SAFE_STRING(myeval), 1);
210 :
211 17 : MAKE_STD_ZVAL(retval);
212 17 : ZVAL_FALSE(retval);
213 :
214 : /* XXX do we want to check for error here? */
215 17 : call_user_function(CG(function_table), NULL, ASSERTG(callback), retval, 3, args TSRMLS_CC);
216 :
217 68 : for (i = 0; i <= 2; i++) {
218 51 : zval_ptr_dtor(&(args[i]));
219 : }
220 17 : zval_ptr_dtor(&retval);
221 : }
222 :
223 21 : if (ASSERTG(warning)) {
224 8 : if (myeval) {
225 4 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Assertion \"%s\" failed", myeval);
226 : } else {
227 4 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Assertion failed");
228 : }
229 : }
230 :
231 21 : if (ASSERTG(bail)) {
232 2 : zend_bailout();
233 : }
234 : }
235 :
236 : /* }}} */
237 : /* {{{ proto mixed assert_options(int what [, mixed value])
238 : Set/get the various assert flags */
239 :
240 : PHP_FUNCTION(assert_options)
241 41 : {
242 : zval **what, **value;
243 : int oldint;
244 41 : int ac = ZEND_NUM_ARGS();
245 :
246 41 : if (ac < 1 || ac > 2 || zend_get_parameters_ex(ac, &what, &value) == FAILURE) {
247 2 : WRONG_PARAM_COUNT;
248 : }
249 :
250 39 : convert_to_long_ex(what);
251 :
252 39 : switch (Z_LVAL_PP(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 18 : if (ASSERTG(callback) != NULL) {
291 13 : RETVAL_ZVAL(ASSERTG(callback), 1, 0);
292 5 : } else if (ASSERTG(cb)) {
293 3 : RETVAL_STRING(ASSERTG(cb), 1);
294 : } else {
295 2 : RETVAL_NULL();
296 : }
297 18 : if (ac == 2) {
298 9 : if (ASSERTG(callback)) {
299 7 : zval_ptr_dtor(&ASSERTG(callback));
300 : }
301 9 : ASSERTG(callback) = *value;
302 9 : zval_add_ref(value);
303 : }
304 18 : return;
305 : break;
306 :
307 : default:
308 2 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown value %ld", Z_LVAL_PP(what));
309 : break;
310 : }
311 :
312 2 : RETURN_FALSE;
313 : }
314 :
315 : /* }}} */
316 :
317 : /*
318 : * Local variables:
319 : * tab-width: 4
320 : * c-basic-offset: 4
321 : * End:
322 : * vim600: sw=4 ts=4 fdm=marker
323 : * vim<600: sw=4 ts=4
324 : */
|