1 : /*
2 : +----------------------------------------------------------------------+
3 : | Zend Engine |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1998-2009 Zend Technologies Ltd. (http://www.zend.com) |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 2.00 of the Zend 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.zend.com/license/2_00.txt. |
11 : | If you did not receive a copy of the Zend license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@zend.com so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Authors: Andi Gutmans <andi@zend.com> |
16 : | Zeev Suraski <zeev@zend.com> |
17 : +----------------------------------------------------------------------+
18 : */
19 :
20 : /* $Id: zend_operators.c 281670 2009-06-04 18:20:45Z mattwil $ */
21 :
22 : #include <ctype.h>
23 :
24 : #include "zend.h"
25 : #include "zend_operators.h"
26 : #include "zend_variables.h"
27 : #include "zend_globals.h"
28 : #include "zend_list.h"
29 : #include "zend_API.h"
30 : #include "zend_multiply.h"
31 : #include "zend_strtod.h"
32 : #include "zend_exceptions.h"
33 :
34 : #define LONG_SIGN_MASK (1L << (8*sizeof(long)-1))
35 :
36 : #if ZEND_USE_TOLOWER_L
37 : #include <locale.h>
38 : static _locale_t current_locale = NULL;
39 : /* this is true global! may lead to strange effects on ZTS, but so may setlocale() */
40 : #define zend_tolower(c) _tolower_l(c, current_locale)
41 : #else
42 : #define zend_tolower(c) tolower(c)
43 : #endif
44 :
45 : #define TYPE_PAIR(t1,t2) (((t1) << 4) | (t2))
46 :
47 : ZEND_API int zend_atoi(const char *str, int str_len) /* {{{ */
48 35268 : {
49 : int retval;
50 :
51 35268 : if (!str_len) {
52 35073 : str_len = strlen(str);
53 : }
54 35268 : retval = strtol(str, NULL, 0);
55 35268 : if (str_len>0) {
56 17822 : switch (str[str_len-1]) {
57 : case 'g':
58 : case 'G':
59 0 : retval *= 1024;
60 : /* break intentionally missing */
61 : case 'm':
62 : case 'M':
63 0 : retval *= 1024;
64 : /* break intentionally missing */
65 : case 'k':
66 : case 'K':
67 0 : retval *= 1024;
68 : break;
69 : }
70 : }
71 35268 : return retval;
72 : }
73 : /* }}} */
74 :
75 : ZEND_API long zend_atol(const char *str, int str_len) /* {{{ */
76 1093485 : {
77 : long retval;
78 :
79 1093485 : if (!str_len) {
80 34966 : str_len = strlen(str);
81 : }
82 1093485 : retval = strtol(str, NULL, 0);
83 1093485 : if (str_len>0) {
84 1058519 : switch (str[str_len-1]) {
85 : case 'g':
86 : case 'G':
87 4 : retval *= 1024;
88 : /* break intentionally missing */
89 : case 'm':
90 : case 'M':
91 52886 : retval *= 1024;
92 : /* break intentionally missing */
93 : case 'k':
94 : case 'K':
95 70520 : retval *= 1024;
96 : break;
97 : }
98 : }
99 1093485 : return retval;
100 : }
101 : /* }}} */
102 :
103 : ZEND_API double zend_string_to_double(const char *number, zend_uint length) /* {{{ */
104 0 : {
105 0 : double divisor = 10.0;
106 0 : double result = 0.0;
107 : double exponent;
108 0 : const char *end = number+length;
109 0 : const char *digit = number;
110 :
111 0 : if (!length) {
112 0 : return result;
113 : }
114 :
115 0 : while (digit < end) {
116 0 : if ((*digit <= '9' && *digit >= '0')) {
117 0 : result *= 10;
118 0 : result += *digit - '0';
119 0 : } else if (*digit == '.') {
120 0 : digit++;
121 0 : break;
122 0 : } else if (toupper(*digit) == 'E') {
123 0 : exponent = (double) atoi(digit+1);
124 0 : result *= pow(10.0, exponent);
125 0 : return result;
126 : } else {
127 0 : return result;
128 : }
129 0 : digit++;
130 : }
131 :
132 0 : while (digit < end) {
133 0 : if ((*digit <= '9' && *digit >= '0')) {
134 0 : result += (*digit - '0') / divisor;
135 0 : divisor *= 10;
136 0 : } else if (toupper(*digit) == 'E') {
137 0 : exponent = (double) atoi(digit+1);
138 0 : result *= pow(10.0, exponent);
139 0 : return result;
140 : } else {
141 0 : return result;
142 : }
143 0 : digit++;
144 : }
145 0 : return result;
146 : }
147 : /* }}} */
148 :
149 : ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC) /* {{{ */
150 206269 : {
151 206269 : switch (Z_TYPE_P(op)) {
152 : case IS_STRING:
153 : {
154 : char *strval;
155 :
156 101169 : strval = Z_STRVAL_P(op);
157 101169 : if ((Z_TYPE_P(op)=is_numeric_string(strval, Z_STRLEN_P(op), &Z_LVAL_P(op), &Z_DVAL_P(op), 1)) == 0) {
158 49 : ZVAL_LONG(op, 0);
159 : }
160 101169 : STR_FREE(strval);
161 101169 : break;
162 : }
163 : case IS_BOOL:
164 39 : Z_TYPE_P(op) = IS_LONG;
165 39 : break;
166 : case IS_RESOURCE:
167 7 : zend_list_delete(Z_LVAL_P(op));
168 7 : Z_TYPE_P(op) = IS_LONG;
169 7 : break;
170 : case IS_OBJECT:
171 7 : convert_to_long_base(op, 10);
172 7 : break;
173 : case IS_NULL:
174 48 : ZVAL_LONG(op, 0);
175 : break;
176 : }
177 206269 : }
178 : /* }}} */
179 :
180 : /* {{{ zendi_convert_scalar_to_number */
181 : #define zendi_convert_scalar_to_number(op, holder, result) \
182 : if (op==result) { \
183 : if (Z_TYPE_P(op) != IS_LONG) { \
184 : convert_scalar_to_number(op TSRMLS_CC); \
185 : } \
186 : } else { \
187 : switch (Z_TYPE_P(op)) { \
188 : case IS_STRING: \
189 : { \
190 : if ((Z_TYPE(holder)=is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &Z_LVAL(holder), &Z_DVAL(holder), 1)) == 0) { \
191 : ZVAL_LONG(&(holder), 0); \
192 : } \
193 : (op) = &(holder); \
194 : break; \
195 : } \
196 : case IS_BOOL: \
197 : case IS_RESOURCE: \
198 : ZVAL_LONG(&(holder), Z_LVAL_P(op)); \
199 : (op) = &(holder); \
200 : break; \
201 : case IS_NULL: \
202 : ZVAL_LONG(&(holder), 0); \
203 : (op) = &(holder); \
204 : break; \
205 : case IS_OBJECT: \
206 : (holder) = (*(op)); \
207 : zval_copy_ctor(&(holder)); \
208 : convert_to_long_base(&(holder), 10); \
209 : if (Z_TYPE(holder) == IS_LONG) { \
210 : (op) = &(holder); \
211 : } \
212 : break; \
213 : } \
214 : }
215 :
216 : /* }}} */
217 :
218 : /* {{{ zendi_convert_to_long */
219 : #define zendi_convert_to_long(op, holder, result) \
220 : if (op == result) { \
221 : convert_to_long(op); \
222 : } else if (Z_TYPE_P(op) != IS_LONG) { \
223 : switch (Z_TYPE_P(op)) { \
224 : case IS_NULL: \
225 : Z_LVAL(holder) = 0; \
226 : break; \
227 : case IS_DOUBLE: \
228 : Z_LVAL(holder) = zend_dval_to_lval(Z_DVAL_P(op)); \
229 : break; \
230 : case IS_STRING: \
231 : Z_LVAL(holder) = strtol(Z_STRVAL_P(op), NULL, 10); \
232 : break; \
233 : case IS_ARRAY: \
234 : Z_LVAL(holder) = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); \
235 : break; \
236 : case IS_OBJECT: \
237 : (holder) = (*(op)); \
238 : zval_copy_ctor(&(holder)); \
239 : convert_to_long_base(&(holder), 10); \
240 : break; \
241 : case IS_BOOL: \
242 : case IS_RESOURCE: \
243 : Z_LVAL(holder) = Z_LVAL_P(op); \
244 : break; \
245 : default: \
246 : zend_error(E_WARNING, "Cannot convert to ordinal value"); \
247 : Z_LVAL(holder) = 0; \
248 : break; \
249 : } \
250 : Z_TYPE(holder) = IS_LONG; \
251 : (op) = &(holder); \
252 : }
253 :
254 : /* }}} */
255 :
256 : /* {{{ zendi_convert_to_boolean */
257 : #define zendi_convert_to_boolean(op, holder, result) \
258 : if (op==result) { \
259 : convert_to_boolean(op); \
260 : } else if (Z_TYPE_P(op) != IS_BOOL) { \
261 : switch (Z_TYPE_P(op)) { \
262 : case IS_NULL: \
263 : Z_LVAL(holder) = 0; \
264 : break; \
265 : case IS_RESOURCE: \
266 : case IS_LONG: \
267 : Z_LVAL(holder) = (Z_LVAL_P(op) ? 1 : 0); \
268 : break; \
269 : case IS_DOUBLE: \
270 : Z_LVAL(holder) = (Z_DVAL_P(op) ? 1 : 0); \
271 : break; \
272 : case IS_STRING: \
273 : if (Z_STRLEN_P(op) == 0 \
274 : || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) { \
275 : Z_LVAL(holder) = 0; \
276 : } else { \
277 : Z_LVAL(holder) = 1; \
278 : } \
279 : break; \
280 : case IS_ARRAY: \
281 : Z_LVAL(holder) = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); \
282 : break; \
283 : case IS_OBJECT: \
284 : (holder) = (*(op)); \
285 : zval_copy_ctor(&(holder)); \
286 : convert_to_boolean(&(holder)); \
287 : break; \
288 : default: \
289 : Z_LVAL(holder) = 0; \
290 : break; \
291 : } \
292 : Z_TYPE(holder) = IS_BOOL; \
293 : (op) = &(holder); \
294 : }
295 :
296 : /* }}} */
297 :
298 : /* {{{ convert_object_to_type */
299 : #define convert_object_to_type(op, ctype, conv_func) \
300 : if (Z_OBJ_HT_P(op)->cast_object) { \
301 : zval dst; \
302 : if (Z_OBJ_HT_P(op)->cast_object(op, &dst, ctype TSRMLS_CC) == FAILURE) { \
303 : zend_error(E_RECOVERABLE_ERROR, \
304 : "Object of class %s could not be converted to %s", Z_OBJCE_P(op)->name, \
305 : zend_get_type_by_const(ctype)); \
306 : } else { \
307 : zval_dtor(op); \
308 : Z_TYPE_P(op) = ctype; \
309 : op->value = dst.value; \
310 : } \
311 : } else { \
312 : if (Z_OBJ_HT_P(op)->get) { \
313 : zval *newop = Z_OBJ_HT_P(op)->get(op TSRMLS_CC); \
314 : if (Z_TYPE_P(newop) != IS_OBJECT) { \
315 : /* for safety - avoid loop */ \
316 : zval_dtor(op); \
317 : *op = *newop; \
318 : FREE_ZVAL(newop); \
319 : conv_func(op); \
320 : } \
321 : } \
322 : }
323 :
324 : /* }}} */
325 :
326 : ZEND_API void convert_to_long(zval *op) /* {{{ */
327 927214 : {
328 927214 : if (Z_TYPE_P(op) != IS_LONG) {
329 55450 : convert_to_long_base(op, 10);
330 : }
331 927214 : }
332 : /* }}} */
333 :
334 : ZEND_API void convert_to_long_base(zval *op, int base) /* {{{ */
335 59279 : {
336 : long tmp;
337 :
338 59279 : switch (Z_TYPE_P(op)) {
339 : case IS_NULL:
340 1446 : Z_LVAL_P(op) = 0;
341 1446 : break;
342 : case IS_RESOURCE: {
343 : TSRMLS_FETCH();
344 :
345 118 : zend_list_delete(Z_LVAL_P(op));
346 : }
347 : /* break missing intentionally */
348 : case IS_BOOL:
349 : case IS_LONG:
350 9017 : break;
351 : case IS_DOUBLE:
352 9133 : Z_LVAL_P(op) = zend_dval_to_lval(Z_DVAL_P(op));
353 9133 : break;
354 : case IS_STRING:
355 : {
356 38758 : char *strval = Z_STRVAL_P(op);
357 :
358 38758 : Z_LVAL_P(op) = strtol(strval, NULL, base);
359 38758 : STR_FREE(strval);
360 : }
361 38758 : break;
362 : case IS_ARRAY:
363 865 : tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
364 865 : zval_dtor(op);
365 865 : Z_LVAL_P(op) = tmp;
366 865 : break;
367 : case IS_OBJECT:
368 : {
369 60 : int retval = 1;
370 : TSRMLS_FETCH();
371 :
372 60 : convert_object_to_type(op, IS_LONG, convert_to_long);
373 :
374 60 : if (Z_TYPE_P(op) == IS_LONG) {
375 60 : return;
376 : }
377 0 : zend_error(E_NOTICE, "Object of class %s could not be converted to int", Z_OBJCE_P(op)->name);
378 :
379 0 : zval_dtor(op);
380 0 : ZVAL_LONG(op, retval);
381 0 : return;
382 : }
383 : default:
384 0 : zend_error(E_WARNING, "Cannot convert to ordinal value");
385 0 : zval_dtor(op);
386 0 : Z_LVAL_P(op) = 0;
387 : break;
388 : }
389 :
390 59219 : Z_TYPE_P(op) = IS_LONG;
391 : }
392 : /* }}} */
393 :
394 : ZEND_API void convert_to_double(zval *op) /* {{{ */
395 332374 : {
396 : double tmp;
397 :
398 332374 : switch (Z_TYPE_P(op)) {
399 : case IS_NULL:
400 319 : Z_DVAL_P(op) = 0.0;
401 319 : break;
402 : case IS_RESOURCE: {
403 : TSRMLS_FETCH();
404 :
405 48 : zend_list_delete(Z_LVAL_P(op));
406 : }
407 : /* break missing intentionally */
408 : case IS_BOOL:
409 : case IS_LONG:
410 258375 : Z_DVAL_P(op) = (double) Z_LVAL_P(op);
411 258375 : break;
412 : case IS_DOUBLE:
413 72549 : break;
414 : case IS_STRING:
415 : {
416 742 : char *strval = Z_STRVAL_P(op);
417 :
418 742 : Z_DVAL_P(op) = zend_strtod(strval, NULL);
419 742 : STR_FREE(strval);
420 : }
421 742 : break;
422 : case IS_ARRAY:
423 369 : tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
424 369 : zval_dtor(op);
425 369 : Z_DVAL_P(op) = tmp;
426 369 : break;
427 : case IS_OBJECT:
428 : {
429 20 : double retval = 1.0;
430 : TSRMLS_FETCH();
431 :
432 20 : convert_object_to_type(op, IS_DOUBLE, convert_to_double);
433 :
434 20 : if (Z_TYPE_P(op) == IS_DOUBLE) {
435 20 : return;
436 : }
437 0 : zend_error(E_NOTICE, "Object of class %s could not be converted to double", Z_OBJCE_P(op)->name);
438 :
439 0 : zval_dtor(op);
440 0 : ZVAL_DOUBLE(op, retval);
441 0 : break;
442 : }
443 : default:
444 0 : zend_error(E_WARNING, "Cannot convert to real value (type=%d)", Z_TYPE_P(op));
445 0 : zval_dtor(op);
446 0 : Z_DVAL_P(op) = 0;
447 : break;
448 : }
449 332354 : Z_TYPE_P(op) = IS_DOUBLE;
450 : }
451 : /* }}} */
452 :
453 : ZEND_API void convert_to_null(zval *op) /* {{{ */
454 1093 : {
455 1093 : if (Z_TYPE_P(op) == IS_OBJECT) {
456 6 : if (Z_OBJ_HT_P(op)->cast_object) {
457 : zval *org;
458 : TSRMLS_FETCH();
459 :
460 6 : ALLOC_ZVAL(org);
461 6 : *org = *op;
462 6 : if (Z_OBJ_HT_P(op)->cast_object(org, op, IS_NULL TSRMLS_CC) == SUCCESS) {
463 0 : zval_dtor(org);
464 0 : return;
465 : }
466 6 : *op = *org;
467 6 : FREE_ZVAL(org);
468 : }
469 : }
470 :
471 1093 : zval_dtor(op);
472 1093 : Z_TYPE_P(op) = IS_NULL;
473 : }
474 : /* }}} */
475 :
476 : ZEND_API void convert_to_boolean(zval *op) /* {{{ */
477 79279 : {
478 : int tmp;
479 :
480 79279 : switch (Z_TYPE_P(op)) {
481 : case IS_BOOL:
482 3477 : break;
483 : case IS_NULL:
484 115 : Z_LVAL_P(op) = 0;
485 115 : break;
486 : case IS_RESOURCE: {
487 : TSRMLS_FETCH();
488 :
489 8 : zend_list_delete(Z_LVAL_P(op));
490 : }
491 : /* break missing intentionally */
492 : case IS_LONG:
493 689 : Z_LVAL_P(op) = (Z_LVAL_P(op) ? 1 : 0);
494 689 : break;
495 : case IS_DOUBLE:
496 177 : Z_LVAL_P(op) = (Z_DVAL_P(op) ? 1 : 0);
497 177 : break;
498 : case IS_STRING:
499 : {
500 262 : char *strval = Z_STRVAL_P(op);
501 :
502 330 : if (Z_STRLEN_P(op) == 0
503 : || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) {
504 68 : Z_LVAL_P(op) = 0;
505 : } else {
506 194 : Z_LVAL_P(op) = 1;
507 : }
508 262 : STR_FREE(strval);
509 : }
510 262 : break;
511 : case IS_ARRAY:
512 20 : tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
513 20 : zval_dtor(op);
514 20 : Z_LVAL_P(op) = tmp;
515 20 : break;
516 : case IS_OBJECT:
517 : {
518 74539 : zend_bool retval = 1;
519 : TSRMLS_FETCH();
520 :
521 74539 : convert_object_to_type(op, IS_BOOL, convert_to_boolean);
522 :
523 74539 : if (Z_TYPE_P(op) == IS_BOOL) {
524 74539 : return;
525 : }
526 :
527 0 : zval_dtor(op);
528 0 : ZVAL_BOOL(op, retval);
529 0 : break;
530 : }
531 : default:
532 0 : zval_dtor(op);
533 0 : Z_LVAL_P(op) = 0;
534 : break;
535 : }
536 4740 : Z_TYPE_P(op) = IS_BOOL;
537 : }
538 : /* }}} */
539 :
540 : ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{{ */
541 2479174 : {
542 : long lval;
543 : double dval;
544 :
545 2479174 : switch (Z_TYPE_P(op)) {
546 : case IS_NULL:
547 4975 : Z_STRVAL_P(op) = STR_EMPTY_ALLOC();
548 4975 : Z_STRLEN_P(op) = 0;
549 4975 : break;
550 : case IS_STRING:
551 0 : break;
552 : case IS_BOOL:
553 11220 : if (Z_LVAL_P(op)) {
554 878 : Z_STRVAL_P(op) = estrndup_rel("1", 1);
555 878 : Z_STRLEN_P(op) = 1;
556 : } else {
557 10342 : Z_STRVAL_P(op) = STR_EMPTY_ALLOC();
558 10342 : Z_STRLEN_P(op) = 0;
559 : }
560 11220 : break;
561 : case IS_RESOURCE: {
562 61 : long tmp = Z_LVAL_P(op);
563 : TSRMLS_FETCH();
564 :
565 61 : zend_list_delete(Z_LVAL_P(op));
566 61 : Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "Resource id #%ld", tmp);
567 61 : break;
568 : }
569 : case IS_LONG:
570 2460387 : lval = Z_LVAL_P(op);
571 :
572 2460387 : Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "%ld", lval);
573 2460387 : break;
574 : case IS_DOUBLE: {
575 : TSRMLS_FETCH();
576 2200 : dval = Z_DVAL_P(op);
577 2200 : Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "%.*G", (int) EG(precision), dval);
578 : /* %G already handles removing trailing zeros from the fractional part, yay */
579 2200 : break;
580 : }
581 : case IS_ARRAY:
582 243 : zend_error(E_NOTICE, "Array to string conversion");
583 243 : zval_dtor(op);
584 243 : Z_STRVAL_P(op) = estrndup_rel("Array", sizeof("Array")-1);
585 243 : Z_STRLEN_P(op) = sizeof("Array")-1;
586 243 : break;
587 : case IS_OBJECT: {
588 : TSRMLS_FETCH();
589 :
590 88 : convert_object_to_type(op, IS_STRING, convert_to_string);
591 :
592 80 : if (Z_TYPE_P(op) == IS_STRING) {
593 71 : return;
594 : }
595 :
596 9 : zend_error(E_NOTICE, "Object of class %s to string conversion", Z_OBJCE_P(op)->name);
597 9 : zval_dtor(op);
598 9 : Z_STRVAL_P(op) = estrndup_rel("Object", sizeof("Object")-1);
599 9 : Z_STRLEN_P(op) = sizeof("Object")-1;
600 9 : break;
601 : }
602 : default:
603 0 : zval_dtor(op);
604 0 : ZVAL_BOOL(op, 0);
605 : break;
606 : }
607 2479095 : Z_TYPE_P(op) = IS_STRING;
608 : }
609 : /* }}} */
610 :
611 : static void convert_scalar_to_array(zval *op, int type TSRMLS_DC) /* {{{ */
612 329 : {
613 : zval *entry;
614 :
615 329 : ALLOC_ZVAL(entry);
616 329 : *entry = *op;
617 329 : INIT_PZVAL(entry);
618 :
619 329 : switch (type) {
620 : case IS_ARRAY:
621 215 : ALLOC_HASHTABLE(Z_ARRVAL_P(op));
622 215 : zend_hash_init(Z_ARRVAL_P(op), 0, NULL, ZVAL_PTR_DTOR, 0);
623 215 : zend_hash_index_update(Z_ARRVAL_P(op), 0, (void *) &entry, sizeof(zval *), NULL);
624 215 : Z_TYPE_P(op) = IS_ARRAY;
625 215 : break;
626 : case IS_OBJECT:
627 114 : object_init(op);
628 114 : zend_hash_update(Z_OBJPROP_P(op), "scalar", sizeof("scalar"), (void *) &entry, sizeof(zval *), NULL);
629 : break;
630 : }
631 329 : }
632 : /* }}} */
633 :
634 : ZEND_API void convert_to_array(zval *op) /* {{{ */
635 17830 : {
636 : TSRMLS_FETCH();
637 :
638 17830 : switch (Z_TYPE_P(op)) {
639 : case IS_ARRAY:
640 17575 : break;
641 : /* OBJECTS_OPTIMIZE */
642 : case IS_OBJECT:
643 : {
644 : zval *tmp;
645 : HashTable *ht;
646 :
647 15 : ALLOC_HASHTABLE(ht);
648 15 : zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
649 15 : if (Z_OBJ_HT_P(op)->get_properties) {
650 15 : HashTable *obj_ht = Z_OBJ_HT_P(op)->get_properties(op TSRMLS_CC);
651 15 : if (obj_ht) {
652 15 : zend_hash_copy(ht, obj_ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
653 : }
654 : } else {
655 0 : convert_object_to_type(op, IS_ARRAY, convert_to_array);
656 :
657 0 : if (Z_TYPE_P(op) == IS_ARRAY) {
658 0 : zend_hash_destroy(ht);
659 0 : FREE_HASHTABLE(ht);
660 0 : return;
661 : }
662 : }
663 15 : zval_dtor(op);
664 15 : Z_TYPE_P(op) = IS_ARRAY;
665 15 : Z_ARRVAL_P(op) = ht;
666 : }
667 15 : break;
668 : case IS_NULL:
669 25 : ALLOC_HASHTABLE(Z_ARRVAL_P(op));
670 25 : zend_hash_init(Z_ARRVAL_P(op), 0, NULL, ZVAL_PTR_DTOR, 0);
671 25 : Z_TYPE_P(op) = IS_ARRAY;
672 25 : break;
673 : default:
674 215 : convert_scalar_to_array(op, IS_ARRAY TSRMLS_CC);
675 : break;
676 : }
677 : }
678 : /* }}} */
679 :
680 : ZEND_API void convert_to_object(zval *op) /* {{{ */
681 198 : {
682 : TSRMLS_FETCH();
683 :
684 198 : switch (Z_TYPE_P(op)) {
685 : case IS_ARRAY:
686 : {
687 67 : object_and_properties_init(op, zend_standard_class_def, Z_ARRVAL_P(op));
688 67 : break;
689 : }
690 : case IS_OBJECT:
691 10 : break;
692 : case IS_NULL:
693 7 : object_init(op);
694 7 : break;
695 : default:
696 114 : convert_scalar_to_array(op, IS_OBJECT TSRMLS_CC);
697 : break;
698 : }
699 198 : }
700 : /* }}} */
701 :
702 : ZEND_API void multi_convert_to_long_ex(int argc, ...) /* {{{ */
703 0 : {
704 : zval **arg;
705 : va_list ap;
706 :
707 0 : va_start(ap, argc);
708 :
709 0 : while (argc--) {
710 0 : arg = va_arg(ap, zval **);
711 0 : convert_to_long_ex(arg);
712 : }
713 :
714 0 : va_end(ap);
715 0 : }
716 : /* }}} */
717 :
718 : ZEND_API void multi_convert_to_double_ex(int argc, ...) /* {{{ */
719 0 : {
720 : zval **arg;
721 : va_list ap;
722 :
723 0 : va_start(ap, argc);
724 :
725 0 : while (argc--) {
726 0 : arg = va_arg(ap, zval **);
727 0 : convert_to_double_ex(arg);
728 : }
729 :
730 0 : va_end(ap);
731 0 : }
732 : /* }}} */
733 :
734 : ZEND_API void multi_convert_to_string_ex(int argc, ...) /* {{{ */
735 0 : {
736 : zval **arg;
737 : va_list ap;
738 :
739 0 : va_start(ap, argc);
740 :
741 0 : while (argc--) {
742 0 : arg = va_arg(ap, zval **);
743 0 : convert_to_string_ex(arg);
744 : }
745 :
746 0 : va_end(ap);
747 0 : }
748 : /* }}} */
749 :
750 : ZEND_API int add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
751 1033604 : {
752 : zval op1_copy, op2_copy;
753 1033604 : int converted = 0;
754 :
755 : while (1) {
756 1034076 : switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
757 : case TYPE_PAIR(IS_LONG, IS_LONG): {
758 298183 : long lval = Z_LVAL_P(op1) + Z_LVAL_P(op2);
759 :
760 : /* check for overflow by comparing sign bits */
761 298532 : if ((Z_LVAL_P(op1) & LONG_SIGN_MASK) == (Z_LVAL_P(op2) & LONG_SIGN_MASK)
762 : && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {
763 :
764 349 : ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2));
765 : } else {
766 297834 : ZVAL_LONG(result, lval);
767 : }
768 298183 : return SUCCESS;
769 : }
770 :
771 : case TYPE_PAIR(IS_LONG, IS_DOUBLE):
772 237 : ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2));
773 237 : return SUCCESS;
774 :
775 : case TYPE_PAIR(IS_DOUBLE, IS_LONG):
776 734945 : ZVAL_DOUBLE(result, Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2)));
777 734945 : return SUCCESS;
778 :
779 : case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
780 229 : ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2));
781 229 : return SUCCESS;
782 :
783 : case TYPE_PAIR(IS_ARRAY, IS_ARRAY): {
784 : zval *tmp;
785 :
786 6 : if ((result == op1) && (result == op2)) {
787 : /* $a += $a */
788 1 : return SUCCESS;
789 : }
790 5 : if (result != op1) {
791 4 : *result = *op1;
792 4 : zval_copy_ctor(result);
793 : }
794 5 : zend_hash_merge(Z_ARRVAL_P(result), Z_ARRVAL_P(op2), (void (*)(void *pData)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0);
795 5 : return SUCCESS;
796 : }
797 :
798 : default:
799 476 : if (!converted) {
800 472 : zendi_convert_scalar_to_number(op1, op1_copy, result);
801 472 : zendi_convert_scalar_to_number(op2, op2_copy, result);
802 472 : converted = 1;
803 : } else {
804 4 : zend_error(E_ERROR, "Unsupported operand types");
805 0 : return FAILURE; /* unknown datatype */
806 : }
807 : }
808 472 : }
809 : }
810 : /* }}} */
811 :
812 : ZEND_API int sub_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
813 272274 : {
814 : zval op1_copy, op2_copy;
815 272274 : int converted = 0;
816 :
817 : while (1) {
818 272507 : switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
819 : case TYPE_PAIR(IS_LONG, IS_LONG): {
820 252703 : long lval = Z_LVAL_P(op1) - Z_LVAL_P(op2);
821 :
822 : /* check for overflow by comparing sign bits */
823 252719 : if ((Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(op2) & LONG_SIGN_MASK)
824 : && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {
825 :
826 16 : ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2));
827 : } else {
828 252687 : ZVAL_LONG(result, lval);
829 : }
830 252703 : return SUCCESS;
831 :
832 : }
833 : case TYPE_PAIR(IS_LONG, IS_DOUBLE):
834 2124 : ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2));
835 2124 : return SUCCESS;
836 :
837 : case TYPE_PAIR(IS_DOUBLE, IS_LONG):
838 116 : ZVAL_DOUBLE(result, Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2)));
839 116 : return SUCCESS;
840 :
841 : case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
842 17330 : ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2));
843 17330 : return SUCCESS;
844 :
845 : default:
846 234 : if (!converted) {
847 233 : zendi_convert_scalar_to_number(op1, op1_copy, result);
848 233 : zendi_convert_scalar_to_number(op2, op2_copy, result);
849 233 : converted = 1;
850 : } else {
851 1 : zend_error(E_ERROR, "Unsupported operand types");
852 0 : return FAILURE; /* unknown datatype */
853 : }
854 : }
855 233 : }
856 : }
857 : /* }}} */
858 :
859 : ZEND_API int mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
860 13262 : {
861 : zval op1_copy, op2_copy;
862 13262 : int converted = 0;
863 :
864 : while (1) {
865 13487 : switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
866 : case TYPE_PAIR(IS_LONG, IS_LONG): {
867 : long overflow;
868 :
869 12921 : ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1),Z_LVAL_P(op2), Z_LVAL_P(result),Z_DVAL_P(result),overflow);
870 12921 : Z_TYPE_P(result) = overflow ? IS_DOUBLE : IS_LONG;
871 12921 : return SUCCESS;
872 :
873 : }
874 : case TYPE_PAIR(IS_LONG, IS_DOUBLE):
875 54 : ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) * Z_DVAL_P(op2));
876 54 : return SUCCESS;
877 :
878 : case TYPE_PAIR(IS_DOUBLE, IS_LONG):
879 77 : ZVAL_DOUBLE(result, Z_DVAL_P(op1) * ((double)Z_LVAL_P(op2)));
880 77 : return SUCCESS;
881 :
882 : case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
883 209 : ZVAL_DOUBLE(result, Z_DVAL_P(op1) * Z_DVAL_P(op2));
884 209 : return SUCCESS;
885 :
886 : default:
887 226 : if (!converted) {
888 225 : zendi_convert_scalar_to_number(op1, op1_copy, result);
889 225 : zendi_convert_scalar_to_number(op2, op2_copy, result);
890 225 : converted = 1;
891 : } else {
892 1 : zend_error(E_ERROR, "Unsupported operand types");
893 0 : return FAILURE; /* unknown datatype */
894 : }
895 : }
896 225 : }
897 : }
898 : /* }}} */
899 :
900 : ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
901 120281 : {
902 : zval op1_copy, op2_copy;
903 120281 : int converted = 0;
904 :
905 : while (1) {
906 120480 : switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
907 : case TYPE_PAIR(IS_LONG, IS_LONG):
908 76873 : if (Z_LVAL_P(op2) == 0) {
909 30 : zend_error(E_WARNING, "Division by zero");
910 30 : ZVAL_BOOL(result, 0);
911 30 : return FAILURE; /* division by zero */
912 76843 : } else if (Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == LONG_MIN) {
913 : /* Prevent overflow error/crash */
914 0 : ZVAL_DOUBLE(result, (double) LONG_MIN / -1);
915 0 : return SUCCESS;
916 : }
917 76843 : if (Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0) { /* integer */
918 55887 : ZVAL_LONG(result, Z_LVAL_P(op1) / Z_LVAL_P(op2));
919 : } else {
920 20956 : ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1)) / Z_LVAL_P(op2));
921 : }
922 76843 : return SUCCESS;
923 :
924 : case TYPE_PAIR(IS_DOUBLE, IS_LONG):
925 25300 : if (Z_LVAL_P(op2) == 0) {
926 15 : zend_error(E_WARNING, "Division by zero");
927 15 : ZVAL_BOOL(result, 0);
928 15 : return FAILURE; /* division by zero */
929 : }
930 25285 : ZVAL_DOUBLE(result, Z_DVAL_P(op1) / (double)Z_LVAL_P(op2));
931 25285 : return SUCCESS;
932 :
933 : case TYPE_PAIR(IS_LONG, IS_DOUBLE):
934 2039 : if (Z_DVAL_P(op2) == 0) {
935 0 : zend_error(E_WARNING, "Division by zero");
936 0 : ZVAL_BOOL(result, 0);
937 0 : return FAILURE; /* division by zero */
938 : }
939 2039 : ZVAL_DOUBLE(result, (double)Z_LVAL_P(op1) / Z_DVAL_P(op2));
940 2039 : return SUCCESS;
941 :
942 : case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
943 16068 : if (Z_DVAL_P(op2) == 0) {
944 0 : zend_error(E_WARNING, "Division by zero");
945 0 : ZVAL_BOOL(result, 0);
946 0 : return FAILURE; /* division by zero */
947 : }
948 16068 : ZVAL_DOUBLE(result, Z_DVAL_P(op1) / Z_DVAL_P(op2));
949 16068 : return SUCCESS;
950 :
951 : default:
952 200 : if (!converted) {
953 199 : zendi_convert_scalar_to_number(op1, op1_copy, result);
954 199 : zendi_convert_scalar_to_number(op2, op2_copy, result);
955 199 : converted = 1;
956 : } else {
957 1 : zend_error(E_ERROR, "Unsupported operand types");
958 0 : return FAILURE; /* unknown datatype */
959 : }
960 : }
961 199 : }
962 : }
963 : /* }}} */
964 :
965 : ZEND_API int mod_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
966 49397 : {
967 : zval op1_copy, op2_copy;
968 :
969 49397 : zendi_convert_to_long(op1, op1_copy, result);
970 49397 : zendi_convert_to_long(op2, op2_copy, result);
971 :
972 49397 : if (Z_LVAL_P(op2) == 0) {
973 43 : zend_error(E_WARNING, "Division by zero");
974 43 : ZVAL_BOOL(result, 0);
975 43 : return FAILURE; /* modulus by zero */
976 : }
977 :
978 49354 : if (Z_LVAL_P(op2) == -1) {
979 : /* Prevent overflow error/crash if op1==LONG_MIN */
980 3 : ZVAL_LONG(result, 0);
981 3 : return SUCCESS;
982 : }
983 :
984 49351 : ZVAL_LONG(result, Z_LVAL_P(op1) % Z_LVAL_P(op2));
985 49351 : return SUCCESS;
986 : }
987 : /* }}} */
988 :
989 : ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
990 0 : {
991 : zval op1_copy, op2_copy;
992 :
993 0 : zendi_convert_to_boolean(op1, op1_copy, result);
994 0 : zendi_convert_to_boolean(op2, op2_copy, result);
995 0 : ZVAL_BOOL(result, Z_LVAL_P(op1) ^ Z_LVAL_P(op2));
996 0 : return SUCCESS;
997 : }
998 : /* }}} */
999 :
1000 : ZEND_API int boolean_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */
1001 2535130 : {
1002 : zval op1_copy;
1003 :
1004 2535130 : zendi_convert_to_boolean(op1, op1_copy, result);
1005 2535130 : ZVAL_BOOL(result, !Z_LVAL_P(op1));
1006 2535130 : return SUCCESS;
1007 : }
1008 : /* }}} */
1009 :
1010 : ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */
1011 95 : {
1012 95 : zval op1_copy = *op1;
1013 :
1014 95 : op1 = &op1_copy;
1015 :
1016 95 : if (Z_TYPE_P(op1) == IS_LONG) {
1017 78 : ZVAL_LONG(result, ~Z_LVAL_P(op1));
1018 78 : return SUCCESS;
1019 17 : } else if (Z_TYPE_P(op1) == IS_DOUBLE) {
1020 1 : ZVAL_LONG(result, ~zend_dval_to_lval(Z_DVAL_P(op1)));
1021 1 : return SUCCESS;
1022 16 : } else if (Z_TYPE_P(op1) == IS_STRING) {
1023 : int i;
1024 :
1025 15 : Z_TYPE_P(result) = IS_STRING;
1026 15 : Z_STRVAL_P(result) = estrndup(Z_STRVAL_P(op1), Z_STRLEN_P(op1));
1027 15 : Z_STRLEN_P(result) = Z_STRLEN_P(op1);
1028 83 : for (i = 0; i < Z_STRLEN_P(op1); i++) {
1029 68 : Z_STRVAL_P(result)[i] = ~Z_STRVAL_P(op1)[i];
1030 : }
1031 15 : return SUCCESS;
1032 : }
1033 1 : zend_error(E_ERROR, "Unsupported operand types");
1034 0 : return FAILURE; /* unknown datatype */
1035 : }
1036 : /* }}} */
1037 :
1038 : ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1039 7799 : {
1040 : zval op1_copy, op2_copy;
1041 :
1042 7799 : if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1043 : zval *longer, *shorter;
1044 : char *result_str;
1045 : int i, result_len;
1046 :
1047 200 : if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
1048 117 : longer = op1;
1049 117 : shorter = op2;
1050 : } else {
1051 83 : longer = op2;
1052 83 : shorter = op1;
1053 : }
1054 :
1055 200 : Z_TYPE_P(result) = IS_STRING;
1056 200 : result_len = Z_STRLEN_P(longer);
1057 200 : result_str = estrndup(Z_STRVAL_P(longer), Z_STRLEN_P(longer));
1058 888 : for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1059 688 : result_str[i] |= Z_STRVAL_P(shorter)[i];
1060 : }
1061 200 : if (result==op1) {
1062 1 : STR_FREE(Z_STRVAL_P(result));
1063 : }
1064 200 : Z_STRVAL_P(result) = result_str;
1065 200 : Z_STRLEN_P(result) = result_len;
1066 200 : return SUCCESS;
1067 : }
1068 7599 : zendi_convert_to_long(op1, op1_copy, result);
1069 7599 : zendi_convert_to_long(op2, op2_copy, result);
1070 :
1071 7599 : ZVAL_LONG(result, Z_LVAL_P(op1) | Z_LVAL_P(op2));
1072 7599 : return SUCCESS;
1073 : }
1074 : /* }}} */
1075 :
1076 : ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1077 44065 : {
1078 : zval op1_copy, op2_copy;
1079 :
1080 44065 : if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1081 : zval *longer, *shorter;
1082 : char *result_str;
1083 : int i, result_len;
1084 :
1085 201 : if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
1086 117 : longer = op1;
1087 117 : shorter = op2;
1088 : } else {
1089 84 : longer = op2;
1090 84 : shorter = op1;
1091 : }
1092 :
1093 201 : Z_TYPE_P(result) = IS_STRING;
1094 201 : result_len = Z_STRLEN_P(shorter);
1095 201 : result_str = estrndup(Z_STRVAL_P(shorter), Z_STRLEN_P(shorter));
1096 888 : for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1097 687 : result_str[i] &= Z_STRVAL_P(longer)[i];
1098 : }
1099 201 : if (result==op1) {
1100 1 : STR_FREE(Z_STRVAL_P(result));
1101 : }
1102 201 : Z_STRVAL_P(result) = result_str;
1103 201 : Z_STRLEN_P(result) = result_len;
1104 201 : return SUCCESS;
1105 : }
1106 :
1107 :
1108 43864 : zendi_convert_to_long(op1, op1_copy, result);
1109 43864 : zendi_convert_to_long(op2, op2_copy, result);
1110 :
1111 43864 : ZVAL_LONG(result, Z_LVAL_P(op1) & Z_LVAL_P(op2));
1112 43864 : return SUCCESS;
1113 : }
1114 : /* }}} */
1115 :
1116 : ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1117 215 : {
1118 : zval op1_copy, op2_copy;
1119 :
1120 215 : if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1121 : zval *longer, *shorter;
1122 : char *result_str;
1123 : int i, result_len;
1124 :
1125 202 : if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
1126 118 : longer = op1;
1127 118 : shorter = op2;
1128 : } else {
1129 84 : longer = op2;
1130 84 : shorter = op1;
1131 : }
1132 :
1133 202 : Z_TYPE_P(result) = IS_STRING;
1134 202 : result_len = Z_STRLEN_P(shorter);
1135 202 : result_str = estrndup(Z_STRVAL_P(shorter), Z_STRLEN_P(shorter));
1136 892 : for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1137 690 : result_str[i] ^= Z_STRVAL_P(longer)[i];
1138 : }
1139 202 : if (result==op1) {
1140 1 : STR_FREE(Z_STRVAL_P(result));
1141 : }
1142 202 : Z_STRVAL_P(result) = result_str;
1143 202 : Z_STRLEN_P(result) = result_len;
1144 202 : return SUCCESS;
1145 : }
1146 :
1147 13 : zendi_convert_to_long(op1, op1_copy, result);
1148 13 : zendi_convert_to_long(op2, op2_copy, result);
1149 :
1150 13 : ZVAL_LONG(result, Z_LVAL_P(op1) ^ Z_LVAL_P(op2));
1151 13 : return SUCCESS;
1152 : }
1153 : /* }}} */
1154 :
1155 : ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1156 3144 : {
1157 : zval op1_copy, op2_copy;
1158 :
1159 3144 : zendi_convert_to_long(op1, op1_copy, result);
1160 3144 : zendi_convert_to_long(op2, op2_copy, result);
1161 3144 : ZVAL_LONG(result, Z_LVAL_P(op1) << Z_LVAL_P(op2));
1162 3144 : return SUCCESS;
1163 : }
1164 : /* }}} */
1165 :
1166 : ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1167 35069 : {
1168 : zval op1_copy, op2_copy;
1169 :
1170 35069 : zendi_convert_to_long(op1, op1_copy, result);
1171 35069 : zendi_convert_to_long(op2, op2_copy, result);
1172 35069 : ZVAL_LONG(result, Z_LVAL_P(op1) >> Z_LVAL_P(op2));
1173 35069 : return SUCCESS;
1174 : }
1175 : /* }}} */
1176 :
1177 : /* must support result==op1 */
1178 : ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */
1179 975596 : {
1180 975596 : Z_STRLEN_P(result) = Z_STRLEN_P(op1) + 1;
1181 975596 : Z_STRVAL_P(result) = (char *) erealloc(Z_STRVAL_P(op1), Z_STRLEN_P(result)+1);
1182 975596 : Z_STRVAL_P(result)[Z_STRLEN_P(result) - 1] = (char) Z_LVAL_P(op2);
1183 975596 : Z_STRVAL_P(result)[Z_STRLEN_P(result)] = 0;
1184 975596 : Z_TYPE_P(result) = IS_STRING;
1185 975596 : return SUCCESS;
1186 : }
1187 : /* }}} */
1188 :
1189 : /* must support result==op1 */
1190 : ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */
1191 2952376 : {
1192 2952376 : int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
1193 :
1194 2952376 : Z_STRVAL_P(result) = (char *) erealloc(Z_STRVAL_P(op1), length+1);
1195 2952376 : memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
1196 2952376 : Z_STRVAL_P(result)[length] = 0;
1197 2952376 : Z_STRLEN_P(result) = length;
1198 2952376 : Z_TYPE_P(result) = IS_STRING;
1199 2952376 : return SUCCESS;
1200 : }
1201 : /* }}} */
1202 :
1203 : ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1204 3923723 : {
1205 : zval op1_copy, op2_copy;
1206 3923723 : int use_copy1 = 0, use_copy2 = 0;
1207 :
1208 3923723 : if (Z_TYPE_P(op1) != IS_STRING) {
1209 7345 : zend_make_printable_zval(op1, &op1_copy, &use_copy1);
1210 : }
1211 3923723 : if (Z_TYPE_P(op2) != IS_STRING) {
1212 54767 : zend_make_printable_zval(op2, &op2_copy, &use_copy2);
1213 : }
1214 :
1215 3923723 : if (use_copy1) {
1216 : /* We have created a converted copy of op1. Therefore, op1 won't become the result so
1217 : * we have to free it.
1218 : */
1219 7345 : if (result == op1) {
1220 8 : zval_dtor(op1);
1221 : }
1222 7345 : op1 = &op1_copy;
1223 : }
1224 3923723 : if (use_copy2) {
1225 54767 : op2 = &op2_copy;
1226 : }
1227 3923723 : if (result==op1) { /* special case, perform operations on result */
1228 2983583 : uint res_len = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
1229 :
1230 2983583 : Z_STRVAL_P(result) = erealloc(Z_STRVAL_P(result), res_len+1);
1231 :
1232 2983583 : memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(result), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
1233 2983583 : Z_STRVAL_P(result)[res_len]=0;
1234 2983583 : Z_STRLEN_P(result) = res_len;
1235 : } else {
1236 940140 : Z_STRLEN_P(result) = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
1237 940140 : Z_STRVAL_P(result) = (char *) emalloc(Z_STRLEN_P(result) + 1);
1238 940140 : memcpy(Z_STRVAL_P(result), Z_STRVAL_P(op1), Z_STRLEN_P(op1));
1239 940140 : memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
1240 940140 : Z_STRVAL_P(result)[Z_STRLEN_P(result)] = 0;
1241 940140 : Z_TYPE_P(result) = IS_STRING;
1242 : }
1243 3923723 : if (use_copy1) {
1244 7345 : zval_dtor(op1);
1245 : }
1246 3923723 : if (use_copy2) {
1247 54767 : zval_dtor(op2);
1248 : }
1249 3923723 : return SUCCESS;
1250 : }
1251 : /* }}} */
1252 :
1253 : ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1254 814568 : {
1255 : zval op1_copy, op2_copy;
1256 814568 : int use_copy1 = 0, use_copy2 = 0;
1257 :
1258 814568 : if (Z_TYPE_P(op1) != IS_STRING) {
1259 534792 : zend_make_printable_zval(op1, &op1_copy, &use_copy1);
1260 : }
1261 814568 : if (Z_TYPE_P(op2) != IS_STRING) {
1262 609423 : zend_make_printable_zval(op2, &op2_copy, &use_copy2);
1263 : }
1264 :
1265 814568 : if (use_copy1) {
1266 534792 : op1 = &op1_copy;
1267 : }
1268 814568 : if (use_copy2) {
1269 609423 : op2 = &op2_copy;
1270 : }
1271 :
1272 814568 : ZVAL_LONG(result, zend_binary_zval_strcmp(op1, op2));
1273 :
1274 814568 : if (use_copy1) {
1275 534792 : zval_dtor(op1);
1276 : }
1277 814568 : if (use_copy2) {
1278 609423 : zval_dtor(op2);
1279 : }
1280 814568 : return SUCCESS;
1281 : }
1282 : /* }}} */
1283 :
1284 : #if HAVE_STRCOLL
1285 : ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1286 33 : {
1287 : zval op1_copy, op2_copy;
1288 33 : int use_copy1 = 0, use_copy2 = 0;
1289 :
1290 33 : if (Z_TYPE_P(op1) != IS_STRING) {
1291 0 : zend_make_printable_zval(op1, &op1_copy, &use_copy1);
1292 : }
1293 33 : if (Z_TYPE_P(op2) != IS_STRING) {
1294 0 : zend_make_printable_zval(op2, &op2_copy, &use_copy2);
1295 : }
1296 :
1297 33 : if (use_copy1) {
1298 0 : op1 = &op1_copy;
1299 : }
1300 33 : if (use_copy2) {
1301 0 : op2 = &op2_copy;
1302 : }
1303 :
1304 33 : ZVAL_LONG(result, strcoll(Z_STRVAL_P(op1), Z_STRVAL_P(op2)));
1305 :
1306 33 : if (use_copy1) {
1307 0 : zval_dtor(op1);
1308 : }
1309 33 : if (use_copy2) {
1310 0 : zval_dtor(op2);
1311 : }
1312 33 : return SUCCESS;
1313 : }
1314 : /* }}} */
1315 : #endif
1316 :
1317 : ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1318 926 : {
1319 : zval op1_copy, op2_copy;
1320 :
1321 926 : op1_copy = *op1;
1322 926 : zval_copy_ctor(&op1_copy);
1323 :
1324 926 : op2_copy = *op2;
1325 926 : zval_copy_ctor(&op2_copy);
1326 :
1327 926 : convert_to_double(&op1_copy);
1328 926 : convert_to_double(&op2_copy);
1329 :
1330 926 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL(op1_copy)-Z_DVAL(op2_copy)));
1331 :
1332 926 : return SUCCESS;
1333 : }
1334 : /* }}} */
1335 :
1336 : static inline void zend_free_obj_get_result(zval *op TSRMLS_DC) /* {{{ */
1337 413 : {
1338 413 : if (Z_REFCOUNT_P(op) == 0) {
1339 1 : GC_REMOVE_ZVAL_FROM_BUFFER(op);
1340 1 : zval_dtor(op);
1341 1 : FREE_ZVAL(op);
1342 : } else {
1343 412 : zval_ptr_dtor(&op);
1344 : }
1345 413 : }
1346 : /* }}} */
1347 :
1348 : ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1349 7796319 : {
1350 : int ret;
1351 7796319 : int converted = 0;
1352 : zval op1_copy, op2_copy;
1353 : zval *op_free;
1354 :
1355 : while (1) {
1356 7817313 : switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
1357 : case TYPE_PAIR(IS_LONG, IS_LONG):
1358 6621248 : ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0));
1359 6621248 : return SUCCESS;
1360 :
1361 : case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1362 9472 : Z_DVAL_P(result) = Z_DVAL_P(op1) - (double)Z_LVAL_P(op2);
1363 9472 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1364 9472 : return SUCCESS;
1365 :
1366 : case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1367 168898 : Z_DVAL_P(result) = (double)Z_LVAL_P(op1) - Z_DVAL_P(op2);
1368 168898 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1369 168898 : return SUCCESS;
1370 :
1371 : case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1372 1454 : Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2);
1373 1454 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1374 1454 : return SUCCESS;
1375 :
1376 : case TYPE_PAIR(IS_ARRAY, IS_ARRAY):
1377 705 : zend_compare_arrays(result, op1, op2 TSRMLS_CC);
1378 705 : return SUCCESS;
1379 :
1380 : case TYPE_PAIR(IS_NULL, IS_NULL):
1381 251 : ZVAL_LONG(result, 0);
1382 251 : return SUCCESS;
1383 :
1384 : case TYPE_PAIR(IS_NULL, IS_BOOL):
1385 24 : ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0);
1386 24 : return SUCCESS;
1387 :
1388 : case TYPE_PAIR(IS_BOOL, IS_NULL):
1389 30 : ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0);
1390 30 : return SUCCESS;
1391 :
1392 : case TYPE_PAIR(IS_BOOL, IS_BOOL):
1393 4672 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
1394 4672 : return SUCCESS;
1395 :
1396 : case TYPE_PAIR(IS_STRING, IS_STRING):
1397 975626 : zendi_smart_strcmp(result, op1, op2);
1398 975626 : return SUCCESS;
1399 :
1400 : case TYPE_PAIR(IS_NULL, IS_STRING):
1401 104 : ZVAL_LONG(result, zend_binary_strcmp("", 0, Z_STRVAL_P(op2), Z_STRLEN_P(op2)));
1402 104 : return SUCCESS;
1403 :
1404 : case TYPE_PAIR(IS_STRING, IS_NULL):
1405 143 : ZVAL_LONG(result, zend_binary_strcmp(Z_STRVAL_P(op1), Z_STRLEN_P(op1), "", 0));
1406 143 : return SUCCESS;
1407 :
1408 : case TYPE_PAIR(IS_OBJECT, IS_NULL):
1409 48 : ZVAL_LONG(result, 1);
1410 48 : return SUCCESS;
1411 :
1412 : case TYPE_PAIR(IS_NULL, IS_OBJECT):
1413 15 : ZVAL_LONG(result, -1);
1414 15 : return SUCCESS;
1415 :
1416 : case TYPE_PAIR(IS_OBJECT, IS_OBJECT):
1417 : /* If both are objects sharing the same comparision handler then use is */
1418 572 : if (Z_OBJ_HANDLER_P(op1,compare_objects) == Z_OBJ_HANDLER_P(op2,compare_objects)) {
1419 571 : if (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2)) {
1420 : /* object handles are identical, apprently this is the same object */
1421 23 : ZVAL_LONG(result, 0);
1422 23 : return SUCCESS;
1423 : }
1424 548 : ZVAL_LONG(result, Z_OBJ_HT_P(op1)->compare_objects(op1, op2 TSRMLS_CC));
1425 548 : return SUCCESS;
1426 : }
1427 : /* break missing intentionally */
1428 :
1429 : default:
1430 34052 : if (Z_TYPE_P(op1) == IS_OBJECT) {
1431 217 : if (Z_OBJ_HT_P(op1)->get) {
1432 1 : op_free = Z_OBJ_HT_P(op1)->get(op1 TSRMLS_CC);
1433 1 : ret = compare_function(result, op_free, op2 TSRMLS_CC);
1434 1 : zend_free_obj_get_result(op_free TSRMLS_CC);
1435 1 : return ret;
1436 216 : } else if (Z_TYPE_P(op2) != IS_OBJECT && Z_OBJ_HT_P(op1)->cast_object) {
1437 215 : ALLOC_INIT_ZVAL(op_free);
1438 215 : if (Z_OBJ_HT_P(op1)->cast_object(op1, op_free, Z_TYPE_P(op2) TSRMLS_CC) == FAILURE) {
1439 112 : ZVAL_LONG(result, 1);
1440 112 : zend_free_obj_get_result(op_free TSRMLS_CC);
1441 112 : return SUCCESS;
1442 : }
1443 103 : ret = compare_function(result, op_free, op2 TSRMLS_CC);
1444 103 : zend_free_obj_get_result(op_free TSRMLS_CC);
1445 103 : return ret;
1446 : }
1447 : }
1448 33836 : if (Z_TYPE_P(op2) == IS_OBJECT) {
1449 198 : if (Z_OBJ_HT_P(op2)->get) {
1450 0 : op_free = Z_OBJ_HT_P(op2)->get(op2 TSRMLS_CC);
1451 0 : ret = compare_function(result, op1, op_free TSRMLS_CC);
1452 0 : zend_free_obj_get_result(op_free TSRMLS_CC);
1453 0 : return ret;
1454 198 : } else if (Z_TYPE_P(op1) != IS_OBJECT && Z_OBJ_HT_P(op2)->cast_object) {
1455 197 : ALLOC_INIT_ZVAL(op_free);
1456 197 : if (Z_OBJ_HT_P(op2)->cast_object(op2, op_free, Z_TYPE_P(op1) TSRMLS_CC) == FAILURE) {
1457 107 : ZVAL_LONG(result, -1);
1458 107 : zend_free_obj_get_result(op_free TSRMLS_CC);
1459 107 : return SUCCESS;
1460 : }
1461 90 : ret = compare_function(result, op1, op_free TSRMLS_CC);
1462 90 : zend_free_obj_get_result(op_free TSRMLS_CC);
1463 90 : return ret;
1464 : }
1465 : }
1466 33639 : if (!converted) {
1467 33088 : if (Z_TYPE_P(op1) == IS_NULL) {
1468 212 : zendi_convert_to_boolean(op2, op2_copy, result);
1469 212 : ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0);
1470 212 : return SUCCESS;
1471 32876 : } else if (Z_TYPE_P(op2) == IS_NULL) {
1472 89 : zendi_convert_to_boolean(op1, op1_copy, result);
1473 89 : ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0);
1474 89 : return SUCCESS;
1475 32787 : } else if (Z_TYPE_P(op1) == IS_BOOL) {
1476 8429 : zendi_convert_to_boolean(op2, op2_copy, result);
1477 8429 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
1478 8429 : return SUCCESS;
1479 24358 : } else if (Z_TYPE_P(op2) == IS_BOOL) {
1480 3364 : zendi_convert_to_boolean(op1, op1_copy, result);
1481 3364 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
1482 3364 : return SUCCESS;
1483 : } else {
1484 20994 : zendi_convert_scalar_to_number(op1, op1_copy, result);
1485 20994 : zendi_convert_scalar_to_number(op2, op2_copy, result);
1486 20994 : converted = 1;
1487 : }
1488 551 : } else if (Z_TYPE_P(op1)==IS_ARRAY) {
1489 271 : ZVAL_LONG(result, 1);
1490 271 : return SUCCESS;
1491 280 : } else if (Z_TYPE_P(op2)==IS_ARRAY) {
1492 280 : ZVAL_LONG(result, -1);
1493 280 : return SUCCESS;
1494 0 : } else if (Z_TYPE_P(op1)==IS_OBJECT) {
1495 0 : ZVAL_LONG(result, 1);
1496 0 : return SUCCESS;
1497 0 : } else if (Z_TYPE_P(op2)==IS_OBJECT) {
1498 0 : ZVAL_LONG(result, -1);
1499 0 : return SUCCESS;
1500 : } else {
1501 0 : ZVAL_LONG(result, 0);
1502 0 : return FAILURE;
1503 : }
1504 : }
1505 20994 : }
1506 : }
1507 : /* }}} */
1508 :
1509 : static int hash_zval_identical_function(const zval **z1, const zval **z2) /* {{{ */
1510 1144 : {
1511 : zval result;
1512 : TSRMLS_FETCH();
1513 :
1514 : /* is_identical_function() returns 1 in case of identity and 0 in case
1515 : * of a difference;
1516 : * whereas this comparison function is expected to return 0 on identity,
1517 : * and non zero otherwise.
1518 : */
1519 1144 : if (is_identical_function(&result, (zval *) *z1, (zval *) *z2 TSRMLS_CC)==FAILURE) {
1520 0 : return 1;
1521 : }
1522 1144 : return !Z_LVAL(result);
1523 : }
1524 : /* }}} */
1525 :
1526 : ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1527 2523863 : {
1528 2523863 : Z_TYPE_P(result) = IS_BOOL;
1529 2523863 : if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) {
1530 1561322 : Z_LVAL_P(result) = 0;
1531 1561322 : return SUCCESS;
1532 : }
1533 962541 : switch (Z_TYPE_P(op1)) {
1534 : case IS_NULL:
1535 2268 : Z_LVAL_P(result) = 1;
1536 2268 : break;
1537 : case IS_BOOL:
1538 : case IS_LONG:
1539 : case IS_RESOURCE:
1540 941363 : Z_LVAL_P(result) = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
1541 941363 : break;
1542 : case IS_DOUBLE:
1543 192 : Z_LVAL_P(result) = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
1544 192 : break;
1545 : case IS_STRING:
1546 18603 : Z_LVAL_P(result) = ((Z_STRLEN_P(op1) == Z_STRLEN_P(op2))
1547 : && (!memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1))));
1548 18603 : break;
1549 : case IS_ARRAY:
1550 82 : Z_LVAL_P(result) = zend_hash_compare(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2), (compare_func_t) hash_zval_identical_function, 1 TSRMLS_CC)==0;
1551 82 : break;
1552 : case IS_OBJECT:
1553 33 : if (Z_OBJ_HT_P(op1) == Z_OBJ_HT_P(op2)) {
1554 33 : Z_LVAL_P(result) = (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2));
1555 : } else {
1556 0 : Z_LVAL_P(result) = 0;
1557 : }
1558 33 : break;
1559 : default:
1560 0 : Z_LVAL_P(result) = 0;
1561 0 : return FAILURE;
1562 : }
1563 962541 : return SUCCESS;
1564 : }
1565 : /* }}} */
1566 :
1567 : ZEND_API int is_not_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1568 0 : {
1569 0 : if (is_identical_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1570 0 : return FAILURE;
1571 : }
1572 0 : Z_LVAL_P(result) = !Z_LVAL_P(result);
1573 0 : return SUCCESS;
1574 : }
1575 : /* }}} */
1576 :
1577 : ZEND_API int is_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1578 329654 : {
1579 329654 : if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1580 0 : return FAILURE;
1581 : }
1582 329654 : ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
1583 329654 : return SUCCESS;
1584 : }
1585 : /* }}} */
1586 :
1587 : ZEND_API int is_not_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1588 0 : {
1589 0 : if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1590 0 : return FAILURE;
1591 : }
1592 0 : ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
1593 0 : return SUCCESS;
1594 : }
1595 : /* }}} */
1596 :
1597 : ZEND_API int is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1598 1894 : {
1599 1894 : if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1600 0 : return FAILURE;
1601 : }
1602 1894 : ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
1603 1894 : return SUCCESS;
1604 : }
1605 : /* }}} */
1606 :
1607 : ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1608 1277 : {
1609 1277 : if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1610 0 : return FAILURE;
1611 : }
1612 1277 : ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
1613 1277 : return SUCCESS;
1614 : }
1615 : /* }}} */
1616 :
1617 : ZEND_API zend_bool instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool interfaces_only TSRMLS_DC) /* {{{ */
1618 355628 : {
1619 : zend_uint i;
1620 :
1621 536281 : for (i=0; i<instance_ce->num_interfaces; i++) {
1622 201354 : if (instanceof_function(instance_ce->interfaces[i], ce TSRMLS_CC)) {
1623 20701 : return 1;
1624 : }
1625 : }
1626 334927 : if (!interfaces_only) {
1627 872203 : while (instance_ce) {
1628 344305 : if (instance_ce == ce) {
1629 141948 : return 1;
1630 : }
1631 202357 : instance_ce = instance_ce->parent;
1632 : }
1633 : }
1634 :
1635 192979 : return 0;
1636 : }
1637 : /* }}} */
1638 :
1639 : ZEND_API zend_bool instanceof_function(const zend_class_entry *instance_ce, const zend_class_entry *ce TSRMLS_DC) /* {{{ */
1640 337025 : {
1641 337025 : return instanceof_function_ex(instance_ce, ce, 0 TSRMLS_CC);
1642 : }
1643 : /* }}} */
1644 :
1645 : #define LOWER_CASE 1
1646 : #define UPPER_CASE 2
1647 : #define NUMERIC 3
1648 :
1649 : static void increment_string(zval *str) /* {{{ */
1650 41 : {
1651 41 : int carry=0;
1652 41 : int pos=Z_STRLEN_P(str)-1;
1653 41 : char *s=Z_STRVAL_P(str);
1654 : char *t;
1655 41 : int last=0; /* Shut up the compiler warning */
1656 : int ch;
1657 :
1658 41 : if (Z_STRLEN_P(str) == 0) {
1659 1 : STR_FREE(Z_STRVAL_P(str));
1660 1 : Z_STRVAL_P(str) = estrndup("1", sizeof("1")-1);
1661 1 : Z_STRLEN_P(str) = 1;
1662 1 : return;
1663 : }
1664 :
1665 84 : while (pos >= 0) {
1666 44 : ch = s[pos];
1667 76 : if (ch >= 'a' && ch <= 'z') {
1668 32 : if (ch == 'z') {
1669 2 : s[pos] = 'a';
1670 2 : carry=1;
1671 : } else {
1672 30 : s[pos]++;
1673 30 : carry=0;
1674 : }
1675 32 : last=LOWER_CASE;
1676 18 : } else if (ch >= 'A' && ch <= 'Z') {
1677 6 : if (ch == 'Z') {
1678 0 : s[pos] = 'A';
1679 0 : carry=1;
1680 : } else {
1681 6 : s[pos]++;
1682 6 : carry=0;
1683 : }
1684 6 : last=UPPER_CASE;
1685 8 : } else if (ch >= '0' && ch <= '9') {
1686 2 : if (ch == '9') {
1687 2 : s[pos] = '0';
1688 2 : carry=1;
1689 : } else {
1690 0 : s[pos]++;
1691 0 : carry=0;
1692 : }
1693 2 : last = NUMERIC;
1694 : } else {
1695 4 : carry=0;
1696 4 : break;
1697 : }
1698 40 : if (carry == 0) {
1699 36 : break;
1700 : }
1701 4 : pos--;
1702 : }
1703 :
1704 40 : if (carry) {
1705 0 : t = (char *) emalloc(Z_STRLEN_P(str)+1+1);
1706 0 : memcpy(t+1, Z_STRVAL_P(str), Z_STRLEN_P(str));
1707 0 : Z_STRLEN_P(str)++;
1708 0 : t[Z_STRLEN_P(str)] = '\0';
1709 0 : switch (last) {
1710 : case NUMERIC:
1711 0 : t[0] = '1';
1712 0 : break;
1713 : case UPPER_CASE:
1714 0 : t[0] = 'A';
1715 0 : break;
1716 : case LOWER_CASE:
1717 0 : t[0] = 'a';
1718 : break;
1719 : }
1720 0 : STR_FREE(Z_STRVAL_P(str));
1721 0 : Z_STRVAL_P(str) = t;
1722 : }
1723 : }
1724 : /* }}} */
1725 :
1726 : ZEND_API int increment_function(zval *op1) /* {{{ */
1727 3924474 : {
1728 3924474 : switch (Z_TYPE_P(op1)) {
1729 : case IS_LONG:
1730 3924280 : if (Z_LVAL_P(op1) == LONG_MAX) {
1731 : /* switch to double */
1732 2 : double d = (double)Z_LVAL_P(op1);
1733 2 : ZVAL_DOUBLE(op1, d+1);
1734 : } else {
1735 3924278 : Z_LVAL_P(op1)++;
1736 : }
1737 3924280 : break;
1738 : case IS_DOUBLE:
1739 1 : Z_DVAL_P(op1) = Z_DVAL_P(op1) + 1;
1740 1 : break;
1741 : case IS_NULL:
1742 23 : ZVAL_LONG(op1, 1);
1743 23 : break;
1744 : case IS_STRING: {
1745 : long lval;
1746 : double dval;
1747 :
1748 165 : switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
1749 : case IS_LONG:
1750 117 : efree(Z_STRVAL_P(op1));
1751 117 : if (lval == LONG_MAX) {
1752 : /* switch to double */
1753 1 : double d = (double)lval;
1754 1 : ZVAL_DOUBLE(op1, d+1);
1755 : } else {
1756 116 : ZVAL_LONG(op1, lval+1);
1757 : }
1758 117 : break;
1759 : case IS_DOUBLE:
1760 7 : efree(Z_STRVAL_P(op1));
1761 7 : ZVAL_DOUBLE(op1, dval+1);
1762 7 : break;
1763 : default:
1764 : /* Perl style string increment */
1765 41 : increment_string(op1);
1766 : break;
1767 : }
1768 : }
1769 165 : break;
1770 : default:
1771 5 : return FAILURE;
1772 : }
1773 3924469 : return SUCCESS;
1774 : }
1775 : /* }}} */
1776 :
1777 : ZEND_API int decrement_function(zval *op1) /* {{{ */
1778 387623 : {
1779 : long lval;
1780 : double dval;
1781 :
1782 387623 : switch (Z_TYPE_P(op1)) {
1783 : case IS_LONG:
1784 227608 : if (Z_LVAL_P(op1) == LONG_MIN) {
1785 1 : double d = (double)Z_LVAL_P(op1);
1786 1 : ZVAL_DOUBLE(op1, d-1);
1787 : } else {
1788 227607 : Z_LVAL_P(op1)--;
1789 : }
1790 227608 : break;
1791 : case IS_DOUBLE:
1792 159976 : Z_DVAL_P(op1) = Z_DVAL_P(op1) - 1;
1793 159976 : break;
1794 : case IS_STRING: /* Like perl we only support string increment */
1795 33 : if (Z_STRLEN_P(op1) == 0) { /* consider as 0 */
1796 1 : STR_FREE(Z_STRVAL_P(op1));
1797 1 : ZVAL_LONG(op1, -1);
1798 1 : break;
1799 : }
1800 32 : switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
1801 : case IS_LONG:
1802 8 : STR_FREE(Z_STRVAL_P(op1));
1803 8 : if (lval == LONG_MIN) {
1804 1 : double d = (double)lval;
1805 1 : ZVAL_DOUBLE(op1, d-1);
1806 : } else {
1807 7 : ZVAL_LONG(op1, lval-1);
1808 : }
1809 8 : break;
1810 : case IS_DOUBLE:
1811 7 : STR_FREE(Z_STRVAL_P(op1));
1812 7 : ZVAL_DOUBLE(op1, dval - 1);
1813 : break;
1814 : }
1815 32 : break;
1816 : default:
1817 6 : return FAILURE;
1818 : }
1819 :
1820 387617 : return SUCCESS;
1821 : }
1822 : /* }}} */
1823 :
1824 : ZEND_API int zval_is_true(zval *op) /* {{{ */
1825 3431 : {
1826 3431 : convert_to_boolean(op);
1827 3431 : return (Z_LVAL_P(op) ? 1 : 0);
1828 : }
1829 : /* }}} */
1830 :
1831 : #ifdef ZEND_USE_TOLOWER_L
1832 : ZEND_API void zend_update_current_locale(void) /* {{{ */
1833 : {
1834 : current_locale = _get_current_locale();
1835 : }
1836 : /* }}} */
1837 : #endif
1838 :
1839 : ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length) /* {{{ */
1840 69093034 : {
1841 69093034 : register unsigned char *str = (unsigned char*)source;
1842 69093034 : register unsigned char *result = (unsigned char*)dest;
1843 69093034 : register unsigned char *end = str + length;
1844 :
1845 1020466901 : while (str < end) {
1846 882280833 : *result++ = zend_tolower((int)*str++);
1847 : }
1848 69093034 : *result = '\0';
1849 :
1850 69093034 : return dest;
1851 : }
1852 : /* }}} */
1853 :
1854 : ZEND_API char *zend_str_tolower_dup(const char *source, unsigned int length) /* {{{ */
1855 64162110 : {
1856 64162110 : return zend_str_tolower_copy((char *)emalloc(length+1), source, length);
1857 : }
1858 : /* }}} */
1859 :
1860 : ZEND_API void zend_str_tolower(char *str, unsigned int length) /* {{{ */
1861 1613199 : {
1862 1613199 : register unsigned char *p = (unsigned char*)str;
1863 1613199 : register unsigned char *end = p + length;
1864 :
1865 20879865 : while (p < end) {
1866 17653467 : *p = zend_tolower((int)*p);
1867 17653467 : p++;
1868 : }
1869 1613199 : }
1870 : /* }}} */
1871 :
1872 : ZEND_API int zend_binary_strcmp(const char *s1, uint len1, const char *s2, uint len2) /* {{{ */
1873 1764964 : {
1874 : int retval;
1875 :
1876 1764964 : retval = memcmp(s1, s2, MIN(len1, len2));
1877 1764964 : if (!retval) {
1878 225877 : return (len1 - len2);
1879 : } else {
1880 1539087 : return retval;
1881 : }
1882 : }
1883 : /* }}} */
1884 :
1885 : ZEND_API int zend_binary_strncmp(const char *s1, uint len1, const char *s2, uint len2, uint length) /* {{{ */
1886 12142 : {
1887 : int retval;
1888 :
1889 12142 : retval = memcmp(s1, s2, MIN(length, MIN(len1, len2)));
1890 12142 : if (!retval) {
1891 11909 : return (MIN(length, len1) - MIN(length, len2));
1892 : } else {
1893 233 : return retval;
1894 : }
1895 : }
1896 : /* }}} */
1897 :
1898 : ZEND_API int zend_binary_strcasecmp(const char *s1, uint len1, const char *s2, uint len2) /* {{{ */
1899 113032 : {
1900 : int len;
1901 : int c1, c2;
1902 :
1903 113032 : len = MIN(len1, len2);
1904 :
1905 457758 : while (len--) {
1906 344173 : c1 = zend_tolower((int)*(unsigned char *)s1++);
1907 344173 : c2 = zend_tolower((int)*(unsigned char *)s2++);
1908 344173 : if (c1 != c2) {
1909 112479 : return c1 - c2;
1910 : }
1911 : }
1912 :
1913 553 : return len1 - len2;
1914 : }
1915 : /* }}} */
1916 :
1917 : ZEND_API int zend_binary_strncasecmp(const char *s1, uint len1, const char *s2, uint len2, uint length) /* {{{ */
1918 17505 : {
1919 : int len;
1920 : int c1, c2;
1921 :
1922 17505 : len = MIN(length, MIN(len1, len2));
1923 :
1924 41724 : while (len--) {
1925 7081 : c1 = zend_tolower((int)*(unsigned char *)s1++);
1926 7081 : c2 = zend_tolower((int)*(unsigned char *)s2++);
1927 7081 : if (c1 != c2) {
1928 367 : return c1 - c2;
1929 : }
1930 : }
1931 :
1932 17138 : return MIN(length, len1) - MIN(length, len2);
1933 : }
1934 : /* }}} */
1935 :
1936 : ZEND_API int zend_binary_zval_strcmp(zval *s1, zval *s2) /* {{{ */
1937 1484155 : {
1938 1484155 : return zend_binary_strcmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2));
1939 : }
1940 : /* }}} */
1941 :
1942 : ZEND_API int zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3) /* {{{ */
1943 0 : {
1944 0 : return zend_binary_strncmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2), Z_LVAL_P(s3));
1945 : }
1946 : /* }}} */
1947 :
1948 : ZEND_API int zend_binary_zval_strcasecmp(zval *s1, zval *s2) /* {{{ */
1949 0 : {
1950 0 : return zend_binary_strcasecmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2));
1951 : }
1952 : /* }}} */
1953 :
1954 : ZEND_API int zend_binary_zval_strncasecmp(zval *s1, zval *s2, zval *s3) /* {{{ */
1955 0 : {
1956 0 : return zend_binary_strncasecmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2), Z_LVAL_P(s3));
1957 : }
1958 : /* }}} */
1959 :
1960 : ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2) /* {{{ */
1961 975626 : {
1962 : int ret1, ret2;
1963 : long lval1, lval2;
1964 : double dval1, dval2;
1965 :
1966 1281668 : if ((ret1=is_numeric_string(Z_STRVAL_P(s1), Z_STRLEN_P(s1), &lval1, &dval1, 0)) &&
1967 : (ret2=is_numeric_string(Z_STRVAL_P(s2), Z_STRLEN_P(s2), &lval2, &dval2, 0))) {
1968 407066 : if ((ret1==IS_DOUBLE) || (ret2==IS_DOUBLE)) {
1969 101024 : if (ret1!=IS_DOUBLE) {
1970 24 : dval1 = (double) lval1;
1971 101000 : } else if (ret2!=IS_DOUBLE) {
1972 20 : dval2 = (double) lval2;
1973 100980 : } else if (dval1 == dval2 && !zend_finite(dval1)) {
1974 : /* Both values overflowed and have the same sign,
1975 : * so a numeric comparison would be inaccurate */
1976 0 : goto string_cmp;
1977 : }
1978 101024 : Z_DVAL_P(result) = dval1 - dval2;
1979 101024 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1980 : } else { /* they both have to be long's */
1981 205018 : ZVAL_LONG(result, lval1 > lval2 ? 1 : (lval1 < lval2 ? -1 : 0));
1982 : }
1983 : } else {
1984 669584 : string_cmp:
1985 669584 : Z_LVAL_P(result) = zend_binary_zval_strcmp(s1, s2);
1986 669584 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(result)));
1987 : }
1988 975626 : }
1989 : /* }}} */
1990 :
1991 : static int hash_zval_compare_function(const zval **z1, const zval **z2 TSRMLS_DC) /* {{{ */
1992 2584 : {
1993 : zval result;
1994 :
1995 2584 : if (compare_function(&result, (zval *) *z1, (zval *) *z2 TSRMLS_CC)==FAILURE) {
1996 0 : return 1;
1997 : }
1998 2584 : return Z_LVAL(result);
1999 : }
2000 : /* }}} */
2001 :
2002 : ZEND_API int zend_compare_symbol_tables_i(HashTable *ht1, HashTable *ht2 TSRMLS_DC) /* {{{ */
2003 495 : {
2004 495 : return zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC);
2005 : }
2006 : /* }}} */
2007 :
2008 : ZEND_API void zend_compare_symbol_tables(zval *result, HashTable *ht1, HashTable *ht2 TSRMLS_DC) /* {{{ */
2009 705 : {
2010 705 : ZVAL_LONG(result, zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC));
2011 705 : }
2012 : /* }}} */
2013 :
2014 : ZEND_API void zend_compare_arrays(zval *result, zval *a1, zval *a2 TSRMLS_DC) /* {{{ */
2015 705 : {
2016 705 : zend_compare_symbol_tables(result, Z_ARRVAL_P(a1), Z_ARRVAL_P(a2) TSRMLS_CC);
2017 705 : }
2018 : /* }}} */
2019 :
2020 : ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC) /* {{{ */
2021 0 : {
2022 0 : Z_TYPE_P(result) = IS_LONG;
2023 :
2024 0 : if (Z_OBJ_HANDLE_P(o1) == Z_OBJ_HANDLE_P(o2)) {
2025 0 : Z_LVAL_P(result) = 0;
2026 0 : return;
2027 : }
2028 :
2029 0 : if (Z_OBJ_HT_P(o1)->compare_objects == NULL) {
2030 0 : Z_LVAL_P(result) = 1;
2031 : } else {
2032 0 : Z_LVAL_P(result) = Z_OBJ_HT_P(o1)->compare_objects(o1, o2 TSRMLS_CC);
2033 : }
2034 : }
2035 : /* }}} */
2036 :
2037 : ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC) /* {{{ */
2038 19026 : {
2039 : TSRMLS_FETCH();
2040 :
2041 19026 : Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "%.*G", (int) EG(precision), (double)Z_DVAL_P(op));
2042 19026 : }
2043 : /* }}} */
2044 :
2045 : /*
2046 : * Local variables:
2047 : * tab-width: 4
2048 : * c-basic-offset: 4
2049 : * indent-tabs-mode: t
2050 : * End:
2051 : */
|