1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 6 |
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 284155 2009-07-15 23:57:52Z 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 17011 : {
56 17011 : 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 17009 : if (ASSERTG(cb)) {
67 1 : pefree(ASSERTG(cb), 1);
68 : }
69 17019 : 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 16999 : ASSERTG(cb) = NULL;
75 : }
76 : }
77 17011 : 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 17007 : {
91 17007 : assert_globals_p->callback = NULL;
92 17007 : assert_globals_p->cb = NULL;
93 17007 : }
94 : /* }}} */
95 :
96 : PHP_MINIT_FUNCTION(assert) /* {{{ */
97 17007 : {
98 17007 : ZEND_INIT_MODULE_GLOBALS(assert, php_assert_init_globals, NULL);
99 :
100 17007 : REGISTER_INI_ENTRIES();
101 :
102 17007 : REGISTER_LONG_CONSTANT("ASSERT_ACTIVE", ASSERT_ACTIVE, CONST_CS|CONST_PERSISTENT);
103 17007 : REGISTER_LONG_CONSTANT("ASSERT_CALLBACK", ASSERT_CALLBACK, CONST_CS|CONST_PERSISTENT);
104 17007 : REGISTER_LONG_CONSTANT("ASSERT_BAIL", ASSERT_BAIL, CONST_CS|CONST_PERSISTENT);
105 17007 : REGISTER_LONG_CONSTANT("ASSERT_WARNING", ASSERT_WARNING, CONST_CS|CONST_PERSISTENT);
106 17007 : REGISTER_LONG_CONSTANT("ASSERT_QUIET_EVAL", ASSERT_QUIET_EVAL, CONST_CS|CONST_PERSISTENT);
107 :
108 17007 : return SUCCESS;
109 : }
110 : /* }}} */
111 :
112 : PHP_MSHUTDOWN_FUNCTION(assert) /* {{{ */
113 17039 : {
114 17039 : if (ASSERTG(cb)) {
115 9 : pefree(ASSERTG(cb), 1);
116 9 : ASSERTG(cb) = NULL;
117 : }
118 17039 : return SUCCESS;
119 : }
120 : /* }}} */
121 :
122 : PHP_RSHUTDOWN_FUNCTION(assert) /* {{{ */
123 17025 : {
124 17025 : if (ASSERTG(callback)) {
125 8 : zval_ptr_dtor(&ASSERTG(callback));
126 8 : ASSERTG(callback) = NULL;
127 : }
128 :
129 17025 : return SUCCESS;
130 : }
131 : /* }}} */
132 :
133 : PHP_MINFO_FUNCTION(assert) /* {{{ */
134 44 : {
135 44 : DISPLAY_INI_ENTRIES();
136 44 : }
137 : /* }}} */
138 :
139 : /* {{{ proto int assert(string|bool assertion) U
140 : Checks if assertion is false */
141 : PHP_FUNCTION(assert)
142 120 : {
143 : zval **assertion;
144 : zval tmp;
145 120 : int val, free_tmp = 0;
146 120 : char *myeval = NULL;
147 : char *compiled_string_description;
148 :
149 120 : if (! ASSERTG(active)) {
150 5 : RETURN_TRUE;
151 : }
152 :
153 115 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &assertion) == FAILURE) {
154 2 : return;
155 : }
156 :
157 135 : if (Z_TYPE_PP(assertion) == IS_STRING || Z_TYPE_PP(assertion) == IS_UNICODE) {
158 : zval retval;
159 25 : int old_error_reporting = 0; /* shut up gcc! */
160 : int myeval_len;
161 :
162 25 : if (Z_TYPE_PP(assertion) == IS_UNICODE) {
163 25 : tmp = **assertion;
164 25 : zval_copy_ctor(&tmp);
165 25 : convert_to_string(&tmp);
166 25 : myeval = Z_STRVAL(tmp);
167 25 : myeval_len = Z_STRLEN(tmp);
168 25 : free_tmp = 1;
169 : } else {
170 0 : myeval = Z_STRVAL_PP(assertion);
171 0 : myeval_len = Z_STRLEN_PP(assertion);
172 : }
173 :
174 25 : if (ASSERTG(quiet_eval)) {
175 8 : old_error_reporting = EG(error_reporting);
176 8 : EG(error_reporting) = 0;
177 : }
178 :
179 25 : compiled_string_description = zend_make_compiled_string_description("assert code" TSRMLS_CC);
180 25 : if (zend_eval_stringl(myeval, myeval_len, &retval, compiled_string_description TSRMLS_CC) == FAILURE) {
181 3 : efree(compiled_string_description);
182 3 : php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Failure evaluating code: %s%s", PHP_EOL, myeval);
183 2 : if (free_tmp) {
184 2 : zval_dtor(&tmp);
185 : }
186 2 : if (ASSERTG(bail)) {
187 1 : zend_bailout();
188 : }
189 1 : RETURN_FALSE;
190 : }
191 22 : efree(compiled_string_description);
192 :
193 22 : if (ASSERTG(quiet_eval)) {
194 7 : EG(error_reporting) = old_error_reporting;
195 : }
196 :
197 22 : convert_to_boolean(&retval);
198 22 : val = Z_LVAL(retval);
199 : } else {
200 88 : convert_to_boolean_ex(assertion);
201 88 : val = Z_LVAL_PP(assertion);
202 : }
203 :
204 110 : if (val) {
205 88 : if (free_tmp) {
206 6 : zval_dtor(&tmp);
207 : }
208 88 : RETURN_TRUE;
209 : }
210 :
211 22 : if (!ASSERTG(callback) && ASSERTG(cb)) {
212 5 : MAKE_STD_ZVAL(ASSERTG(callback));
213 5 : ZVAL_STRING(ASSERTG(callback), ASSERTG(cb), 1);
214 : }
215 :
216 22 : if (ASSERTG(callback)) {
217 : zval *args[3];
218 : zval *retval;
219 : int i;
220 18 : uint lineno = zend_get_executed_lineno(TSRMLS_C);
221 18 : char *filename = zend_get_executed_filename(TSRMLS_C);
222 :
223 18 : MAKE_STD_ZVAL(args[0]);
224 18 : MAKE_STD_ZVAL(args[1]);
225 18 : MAKE_STD_ZVAL(args[2]);
226 :
227 18 : ZVAL_STRING(args[0], SAFE_STRING(filename), 1);
228 18 : ZVAL_LONG (args[1], lineno);
229 18 : if (Z_TYPE_PP(assertion) == IS_UNICODE) {
230 14 : ZVAL_UNICODEL(args[2], Z_USTRVAL_PP(assertion), Z_USTRLEN_PP(assertion), 1);
231 : } else {
232 4 : ZVAL_STRING(args[2], SAFE_STRING(myeval), 1);
233 : }
234 :
235 18 : MAKE_STD_ZVAL(retval);
236 18 : ZVAL_FALSE(retval);
237 :
238 : /* XXX do we want to check for error here? */
239 18 : call_user_function(CG(function_table), NULL, ASSERTG(callback), retval, 3, args TSRMLS_CC);
240 :
241 72 : for (i = 0; i <= 2; i++) {
242 54 : zval_ptr_dtor(&(args[i]));
243 : }
244 18 : zval_ptr_dtor(&retval);
245 : }
246 :
247 22 : if (ASSERTG(warning)) {
248 9 : if (myeval) {
249 4 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Assertion \"%s\" failed", myeval);
250 : } else {
251 5 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Assertion failed");
252 : }
253 : }
254 :
255 22 : if (free_tmp) {
256 16 : zval_dtor(&tmp);
257 : }
258 :
259 22 : if (ASSERTG(bail)) {
260 2 : zend_bailout();
261 : }
262 : }
263 : /* }}} */
264 :
265 : /* {{{ proto mixed assert_options(int what [, mixed value]) U
266 : Set/get the various assert flags */
267 : PHP_FUNCTION(assert_options)
268 42 : {
269 42 : zval **value = NULL;
270 : long what;
271 : int oldint;
272 42 : int ac = ZEND_NUM_ARGS();
273 :
274 42 : if (zend_parse_parameters(ac TSRMLS_CC, "l|Z", &what, &value) == FAILURE) {
275 4 : return;
276 : }
277 :
278 38 : switch (what) {
279 : case ASSERT_ACTIVE:
280 5 : oldint = ASSERTG(active);
281 5 : if (ac == 2) {
282 4 : convert_to_long_ex(value);
283 4 : ASSERTG(active) = Z_LVAL_PP(value);
284 : }
285 5 : RETURN_LONG(oldint);
286 : break;
287 :
288 : case ASSERT_BAIL:
289 4 : oldint = ASSERTG(bail);
290 4 : if (ac == 2) {
291 3 : convert_to_long_ex(value);
292 3 : ASSERTG(bail) = Z_LVAL_PP(value);
293 : }
294 4 : RETURN_LONG(oldint);
295 : break;
296 :
297 : case ASSERT_QUIET_EVAL:
298 4 : oldint = ASSERTG(quiet_eval);
299 4 : if (ac == 2) {
300 3 : convert_to_long_ex(value);
301 3 : ASSERTG(quiet_eval) = Z_LVAL_PP(value);
302 : }
303 4 : RETURN_LONG(oldint);
304 : break;
305 :
306 : case ASSERT_WARNING:
307 6 : oldint = ASSERTG(warning);
308 6 : if (ac == 2) {
309 5 : convert_to_long_ex(value);
310 5 : ASSERTG(warning) = Z_LVAL_PP(value);
311 : }
312 6 : RETURN_LONG(oldint);
313 : break;
314 :
315 : case ASSERT_CALLBACK:
316 19 : if (ASSERTG(callback) != NULL) {
317 13 : RETVAL_ZVAL(ASSERTG(callback), 1, 0);
318 6 : } else if (ASSERTG(cb)) {
319 3 : RETVAL_STRING(ASSERTG(cb), 1);
320 : } else {
321 3 : RETVAL_NULL();
322 : }
323 19 : if (ac == 2) {
324 10 : if (ASSERTG(callback)) {
325 7 : zval_ptr_dtor(&ASSERTG(callback));
326 : }
327 10 : ASSERTG(callback) = *value;
328 10 : zval_add_ref(value);
329 : }
330 19 : return;
331 : break;
332 :
333 : default:
334 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown value %ld", what);
335 : break;
336 : }
337 :
338 0 : RETURN_FALSE;
339 : }
340 : /* }}} */
341 :
342 : /*
343 : * Local variables:
344 : * tab-width: 4
345 : * c-basic-offset: 4
346 : * End:
347 : * vim600: sw=4 ts=4 fdm=marker
348 : * vim<600: sw=4 ts=4
349 : */
|