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