This source file includes following definitions.
- zend_atoi
- zend_atol
- zend_string_to_double
- convert_scalar_to_number
- convert_to_long
- convert_to_long_base
- convert_to_double
- convert_to_null
- convert_to_boolean
- _convert_to_cstring
- _convert_to_string
- convert_scalar_to_array
- convert_to_array
- convert_to_object
- multi_convert_to_long_ex
- multi_convert_to_double_ex
- multi_convert_to_string_ex
- add_function
- sub_function
- mul_function
- pow_function
- div_function
- mod_function
- boolean_xor_function
- boolean_not_function
- bitwise_not_function
- bitwise_or_function
- bitwise_and_function
- bitwise_xor_function
- shift_left_function
- shift_right_function
- add_char_to_string
- add_string_to_string
- concat_function
- string_compare_function_ex
- string_compare_function
- string_case_compare_function
- string_locale_compare_function
- numeric_compare_function
- zend_free_obj_get_result
- compare_function
- hash_zval_identical_function
- is_identical_function
- is_not_identical_function
- is_equal_function
- is_not_equal_function
- is_smaller_function
- is_smaller_or_equal_function
- instanceof_function_ex
- instanceof_function
- increment_string
- increment_function
- decrement_function
- zval_is_true
- zend_update_current_locale
- zend_str_tolower_copy
- zend_str_tolower_dup
- zend_str_tolower
- zend_binary_strcmp
- zend_binary_strncmp
- zend_binary_strcasecmp
- zend_binary_strncasecmp
- zend_binary_strcasecmp_l
- zend_binary_strncasecmp_l
- zend_binary_zval_strcmp
- zend_binary_zval_strncmp
- zend_binary_zval_strcasecmp
- zend_binary_zval_strncasecmp
- zendi_smart_strcmp
- hash_zval_compare_function
- zend_compare_symbol_tables_i
- zend_compare_symbol_tables
- zend_compare_arrays
- zend_compare_objects
- zend_locale_sprintf_double
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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_strtod.h"
31 #include "zend_exceptions.h"
32 #include "zend_closures.h"
33
34 #if ZEND_USE_TOLOWER_L
35 #include <locale.h>
36 static _locale_t current_locale = NULL;
37
38 #define zend_tolower(c) _tolower_l(c, current_locale)
39 #else
40 #define zend_tolower(c) tolower(c)
41 #endif
42
43 #define TYPE_PAIR(t1,t2) (((t1) << 4) | (t2))
44
45 static const unsigned char tolower_map[256] = {
46 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
47 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
48 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
49 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
50 0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
51 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x5b,0x5c,0x5d,0x5e,0x5f,
52 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
53 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
54 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
55 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
56 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
57 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
58 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
59 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
60 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
61 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
62 };
63
64 #define zend_tolower_ascii(c) (tolower_map[(unsigned char)(c)])
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82 ZEND_API int zend_atoi(const char *str, int str_len)
83 {
84 int retval;
85
86 if (!str_len) {
87 str_len = strlen(str);
88 }
89 retval = strtol(str, NULL, 0);
90 if (str_len>0) {
91 switch (str[str_len-1]) {
92 case 'g':
93 case 'G':
94 retval *= 1024;
95
96 case 'm':
97 case 'M':
98 retval *= 1024;
99
100 case 'k':
101 case 'K':
102 retval *= 1024;
103 break;
104 }
105 }
106 return retval;
107 }
108
109
110 ZEND_API long zend_atol(const char *str, int str_len)
111 {
112 long retval;
113
114 if (!str_len) {
115 str_len = strlen(str);
116 }
117 retval = strtol(str, NULL, 0);
118 if (str_len>0) {
119 switch (str[str_len-1]) {
120 case 'g':
121 case 'G':
122 retval *= 1024;
123
124 case 'm':
125 case 'M':
126 retval *= 1024;
127
128 case 'k':
129 case 'K':
130 retval *= 1024;
131 break;
132 }
133 }
134 return retval;
135 }
136
137
138 ZEND_API double zend_string_to_double(const char *number, zend_uint length)
139 {
140 double divisor = 10.0;
141 double result = 0.0;
142 double exponent;
143 const char *end = number+length;
144 const char *digit = number;
145
146 if (!length) {
147 return result;
148 }
149
150 while (digit < end) {
151 if ((*digit <= '9' && *digit >= '0')) {
152 result *= 10;
153 result += *digit - '0';
154 } else if (*digit == '.') {
155 digit++;
156 break;
157 } else if (toupper(*digit) == 'E') {
158 exponent = (double) atoi(digit+1);
159 result *= pow(10.0, exponent);
160 return result;
161 } else {
162 return result;
163 }
164 digit++;
165 }
166
167 while (digit < end) {
168 if ((*digit <= '9' && *digit >= '0')) {
169 result += (*digit - '0') / divisor;
170 divisor *= 10;
171 } else if (toupper(*digit) == 'E') {
172 exponent = (double) atoi(digit+1);
173 result *= pow(10.0, exponent);
174 return result;
175 } else {
176 return result;
177 }
178 digit++;
179 }
180 return result;
181 }
182
183
184 ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC)
185 {
186 switch (Z_TYPE_P(op)) {
187 case IS_STRING:
188 {
189 char *strval;
190
191 strval = Z_STRVAL_P(op);
192 if ((Z_TYPE_P(op)=is_numeric_string(strval, Z_STRLEN_P(op), &Z_LVAL_P(op), &Z_DVAL_P(op), 1)) == 0) {
193 ZVAL_LONG(op, 0);
194 }
195 str_efree(strval);
196 break;
197 }
198 case IS_BOOL:
199 Z_TYPE_P(op) = IS_LONG;
200 break;
201 case IS_RESOURCE:
202 zend_list_delete(Z_LVAL_P(op));
203 Z_TYPE_P(op) = IS_LONG;
204 break;
205 case IS_OBJECT:
206 convert_to_long_base(op, 10);
207 break;
208 case IS_NULL:
209 ZVAL_LONG(op, 0);
210 break;
211 }
212 }
213
214
215
216 #define zendi_convert_scalar_to_number(op, holder, result) \
217 if (op==result) { \
218 if (Z_TYPE_P(op) != IS_LONG) { \
219 convert_scalar_to_number(op TSRMLS_CC); \
220 } \
221 } else { \
222 switch (Z_TYPE_P(op)) { \
223 case IS_STRING: \
224 { \
225 if ((Z_TYPE(holder)=is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &Z_LVAL(holder), &Z_DVAL(holder), 1)) == 0) { \
226 ZVAL_LONG(&(holder), 0); \
227 } \
228 (op) = &(holder); \
229 break; \
230 } \
231 case IS_BOOL: \
232 case IS_RESOURCE: \
233 ZVAL_LONG(&(holder), Z_LVAL_P(op)); \
234 (op) = &(holder); \
235 break; \
236 case IS_NULL: \
237 ZVAL_LONG(&(holder), 0); \
238 (op) = &(holder); \
239 break; \
240 case IS_OBJECT: \
241 (holder) = (*(op)); \
242 zval_copy_ctor(&(holder)); \
243 convert_to_long_base(&(holder), 10); \
244 if (Z_TYPE(holder) == IS_LONG) { \
245 (op) = &(holder); \
246 } \
247 break; \
248 } \
249 }
250
251
252
253
254 #define zendi_convert_to_long(op, holder, result) \
255 if (op == result) { \
256 convert_to_long(op); \
257 } else if (Z_TYPE_P(op) != IS_LONG) { \
258 switch (Z_TYPE_P(op)) { \
259 case IS_NULL: \
260 Z_LVAL(holder) = 0; \
261 break; \
262 case IS_DOUBLE: \
263 Z_LVAL(holder) = zend_dval_to_lval(Z_DVAL_P(op)); \
264 break; \
265 case IS_STRING: \
266 Z_LVAL(holder) = strtol(Z_STRVAL_P(op), NULL, 10); \
267 break; \
268 case IS_ARRAY: \
269 Z_LVAL(holder) = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); \
270 break; \
271 case IS_OBJECT: \
272 (holder) = (*(op)); \
273 zval_copy_ctor(&(holder)); \
274 convert_to_long_base(&(holder), 10); \
275 break; \
276 case IS_BOOL: \
277 case IS_RESOURCE: \
278 Z_LVAL(holder) = Z_LVAL_P(op); \
279 break; \
280 default: \
281 zend_error(E_WARNING, "Cannot convert to ordinal value"); \
282 Z_LVAL(holder) = 0; \
283 break; \
284 } \
285 Z_TYPE(holder) = IS_LONG; \
286 (op) = &(holder); \
287 }
288
289
290
291
292 #define zendi_convert_to_boolean(op, holder, result) \
293 if (op==result) { \
294 convert_to_boolean(op); \
295 } else if (Z_TYPE_P(op) != IS_BOOL) { \
296 switch (Z_TYPE_P(op)) { \
297 case IS_NULL: \
298 Z_LVAL(holder) = 0; \
299 break; \
300 case IS_RESOURCE: \
301 case IS_LONG: \
302 Z_LVAL(holder) = (Z_LVAL_P(op) ? 1 : 0); \
303 break; \
304 case IS_DOUBLE: \
305 Z_LVAL(holder) = (Z_DVAL_P(op) ? 1 : 0); \
306 break; \
307 case IS_STRING: \
308 if (Z_STRLEN_P(op) == 0 \
309 || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) { \
310 Z_LVAL(holder) = 0; \
311 } else { \
312 Z_LVAL(holder) = 1; \
313 } \
314 break; \
315 case IS_ARRAY: \
316 Z_LVAL(holder) = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); \
317 break; \
318 case IS_OBJECT: \
319 (holder) = (*(op)); \
320 zval_copy_ctor(&(holder)); \
321 convert_to_boolean(&(holder)); \
322 break; \
323 default: \
324 Z_LVAL(holder) = 0; \
325 break; \
326 } \
327 Z_TYPE(holder) = IS_BOOL; \
328 (op) = &(holder); \
329 }
330
331
332
333
334 #define convert_object_to_type(op, ctype, conv_func) \
335 if (Z_OBJ_HT_P(op)->cast_object) { \
336 zval dst; \
337 if (Z_OBJ_HT_P(op)->cast_object(op, &dst, ctype TSRMLS_CC) == FAILURE) { \
338 zend_error(E_RECOVERABLE_ERROR, \
339 "Object of class %s could not be converted to %s", Z_OBJCE_P(op)->name, \
340 zend_get_type_by_const(ctype)); \
341 } else { \
342 zval_dtor(op); \
343 Z_TYPE_P(op) = ctype; \
344 op->value = dst.value; \
345 } \
346 } else { \
347 if (Z_OBJ_HT_P(op)->get) { \
348 zval *newop = Z_OBJ_HT_P(op)->get(op TSRMLS_CC); \
349 if (Z_TYPE_P(newop) != IS_OBJECT) { \
350 \
351 zval_dtor(op); \
352 *op = *newop; \
353 FREE_ZVAL(newop); \
354 conv_func(op); \
355 } \
356 } \
357 }
358
359
360
361 ZEND_API void convert_to_long(zval *op)
362 {
363 if (Z_TYPE_P(op) != IS_LONG) {
364 convert_to_long_base(op, 10);
365 }
366 }
367
368
369 ZEND_API void convert_to_long_base(zval *op, int base)
370 {
371 long tmp;
372
373 switch (Z_TYPE_P(op)) {
374 case IS_NULL:
375 Z_LVAL_P(op) = 0;
376 break;
377 case IS_RESOURCE: {
378 TSRMLS_FETCH();
379
380 zend_list_delete(Z_LVAL_P(op));
381 }
382
383 case IS_BOOL:
384 case IS_LONG:
385 break;
386 case IS_DOUBLE:
387 Z_LVAL_P(op) = zend_dval_to_lval(Z_DVAL_P(op));
388 break;
389 case IS_STRING:
390 {
391 char *strval = Z_STRVAL_P(op);
392
393 Z_LVAL_P(op) = strtol(strval, NULL, base);
394 str_efree(strval);
395 }
396 break;
397 case IS_ARRAY:
398 tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
399 zval_dtor(op);
400 Z_LVAL_P(op) = tmp;
401 break;
402 case IS_OBJECT:
403 {
404 int retval = 1;
405 TSRMLS_FETCH();
406
407 convert_object_to_type(op, IS_LONG, convert_to_long);
408
409 if (Z_TYPE_P(op) == IS_LONG) {
410 return;
411 }
412 zend_error(E_NOTICE, "Object of class %s could not be converted to int", Z_OBJCE_P(op)->name);
413
414 zval_dtor(op);
415 ZVAL_LONG(op, retval);
416 return;
417 }
418 default:
419 zend_error(E_WARNING, "Cannot convert to ordinal value");
420 zval_dtor(op);
421 Z_LVAL_P(op) = 0;
422 break;
423 }
424
425 Z_TYPE_P(op) = IS_LONG;
426 }
427
428
429 ZEND_API void convert_to_double(zval *op)
430 {
431 double tmp;
432
433 switch (Z_TYPE_P(op)) {
434 case IS_NULL:
435 Z_DVAL_P(op) = 0.0;
436 break;
437 case IS_RESOURCE: {
438 TSRMLS_FETCH();
439
440 zend_list_delete(Z_LVAL_P(op));
441 }
442
443 case IS_BOOL:
444 case IS_LONG:
445 Z_DVAL_P(op) = (double) Z_LVAL_P(op);
446 break;
447 case IS_DOUBLE:
448 break;
449 case IS_STRING:
450 {
451 char *strval = Z_STRVAL_P(op);
452
453 Z_DVAL_P(op) = zend_strtod(strval, NULL);
454 str_efree(strval);
455 }
456 break;
457 case IS_ARRAY:
458 tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
459 zval_dtor(op);
460 Z_DVAL_P(op) = tmp;
461 break;
462 case IS_OBJECT:
463 {
464 double retval = 1.0;
465 TSRMLS_FETCH();
466
467 convert_object_to_type(op, IS_DOUBLE, convert_to_double);
468
469 if (Z_TYPE_P(op) == IS_DOUBLE) {
470 return;
471 }
472 zend_error(E_NOTICE, "Object of class %s could not be converted to double", Z_OBJCE_P(op)->name);
473
474 zval_dtor(op);
475 ZVAL_DOUBLE(op, retval);
476 break;
477 }
478 default:
479 zend_error(E_WARNING, "Cannot convert to real value (type=%d)", Z_TYPE_P(op));
480 zval_dtor(op);
481 Z_DVAL_P(op) = 0;
482 break;
483 }
484 Z_TYPE_P(op) = IS_DOUBLE;
485 }
486
487
488 ZEND_API void convert_to_null(zval *op)
489 {
490 if (Z_TYPE_P(op) == IS_OBJECT) {
491 if (Z_OBJ_HT_P(op)->cast_object) {
492 zval *org;
493 TSRMLS_FETCH();
494
495 ALLOC_ZVAL(org);
496 *org = *op;
497 if (Z_OBJ_HT_P(op)->cast_object(org, op, IS_NULL TSRMLS_CC) == SUCCESS) {
498 zval_dtor(org);
499 return;
500 }
501 *op = *org;
502 FREE_ZVAL(org);
503 }
504 }
505
506 zval_dtor(op);
507 Z_TYPE_P(op) = IS_NULL;
508 }
509
510
511 ZEND_API void convert_to_boolean(zval *op)
512 {
513 int tmp;
514
515 switch (Z_TYPE_P(op)) {
516 case IS_BOOL:
517 break;
518 case IS_NULL:
519 Z_LVAL_P(op) = 0;
520 break;
521 case IS_RESOURCE: {
522 TSRMLS_FETCH();
523
524 zend_list_delete(Z_LVAL_P(op));
525 }
526
527 case IS_LONG:
528 Z_LVAL_P(op) = (Z_LVAL_P(op) ? 1 : 0);
529 break;
530 case IS_DOUBLE:
531 Z_LVAL_P(op) = (Z_DVAL_P(op) ? 1 : 0);
532 break;
533 case IS_STRING:
534 {
535 char *strval = Z_STRVAL_P(op);
536
537 if (Z_STRLEN_P(op) == 0
538 || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) {
539 Z_LVAL_P(op) = 0;
540 } else {
541 Z_LVAL_P(op) = 1;
542 }
543 str_efree(strval);
544 }
545 break;
546 case IS_ARRAY:
547 tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
548 zval_dtor(op);
549 Z_LVAL_P(op) = tmp;
550 break;
551 case IS_OBJECT:
552 {
553 zend_bool retval = 1;
554 TSRMLS_FETCH();
555
556 convert_object_to_type(op, IS_BOOL, convert_to_boolean);
557
558 if (Z_TYPE_P(op) == IS_BOOL) {
559 return;
560 }
561
562 zval_dtor(op);
563 ZVAL_BOOL(op, retval);
564 break;
565 }
566 default:
567 zval_dtor(op);
568 Z_LVAL_P(op) = 0;
569 break;
570 }
571 Z_TYPE_P(op) = IS_BOOL;
572 }
573
574
575 ZEND_API void _convert_to_cstring(zval *op ZEND_FILE_LINE_DC)
576 {
577 double dval;
578 switch (Z_TYPE_P(op)) {
579 case IS_DOUBLE: {
580 TSRMLS_FETCH();
581 dval = Z_DVAL_P(op);
582 Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "%.*H", (int) EG(precision), dval);
583
584 break;
585 }
586 default:
587 _convert_to_string(op ZEND_FILE_LINE_CC);
588 }
589 Z_TYPE_P(op) = IS_STRING;
590 }
591
592
593 ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC)
594 {
595 long lval;
596 double dval;
597
598 switch (Z_TYPE_P(op)) {
599 case IS_NULL:
600 Z_STRVAL_P(op) = STR_EMPTY_ALLOC();
601 Z_STRLEN_P(op) = 0;
602 break;
603 case IS_STRING:
604 break;
605 case IS_BOOL:
606 if (Z_LVAL_P(op)) {
607 Z_STRVAL_P(op) = estrndup_rel("1", 1);
608 Z_STRLEN_P(op) = 1;
609 } else {
610 Z_STRVAL_P(op) = STR_EMPTY_ALLOC();
611 Z_STRLEN_P(op) = 0;
612 }
613 break;
614 case IS_RESOURCE: {
615 long tmp = Z_LVAL_P(op);
616 TSRMLS_FETCH();
617
618 zend_list_delete(Z_LVAL_P(op));
619 Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "Resource id #%ld", tmp);
620 break;
621 }
622 case IS_LONG:
623 lval = Z_LVAL_P(op);
624
625 Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "%ld", lval);
626 break;
627 case IS_DOUBLE: {
628 TSRMLS_FETCH();
629 dval = Z_DVAL_P(op);
630 Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "%.*G", (int) EG(precision), dval);
631
632 break;
633 }
634 case IS_ARRAY:
635 zend_error(E_NOTICE, "Array to string conversion");
636 zval_dtor(op);
637 Z_STRVAL_P(op) = estrndup_rel("Array", sizeof("Array")-1);
638 Z_STRLEN_P(op) = sizeof("Array")-1;
639 break;
640 case IS_OBJECT: {
641 TSRMLS_FETCH();
642
643 convert_object_to_type(op, IS_STRING, convert_to_string);
644
645 if (Z_TYPE_P(op) == IS_STRING) {
646 return;
647 }
648
649 zend_error(E_NOTICE, "Object of class %s to string conversion", Z_OBJCE_P(op)->name);
650 zval_dtor(op);
651 Z_STRVAL_P(op) = estrndup_rel("Object", sizeof("Object")-1);
652 Z_STRLEN_P(op) = sizeof("Object")-1;
653 break;
654 }
655 default:
656 zval_dtor(op);
657 ZVAL_BOOL(op, 0);
658 break;
659 }
660 Z_TYPE_P(op) = IS_STRING;
661 }
662
663
664 static void convert_scalar_to_array(zval *op, int type TSRMLS_DC)
665 {
666 zval *entry;
667
668 ALLOC_ZVAL(entry);
669 *entry = *op;
670 INIT_PZVAL(entry);
671
672 switch (type) {
673 case IS_ARRAY:
674 ALLOC_HASHTABLE(Z_ARRVAL_P(op));
675 zend_hash_init(Z_ARRVAL_P(op), 0, NULL, ZVAL_PTR_DTOR, 0);
676 zend_hash_index_update(Z_ARRVAL_P(op), 0, (void *) &entry, sizeof(zval *), NULL);
677 Z_TYPE_P(op) = IS_ARRAY;
678 break;
679 case IS_OBJECT:
680 object_init(op);
681 zend_hash_update(Z_OBJPROP_P(op), "scalar", sizeof("scalar"), (void *) &entry, sizeof(zval *), NULL);
682 break;
683 }
684 }
685
686
687 ZEND_API void convert_to_array(zval *op)
688 {
689 TSRMLS_FETCH();
690
691 switch (Z_TYPE_P(op)) {
692 case IS_ARRAY:
693 break;
694
695 case IS_OBJECT:
696 {
697 zval *tmp;
698 HashTable *ht;
699
700 ALLOC_HASHTABLE(ht);
701 zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
702 if (Z_OBJCE_P(op) == zend_ce_closure) {
703 convert_scalar_to_array(op, IS_ARRAY TSRMLS_CC);
704 if (Z_TYPE_P(op) == IS_ARRAY) {
705 zend_hash_destroy(ht);
706 FREE_HASHTABLE(ht);
707 return;
708 }
709 } else if (Z_OBJ_HT_P(op)->get_properties) {
710 HashTable *obj_ht = Z_OBJ_HT_P(op)->get_properties(op TSRMLS_CC);
711 if (obj_ht) {
712 zend_hash_copy(ht, obj_ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
713 }
714 } else {
715 convert_object_to_type(op, IS_ARRAY, convert_to_array);
716
717 if (Z_TYPE_P(op) == IS_ARRAY) {
718 zend_hash_destroy(ht);
719 FREE_HASHTABLE(ht);
720 return;
721 }
722 }
723 zval_dtor(op);
724 Z_TYPE_P(op) = IS_ARRAY;
725 Z_ARRVAL_P(op) = ht;
726 }
727 break;
728 case IS_NULL:
729 ALLOC_HASHTABLE(Z_ARRVAL_P(op));
730 zend_hash_init(Z_ARRVAL_P(op), 0, NULL, ZVAL_PTR_DTOR, 0);
731 Z_TYPE_P(op) = IS_ARRAY;
732 break;
733 default:
734 convert_scalar_to_array(op, IS_ARRAY TSRMLS_CC);
735 break;
736 }
737 }
738
739
740 ZEND_API void convert_to_object(zval *op)
741 {
742 TSRMLS_FETCH();
743
744 switch (Z_TYPE_P(op)) {
745 case IS_ARRAY:
746 {
747 object_and_properties_init(op, zend_standard_class_def, Z_ARRVAL_P(op));
748 break;
749 }
750 case IS_OBJECT:
751 break;
752 case IS_NULL:
753 object_init(op);
754 break;
755 default:
756 convert_scalar_to_array(op, IS_OBJECT TSRMLS_CC);
757 break;
758 }
759 }
760
761
762 ZEND_API void multi_convert_to_long_ex(int argc, ...)
763 {
764 zval **arg;
765 va_list ap;
766
767 va_start(ap, argc);
768
769 while (argc--) {
770 arg = va_arg(ap, zval **);
771 convert_to_long_ex(arg);
772 }
773
774 va_end(ap);
775 }
776
777
778 ZEND_API void multi_convert_to_double_ex(int argc, ...)
779 {
780 zval **arg;
781 va_list ap;
782
783 va_start(ap, argc);
784
785 while (argc--) {
786 arg = va_arg(ap, zval **);
787 convert_to_double_ex(arg);
788 }
789
790 va_end(ap);
791 }
792
793
794 ZEND_API void multi_convert_to_string_ex(int argc, ...)
795 {
796 zval **arg;
797 va_list ap;
798
799 va_start(ap, argc);
800
801 while (argc--) {
802 arg = va_arg(ap, zval **);
803 convert_to_string_ex(arg);
804 }
805
806 va_end(ap);
807 }
808
809
810 ZEND_API int add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
811 {
812 zval op1_copy, op2_copy;
813 int converted = 0;
814
815 while (1) {
816 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
817 case TYPE_PAIR(IS_LONG, IS_LONG): {
818 long lval = Z_LVAL_P(op1) + Z_LVAL_P(op2);
819
820
821 if ((Z_LVAL_P(op1) & LONG_SIGN_MASK) == (Z_LVAL_P(op2) & LONG_SIGN_MASK)
822 && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {
823
824 ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2));
825 } else {
826 ZVAL_LONG(result, lval);
827 }
828 return SUCCESS;
829 }
830
831 case TYPE_PAIR(IS_LONG, IS_DOUBLE):
832 ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2));
833 return SUCCESS;
834
835 case TYPE_PAIR(IS_DOUBLE, IS_LONG):
836 ZVAL_DOUBLE(result, Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2)));
837 return SUCCESS;
838
839 case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
840 ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2));
841 return SUCCESS;
842
843 case TYPE_PAIR(IS_ARRAY, IS_ARRAY): {
844 zval *tmp;
845
846 if ((result == op1) && (result == op2)) {
847
848 return SUCCESS;
849 }
850 if (result != op1) {
851 *result = *op1;
852 zval_copy_ctor(result);
853 }
854 zend_hash_merge(Z_ARRVAL_P(result), Z_ARRVAL_P(op2), (void (*)(void *pData)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0);
855 return SUCCESS;
856 }
857
858 default:
859 if (!converted) {
860 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_ADD);
861
862 zendi_convert_scalar_to_number(op1, op1_copy, result);
863 zendi_convert_scalar_to_number(op2, op2_copy, result);
864 converted = 1;
865 } else {
866 zend_error(E_ERROR, "Unsupported operand types");
867 return FAILURE;
868 }
869 }
870 }
871 }
872
873
874 ZEND_API int sub_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
875 {
876 zval op1_copy, op2_copy;
877 int converted = 0;
878
879 while (1) {
880 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
881 case TYPE_PAIR(IS_LONG, IS_LONG): {
882 long lval = Z_LVAL_P(op1) - Z_LVAL_P(op2);
883
884
885 if ((Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(op2) & LONG_SIGN_MASK)
886 && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {
887
888 ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2));
889 } else {
890 ZVAL_LONG(result, lval);
891 }
892 return SUCCESS;
893
894 }
895 case TYPE_PAIR(IS_LONG, IS_DOUBLE):
896 ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2));
897 return SUCCESS;
898
899 case TYPE_PAIR(IS_DOUBLE, IS_LONG):
900 ZVAL_DOUBLE(result, Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2)));
901 return SUCCESS;
902
903 case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
904 ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2));
905 return SUCCESS;
906
907 default:
908 if (!converted) {
909 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SUB);
910
911 zendi_convert_scalar_to_number(op1, op1_copy, result);
912 zendi_convert_scalar_to_number(op2, op2_copy, result);
913 converted = 1;
914 } else {
915 zend_error(E_ERROR, "Unsupported operand types");
916 return FAILURE;
917 }
918 }
919 }
920 }
921
922
923 ZEND_API int mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
924 {
925 zval op1_copy, op2_copy;
926 int converted = 0;
927
928 while (1) {
929 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
930 case TYPE_PAIR(IS_LONG, IS_LONG): {
931 long overflow;
932
933 ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1),Z_LVAL_P(op2), Z_LVAL_P(result),Z_DVAL_P(result),overflow);
934 Z_TYPE_P(result) = overflow ? IS_DOUBLE : IS_LONG;
935 return SUCCESS;
936
937 }
938 case TYPE_PAIR(IS_LONG, IS_DOUBLE):
939 ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) * Z_DVAL_P(op2));
940 return SUCCESS;
941
942 case TYPE_PAIR(IS_DOUBLE, IS_LONG):
943 ZVAL_DOUBLE(result, Z_DVAL_P(op1) * ((double)Z_LVAL_P(op2)));
944 return SUCCESS;
945
946 case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
947 ZVAL_DOUBLE(result, Z_DVAL_P(op1) * Z_DVAL_P(op2));
948 return SUCCESS;
949
950 default:
951 if (!converted) {
952 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_MUL);
953
954 zendi_convert_scalar_to_number(op1, op1_copy, result);
955 zendi_convert_scalar_to_number(op2, op2_copy, result);
956 converted = 1;
957 } else {
958 zend_error(E_ERROR, "Unsupported operand types");
959 return FAILURE;
960 }
961 }
962 }
963 }
964
965
966 ZEND_API int pow_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
967 {
968 zval op1_copy, op2_copy;
969 int converted = 0;
970
971 while (1) {
972 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
973 case TYPE_PAIR(IS_LONG, IS_LONG):
974 if (Z_LVAL_P(op2) >= 0) {
975 long l1 = 1, l2 = Z_LVAL_P(op1), i = Z_LVAL_P(op2);
976
977 if (i == 0) {
978 ZVAL_LONG(result, 1L);
979 return SUCCESS;
980 } else if (l2 == 0) {
981 ZVAL_LONG(result, 0);
982 return SUCCESS;
983 }
984
985 while (i >= 1) {
986 long overflow;
987 double dval = 0.0;
988
989 if (i % 2) {
990 --i;
991 ZEND_SIGNED_MULTIPLY_LONG(l1, l2, l1, dval, overflow);
992 if (overflow) {
993 ZVAL_DOUBLE(result, dval * pow(l2, i));
994 return SUCCESS;
995 }
996 } else {
997 i /= 2;
998 ZEND_SIGNED_MULTIPLY_LONG(l2, l2, l2, dval, overflow);
999 if (overflow) {
1000 ZVAL_DOUBLE(result, (double)l1 * pow(dval, i));
1001 return SUCCESS;
1002 }
1003 }
1004 }
1005
1006 ZVAL_LONG(result, l1);
1007 } else {
1008 ZVAL_DOUBLE(result, pow((double)Z_LVAL_P(op1), (double)Z_LVAL_P(op2)));
1009 }
1010 return SUCCESS;
1011
1012 case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1013 ZVAL_DOUBLE(result, pow((double)Z_LVAL_P(op1), Z_DVAL_P(op2)));
1014 return SUCCESS;
1015
1016 case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1017 ZVAL_DOUBLE(result, pow(Z_DVAL_P(op1), (double)Z_LVAL_P(op2)));
1018 return SUCCESS;
1019
1020 case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1021 ZVAL_DOUBLE(result, pow(Z_DVAL_P(op1), Z_DVAL_P(op2)));
1022 return SUCCESS;
1023
1024 default:
1025 if (!converted) {
1026 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_POW);
1027
1028 if (Z_TYPE_P(op1) == IS_ARRAY) {
1029 ZVAL_LONG(result, 0);
1030 return SUCCESS;
1031 } else {
1032 zendi_convert_scalar_to_number(op1, op1_copy, result);
1033 }
1034 if (Z_TYPE_P(op2) == IS_ARRAY) {
1035 ZVAL_LONG(result, 1L);
1036 return SUCCESS;
1037 } else {
1038 zendi_convert_scalar_to_number(op2, op2_copy, result);
1039 }
1040 converted = 1;
1041 } else {
1042 zend_error(E_ERROR, "Unsupported operand types");
1043 return FAILURE;
1044 }
1045 }
1046 }
1047 }
1048
1049
1050 ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1051 {
1052 zval op1_copy, op2_copy;
1053 int converted = 0;
1054
1055 while (1) {
1056 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
1057 case TYPE_PAIR(IS_LONG, IS_LONG):
1058 if (Z_LVAL_P(op2) == 0) {
1059 zend_error(E_WARNING, "Division by zero");
1060 ZVAL_BOOL(result, 0);
1061 return FAILURE;
1062 } else if (Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == LONG_MIN) {
1063
1064 ZVAL_DOUBLE(result, (double) LONG_MIN / -1);
1065 return SUCCESS;
1066 }
1067 if (Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0) {
1068 ZVAL_LONG(result, Z_LVAL_P(op1) / Z_LVAL_P(op2));
1069 } else {
1070 ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1)) / Z_LVAL_P(op2));
1071 }
1072 return SUCCESS;
1073
1074 case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1075 if (Z_LVAL_P(op2) == 0) {
1076 zend_error(E_WARNING, "Division by zero");
1077 ZVAL_BOOL(result, 0);
1078 return FAILURE;
1079 }
1080 ZVAL_DOUBLE(result, Z_DVAL_P(op1) / (double)Z_LVAL_P(op2));
1081 return SUCCESS;
1082
1083 case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1084 if (Z_DVAL_P(op2) == 0) {
1085 zend_error(E_WARNING, "Division by zero");
1086 ZVAL_BOOL(result, 0);
1087 return FAILURE;
1088 }
1089 ZVAL_DOUBLE(result, (double)Z_LVAL_P(op1) / Z_DVAL_P(op2));
1090 return SUCCESS;
1091
1092 case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1093 if (Z_DVAL_P(op2) == 0) {
1094 zend_error(E_WARNING, "Division by zero");
1095 ZVAL_BOOL(result, 0);
1096 return FAILURE;
1097 }
1098 ZVAL_DOUBLE(result, Z_DVAL_P(op1) / Z_DVAL_P(op2));
1099 return SUCCESS;
1100
1101 default:
1102 if (!converted) {
1103 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_DIV);
1104
1105 zendi_convert_scalar_to_number(op1, op1_copy, result);
1106 zendi_convert_scalar_to_number(op2, op2_copy, result);
1107 converted = 1;
1108 } else {
1109 zend_error(E_ERROR, "Unsupported operand types");
1110 return FAILURE;
1111 }
1112 }
1113 }
1114 }
1115
1116
1117 ZEND_API int mod_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1118 {
1119 zval op1_copy, op2_copy;
1120 long op1_lval;
1121
1122 if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
1123 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_MOD);
1124
1125 zendi_convert_to_long(op1, op1_copy, result);
1126 op1_lval = Z_LVAL_P(op1);
1127 zendi_convert_to_long(op2, op2_copy, result);
1128 } else {
1129 op1_lval = Z_LVAL_P(op1);
1130 }
1131
1132 if (Z_LVAL_P(op2) == 0) {
1133 zend_error(E_WARNING, "Division by zero");
1134 ZVAL_BOOL(result, 0);
1135 return FAILURE;
1136 }
1137
1138 if (Z_LVAL_P(op2) == -1) {
1139
1140 ZVAL_LONG(result, 0);
1141 return SUCCESS;
1142 }
1143
1144 ZVAL_LONG(result, op1_lval % Z_LVAL_P(op2));
1145 return SUCCESS;
1146 }
1147
1148
1149 ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1150 {
1151 zval op1_copy, op2_copy;
1152 long op1_lval;
1153
1154 if (Z_TYPE_P(op1) != IS_BOOL || Z_TYPE_P(op2) != IS_BOOL) {
1155 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BOOL_XOR);
1156
1157 zendi_convert_to_boolean(op1, op1_copy, result);
1158 op1_lval = Z_LVAL_P(op1);
1159 zendi_convert_to_boolean(op2, op2_copy, result);
1160 } else {
1161 op1_lval = Z_LVAL_P(op1);
1162 }
1163
1164 ZVAL_BOOL(result, op1_lval ^ Z_LVAL_P(op2));
1165 return SUCCESS;
1166 }
1167
1168
1169 ZEND_API int boolean_not_function(zval *result, zval *op1 TSRMLS_DC)
1170 {
1171 zval op1_copy;
1172
1173 if (Z_TYPE_P(op1) != IS_BOOL) {
1174 ZEND_TRY_UNARY_OBJECT_OPERATION(ZEND_BOOL_NOT);
1175
1176 zendi_convert_to_boolean(op1, op1_copy, result);
1177 }
1178
1179 ZVAL_BOOL(result, !Z_LVAL_P(op1));
1180 return SUCCESS;
1181 }
1182
1183
1184 ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC)
1185 {
1186
1187 switch (Z_TYPE_P(op1)) {
1188 case IS_LONG:
1189 ZVAL_LONG(result, ~Z_LVAL_P(op1));
1190 return SUCCESS;
1191 case IS_DOUBLE:
1192 ZVAL_LONG(result, ~zend_dval_to_lval(Z_DVAL_P(op1)));
1193 return SUCCESS;
1194 case IS_STRING: {
1195 int i;
1196 zval op1_copy = *op1;
1197
1198 Z_TYPE_P(result) = IS_STRING;
1199 Z_STRVAL_P(result) = estrndup(Z_STRVAL(op1_copy), Z_STRLEN(op1_copy));
1200 Z_STRLEN_P(result) = Z_STRLEN(op1_copy);
1201 for (i = 0; i < Z_STRLEN(op1_copy); i++) {
1202 Z_STRVAL_P(result)[i] = ~Z_STRVAL(op1_copy)[i];
1203 }
1204 return SUCCESS;
1205 }
1206 default:
1207 ZEND_TRY_UNARY_OBJECT_OPERATION(ZEND_BW_NOT);
1208
1209 zend_error(E_ERROR, "Unsupported operand types");
1210 return FAILURE;
1211 }
1212 }
1213
1214
1215 ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1216 {
1217 zval op1_copy, op2_copy;
1218 long op1_lval;
1219
1220 if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1221 zval *longer, *shorter;
1222 char *result_str;
1223 int i, result_len;
1224
1225 if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
1226 longer = op1;
1227 shorter = op2;
1228 } else {
1229 longer = op2;
1230 shorter = op1;
1231 }
1232
1233 Z_TYPE_P(result) = IS_STRING;
1234 result_len = Z_STRLEN_P(longer);
1235 result_str = estrndup(Z_STRVAL_P(longer), Z_STRLEN_P(longer));
1236 for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1237 result_str[i] |= Z_STRVAL_P(shorter)[i];
1238 }
1239 if (result==op1) {
1240 str_efree(Z_STRVAL_P(result));
1241 }
1242 Z_STRVAL_P(result) = result_str;
1243 Z_STRLEN_P(result) = result_len;
1244 return SUCCESS;
1245 }
1246
1247 if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
1248 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BW_OR);
1249
1250 zendi_convert_to_long(op1, op1_copy, result);
1251 op1_lval = Z_LVAL_P(op1);
1252 zendi_convert_to_long(op2, op2_copy, result);
1253 } else {
1254 op1_lval = Z_LVAL_P(op1);
1255 }
1256
1257 ZVAL_LONG(result, op1_lval | Z_LVAL_P(op2));
1258 return SUCCESS;
1259 }
1260
1261
1262 ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1263 {
1264 zval op1_copy, op2_copy;
1265 long op1_lval;
1266
1267 if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1268 zval *longer, *shorter;
1269 char *result_str;
1270 int i, result_len;
1271
1272 if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
1273 longer = op1;
1274 shorter = op2;
1275 } else {
1276 longer = op2;
1277 shorter = op1;
1278 }
1279
1280 Z_TYPE_P(result) = IS_STRING;
1281 result_len = Z_STRLEN_P(shorter);
1282 result_str = estrndup(Z_STRVAL_P(shorter), Z_STRLEN_P(shorter));
1283 for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1284 result_str[i] &= Z_STRVAL_P(longer)[i];
1285 }
1286 if (result==op1) {
1287 str_efree(Z_STRVAL_P(result));
1288 }
1289 Z_STRVAL_P(result) = result_str;
1290 Z_STRLEN_P(result) = result_len;
1291 return SUCCESS;
1292 }
1293
1294 if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
1295 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BW_AND);
1296
1297 zendi_convert_to_long(op1, op1_copy, result);
1298 op1_lval = Z_LVAL_P(op1);
1299 zendi_convert_to_long(op2, op2_copy, result);
1300 } else {
1301 op1_lval = Z_LVAL_P(op1);
1302 }
1303
1304 ZVAL_LONG(result, op1_lval & Z_LVAL_P(op2));
1305 return SUCCESS;
1306 }
1307
1308
1309 ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1310 {
1311 zval op1_copy, op2_copy;
1312 long op1_lval;
1313
1314 if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1315 zval *longer, *shorter;
1316 char *result_str;
1317 int i, result_len;
1318
1319 if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
1320 longer = op1;
1321 shorter = op2;
1322 } else {
1323 longer = op2;
1324 shorter = op1;
1325 }
1326
1327 Z_TYPE_P(result) = IS_STRING;
1328 result_len = Z_STRLEN_P(shorter);
1329 result_str = estrndup(Z_STRVAL_P(shorter), Z_STRLEN_P(shorter));
1330 for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1331 result_str[i] ^= Z_STRVAL_P(longer)[i];
1332 }
1333 if (result==op1) {
1334 str_efree(Z_STRVAL_P(result));
1335 }
1336 Z_STRVAL_P(result) = result_str;
1337 Z_STRLEN_P(result) = result_len;
1338 return SUCCESS;
1339 }
1340
1341 if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
1342 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_BW_XOR);
1343
1344 zendi_convert_to_long(op1, op1_copy, result);
1345 op1_lval = Z_LVAL_P(op1);
1346 zendi_convert_to_long(op2, op2_copy, result);
1347 } else {
1348 op1_lval = Z_LVAL_P(op1);
1349 }
1350
1351 ZVAL_LONG(result, op1_lval ^ Z_LVAL_P(op2));
1352 return SUCCESS;
1353 }
1354
1355
1356 ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1357 {
1358 zval op1_copy, op2_copy;
1359 long op1_lval;
1360
1361 if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
1362 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SL);
1363
1364 zendi_convert_to_long(op1, op1_copy, result);
1365 op1_lval = Z_LVAL_P(op1);
1366 zendi_convert_to_long(op2, op2_copy, result);
1367 } else {
1368 op1_lval = Z_LVAL_P(op1);
1369 }
1370
1371 ZVAL_LONG(result, op1_lval << Z_LVAL_P(op2));
1372 return SUCCESS;
1373 }
1374
1375
1376 ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1377 {
1378 zval op1_copy, op2_copy;
1379 long op1_lval;
1380
1381 if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) {
1382 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SR);
1383
1384 zendi_convert_to_long(op1, op1_copy, result);
1385 op1_lval = Z_LVAL_P(op1);
1386 zendi_convert_to_long(op2, op2_copy, result);
1387 } else {
1388 op1_lval = Z_LVAL_P(op1);
1389 }
1390
1391 ZVAL_LONG(result, op1_lval >> Z_LVAL_P(op2));
1392 return SUCCESS;
1393 }
1394
1395
1396
1397 ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2)
1398 {
1399 int length = Z_STRLEN_P(op1) + 1;
1400 char *buf = str_erealloc(Z_STRVAL_P(op1), length + 1);
1401
1402 buf[length - 1] = (char) Z_LVAL_P(op2);
1403 buf[length] = 0;
1404 ZVAL_STRINGL(result, buf, length, 0);
1405 return SUCCESS;
1406 }
1407
1408
1409
1410 ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2)
1411 {
1412 int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
1413 char *buf = str_erealloc(Z_STRVAL_P(op1), length + 1);
1414
1415 memcpy(buf + Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
1416 buf[length] = 0;
1417 ZVAL_STRINGL(result, buf, length, 0);
1418 return SUCCESS;
1419 }
1420
1421
1422 ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1423 {
1424 zval op1_copy, op2_copy;
1425 int use_copy1 = 0, use_copy2 = 0;
1426
1427 if (Z_TYPE_P(op1) != IS_STRING || Z_TYPE_P(op2) != IS_STRING) {
1428 ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_CONCAT);
1429
1430 if (Z_TYPE_P(op1) != IS_STRING) {
1431 zend_make_printable_zval(op1, &op1_copy, &use_copy1);
1432 }
1433 if (Z_TYPE_P(op2) != IS_STRING) {
1434 zend_make_printable_zval(op2, &op2_copy, &use_copy2);
1435 }
1436 }
1437
1438 if (use_copy1) {
1439
1440
1441
1442 if (result == op1) {
1443 zval_dtor(op1);
1444 }
1445 op1 = &op1_copy;
1446 }
1447 if (use_copy2) {
1448 op2 = &op2_copy;
1449 }
1450 if (result==op1 && !IS_INTERNED(Z_STRVAL_P(op1))) {
1451 uint res_len = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
1452
1453 if (Z_STRLEN_P(result) < 0 || (int) (Z_STRLEN_P(op1) + Z_STRLEN_P(op2)) < 0) {
1454 efree(Z_STRVAL_P(result));
1455 ZVAL_EMPTY_STRING(result);
1456 zend_error(E_ERROR, "String size overflow");
1457 }
1458
1459 Z_STRVAL_P(result) = safe_erealloc(Z_STRVAL_P(result), res_len, 1, 1);
1460
1461 memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(result), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
1462 Z_STRVAL_P(result)[res_len]=0;
1463 Z_STRLEN_P(result) = res_len;
1464 } else {
1465 int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
1466 char *buf;
1467
1468 if (Z_STRLEN_P(op1) < 0 || Z_STRLEN_P(op2) < 0 || (int) (Z_STRLEN_P(op1) + Z_STRLEN_P(op2)) < 0) {
1469 zend_error(E_ERROR, "String size overflow");
1470 }
1471 buf = (char *) safe_emalloc(length, 1, 1);
1472
1473 memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1));
1474 memcpy(buf + Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
1475 buf[length] = 0;
1476 ZVAL_STRINGL(result, buf, length, 0);
1477 }
1478 if (use_copy1) {
1479 zval_dtor(op1);
1480 }
1481 if (use_copy2) {
1482 zval_dtor(op2);
1483 }
1484 return SUCCESS;
1485 }
1486
1487
1488 ZEND_API int string_compare_function_ex(zval *result, zval *op1, zval *op2, zend_bool case_insensitive TSRMLS_DC)
1489 {
1490 zval op1_copy, op2_copy;
1491 int use_copy1 = 0, use_copy2 = 0;
1492
1493 if (Z_TYPE_P(op1) != IS_STRING) {
1494 zend_make_printable_zval(op1, &op1_copy, &use_copy1);
1495 }
1496 if (Z_TYPE_P(op2) != IS_STRING) {
1497 zend_make_printable_zval(op2, &op2_copy, &use_copy2);
1498 }
1499
1500 if (use_copy1) {
1501 op1 = &op1_copy;
1502 }
1503 if (use_copy2) {
1504 op2 = &op2_copy;
1505 }
1506
1507 if (case_insensitive) {
1508 ZVAL_LONG(result, zend_binary_zval_strcasecmp(op1, op2));
1509 } else {
1510 ZVAL_LONG(result, zend_binary_zval_strcmp(op1, op2));
1511 }
1512
1513 if (use_copy1) {
1514 zval_dtor(op1);
1515 }
1516 if (use_copy2) {
1517 zval_dtor(op2);
1518 }
1519 return SUCCESS;
1520 }
1521
1522
1523 ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1524 {
1525 return string_compare_function_ex(result, op1, op2, 0 TSRMLS_CC);
1526 }
1527
1528
1529 ZEND_API int string_case_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1530 {
1531 return string_compare_function_ex(result, op1, op2, 1 TSRMLS_CC);
1532 }
1533
1534
1535 #if HAVE_STRCOLL
1536 ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1537 {
1538 zval op1_copy, op2_copy;
1539 int use_copy1 = 0, use_copy2 = 0;
1540
1541 if (Z_TYPE_P(op1) != IS_STRING) {
1542 zend_make_printable_zval(op1, &op1_copy, &use_copy1);
1543 }
1544 if (Z_TYPE_P(op2) != IS_STRING) {
1545 zend_make_printable_zval(op2, &op2_copy, &use_copy2);
1546 }
1547
1548 if (use_copy1) {
1549 op1 = &op1_copy;
1550 }
1551 if (use_copy2) {
1552 op2 = &op2_copy;
1553 }
1554
1555 ZVAL_LONG(result, strcoll(Z_STRVAL_P(op1), Z_STRVAL_P(op2)));
1556
1557 if (use_copy1) {
1558 zval_dtor(op1);
1559 }
1560 if (use_copy2) {
1561 zval_dtor(op2);
1562 }
1563 return SUCCESS;
1564 }
1565
1566 #endif
1567
1568 ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1569 {
1570 zval op1_copy, op2_copy;
1571
1572 op1_copy = *op1;
1573 zval_copy_ctor(&op1_copy);
1574
1575 op2_copy = *op2;
1576 zval_copy_ctor(&op2_copy);
1577
1578 convert_to_double(&op1_copy);
1579 convert_to_double(&op2_copy);
1580
1581 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL(op1_copy)-Z_DVAL(op2_copy)));
1582
1583 return SUCCESS;
1584 }
1585
1586
1587 static inline void zend_free_obj_get_result(zval *op TSRMLS_DC)
1588 {
1589 if (Z_REFCOUNT_P(op) == 0) {
1590 GC_REMOVE_ZVAL_FROM_BUFFER(op);
1591 zval_dtor(op);
1592 FREE_ZVAL(op);
1593 } else {
1594 zval_ptr_dtor(&op);
1595 }
1596 }
1597
1598
1599 ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1600 {
1601 int ret;
1602 int converted = 0;
1603 zval op1_copy, op2_copy;
1604 zval *op_free;
1605
1606 while (1) {
1607 switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
1608 case TYPE_PAIR(IS_LONG, IS_LONG):
1609 ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0));
1610 return SUCCESS;
1611
1612 case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1613 Z_DVAL_P(result) = Z_DVAL_P(op1) - (double)Z_LVAL_P(op2);
1614 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1615 return SUCCESS;
1616
1617 case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1618 Z_DVAL_P(result) = (double)Z_LVAL_P(op1) - Z_DVAL_P(op2);
1619 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1620 return SUCCESS;
1621
1622 case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1623 if (Z_DVAL_P(op1) == Z_DVAL_P(op2)) {
1624 ZVAL_LONG(result, 0);
1625 } else {
1626 Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2);
1627 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1628 }
1629 return SUCCESS;
1630
1631 case TYPE_PAIR(IS_ARRAY, IS_ARRAY):
1632 zend_compare_arrays(result, op1, op2 TSRMLS_CC);
1633 return SUCCESS;
1634
1635 case TYPE_PAIR(IS_NULL, IS_NULL):
1636 ZVAL_LONG(result, 0);
1637 return SUCCESS;
1638
1639 case TYPE_PAIR(IS_NULL, IS_BOOL):
1640 ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0);
1641 return SUCCESS;
1642
1643 case TYPE_PAIR(IS_BOOL, IS_NULL):
1644 ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0);
1645 return SUCCESS;
1646
1647 case TYPE_PAIR(IS_BOOL, IS_BOOL):
1648 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
1649 return SUCCESS;
1650
1651 case TYPE_PAIR(IS_STRING, IS_STRING):
1652 zendi_smart_strcmp(result, op1, op2);
1653 return SUCCESS;
1654
1655 case TYPE_PAIR(IS_NULL, IS_STRING):
1656 ZVAL_LONG(result, zend_binary_strcmp("", 0, Z_STRVAL_P(op2), Z_STRLEN_P(op2)));
1657 return SUCCESS;
1658
1659 case TYPE_PAIR(IS_STRING, IS_NULL):
1660 ZVAL_LONG(result, zend_binary_strcmp(Z_STRVAL_P(op1), Z_STRLEN_P(op1), "", 0));
1661 return SUCCESS;
1662
1663 case TYPE_PAIR(IS_OBJECT, IS_NULL):
1664 ZVAL_LONG(result, 1);
1665 return SUCCESS;
1666
1667 case TYPE_PAIR(IS_NULL, IS_OBJECT):
1668 ZVAL_LONG(result, -1);
1669 return SUCCESS;
1670
1671 default:
1672 if (Z_TYPE_P(op1) == IS_OBJECT && Z_OBJ_HANDLER_P(op1, compare)) {
1673 return Z_OBJ_HANDLER_P(op1, compare)(result, op1, op2 TSRMLS_CC);
1674 } else if (Z_TYPE_P(op2) == IS_OBJECT && Z_OBJ_HANDLER_P(op2, compare)) {
1675 return Z_OBJ_HANDLER_P(op2, compare)(result, op1, op2 TSRMLS_CC);
1676 }
1677
1678 if (Z_TYPE_P(op1) == IS_OBJECT && Z_TYPE_P(op2) == IS_OBJECT) {
1679 if (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2)) {
1680
1681 ZVAL_LONG(result, 0);
1682 return SUCCESS;
1683 }
1684 if (Z_OBJ_HANDLER_P(op1, compare_objects) == Z_OBJ_HANDLER_P(op2, compare_objects)) {
1685 ZVAL_LONG(result, Z_OBJ_HANDLER_P(op1, compare_objects)(op1, op2 TSRMLS_CC));
1686 return SUCCESS;
1687 }
1688 }
1689 if (Z_TYPE_P(op1) == IS_OBJECT) {
1690 if (Z_OBJ_HT_P(op1)->get) {
1691 op_free = Z_OBJ_HT_P(op1)->get(op1 TSRMLS_CC);
1692 ret = compare_function(result, op_free, op2 TSRMLS_CC);
1693 zend_free_obj_get_result(op_free TSRMLS_CC);
1694 return ret;
1695 } else if (Z_TYPE_P(op2) != IS_OBJECT && Z_OBJ_HT_P(op1)->cast_object) {
1696 ALLOC_INIT_ZVAL(op_free);
1697 if (Z_OBJ_HT_P(op1)->cast_object(op1, op_free, Z_TYPE_P(op2) TSRMLS_CC) == FAILURE) {
1698 ZVAL_LONG(result, 1);
1699 zend_free_obj_get_result(op_free TSRMLS_CC);
1700 return SUCCESS;
1701 }
1702 ret = compare_function(result, op_free, op2 TSRMLS_CC);
1703 zend_free_obj_get_result(op_free TSRMLS_CC);
1704 return ret;
1705 }
1706 }
1707 if (Z_TYPE_P(op2) == IS_OBJECT) {
1708 if (Z_OBJ_HT_P(op2)->get) {
1709 op_free = Z_OBJ_HT_P(op2)->get(op2 TSRMLS_CC);
1710 ret = compare_function(result, op1, op_free TSRMLS_CC);
1711 zend_free_obj_get_result(op_free TSRMLS_CC);
1712 return ret;
1713 } else if (Z_TYPE_P(op1) != IS_OBJECT && Z_OBJ_HT_P(op2)->cast_object) {
1714 ALLOC_INIT_ZVAL(op_free);
1715 if (Z_OBJ_HT_P(op2)->cast_object(op2, op_free, Z_TYPE_P(op1) TSRMLS_CC) == FAILURE) {
1716 ZVAL_LONG(result, -1);
1717 zend_free_obj_get_result(op_free TSRMLS_CC);
1718 return SUCCESS;
1719 }
1720 ret = compare_function(result, op1, op_free TSRMLS_CC);
1721 zend_free_obj_get_result(op_free TSRMLS_CC);
1722 return ret;
1723 } else if (Z_TYPE_P(op1) == IS_OBJECT) {
1724 ZVAL_LONG(result, 1);
1725 return SUCCESS;
1726 }
1727 }
1728 if (!converted) {
1729 if (Z_TYPE_P(op1) == IS_NULL) {
1730 zendi_convert_to_boolean(op2, op2_copy, result);
1731 ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0);
1732 return SUCCESS;
1733 } else if (Z_TYPE_P(op2) == IS_NULL) {
1734 zendi_convert_to_boolean(op1, op1_copy, result);
1735 ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0);
1736 return SUCCESS;
1737 } else if (Z_TYPE_P(op1) == IS_BOOL) {
1738 zendi_convert_to_boolean(op2, op2_copy, result);
1739 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
1740 return SUCCESS;
1741 } else if (Z_TYPE_P(op2) == IS_BOOL) {
1742 zendi_convert_to_boolean(op1, op1_copy, result);
1743 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
1744 return SUCCESS;
1745 } else {
1746 zendi_convert_scalar_to_number(op1, op1_copy, result);
1747 zendi_convert_scalar_to_number(op2, op2_copy, result);
1748 converted = 1;
1749 }
1750 } else if (Z_TYPE_P(op1)==IS_ARRAY) {
1751 ZVAL_LONG(result, 1);
1752 return SUCCESS;
1753 } else if (Z_TYPE_P(op2)==IS_ARRAY) {
1754 ZVAL_LONG(result, -1);
1755 return SUCCESS;
1756 } else if (Z_TYPE_P(op1)==IS_OBJECT) {
1757 ZVAL_LONG(result, 1);
1758 return SUCCESS;
1759 } else if (Z_TYPE_P(op2)==IS_OBJECT) {
1760 ZVAL_LONG(result, -1);
1761 return SUCCESS;
1762 } else {
1763 ZVAL_LONG(result, 0);
1764 return FAILURE;
1765 }
1766 }
1767 }
1768 }
1769
1770
1771 static int hash_zval_identical_function(const zval **z1, const zval **z2)
1772 {
1773 zval result;
1774 TSRMLS_FETCH();
1775
1776
1777
1778
1779
1780
1781 if (is_identical_function(&result, (zval *) *z1, (zval *) *z2 TSRMLS_CC)==FAILURE) {
1782 return 1;
1783 }
1784 return !Z_LVAL(result);
1785 }
1786
1787
1788 ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1789 {
1790 Z_TYPE_P(result) = IS_BOOL;
1791 if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) {
1792 Z_LVAL_P(result) = 0;
1793 return SUCCESS;
1794 }
1795 switch (Z_TYPE_P(op1)) {
1796 case IS_NULL:
1797 Z_LVAL_P(result) = 1;
1798 break;
1799 case IS_BOOL:
1800 case IS_LONG:
1801 case IS_RESOURCE:
1802 Z_LVAL_P(result) = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
1803 break;
1804 case IS_DOUBLE:
1805 Z_LVAL_P(result) = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
1806 break;
1807 case IS_STRING:
1808 Z_LVAL_P(result) = ((Z_STRLEN_P(op1) == Z_STRLEN_P(op2))
1809 && (!memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1))));
1810 break;
1811 case IS_ARRAY:
1812 Z_LVAL_P(result) = (Z_ARRVAL_P(op1) == Z_ARRVAL_P(op2) ||
1813 zend_hash_compare(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2), (compare_func_t) hash_zval_identical_function, 1 TSRMLS_CC)==0);
1814 break;
1815 case IS_OBJECT:
1816 if (Z_OBJ_HT_P(op1) == Z_OBJ_HT_P(op2)) {
1817 Z_LVAL_P(result) = (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2));
1818 } else {
1819 Z_LVAL_P(result) = 0;
1820 }
1821 break;
1822 default:
1823 Z_LVAL_P(result) = 0;
1824 return FAILURE;
1825 }
1826 return SUCCESS;
1827 }
1828
1829
1830 ZEND_API int is_not_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1831 {
1832 if (is_identical_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1833 return FAILURE;
1834 }
1835 Z_LVAL_P(result) = !Z_LVAL_P(result);
1836 return SUCCESS;
1837 }
1838
1839
1840 ZEND_API int is_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1841 {
1842 if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1843 return FAILURE;
1844 }
1845 ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
1846 return SUCCESS;
1847 }
1848
1849
1850 ZEND_API int is_not_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1851 {
1852 if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1853 return FAILURE;
1854 }
1855 ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
1856 return SUCCESS;
1857 }
1858
1859
1860 ZEND_API int is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1861 {
1862 if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1863 return FAILURE;
1864 }
1865 ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
1866 return SUCCESS;
1867 }
1868
1869
1870 ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
1871 {
1872 if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
1873 return FAILURE;
1874 }
1875 ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
1876 return SUCCESS;
1877 }
1878
1879
1880 ZEND_API zend_bool instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool interfaces_only TSRMLS_DC)
1881 {
1882 zend_uint i;
1883
1884 for (i=0; i<instance_ce->num_interfaces; i++) {
1885 if (instanceof_function(instance_ce->interfaces[i], ce TSRMLS_CC)) {
1886 return 1;
1887 }
1888 }
1889 if (!interfaces_only) {
1890 while (instance_ce) {
1891 if (instance_ce == ce) {
1892 return 1;
1893 }
1894 instance_ce = instance_ce->parent;
1895 }
1896 }
1897
1898 return 0;
1899 }
1900
1901
1902 ZEND_API zend_bool instanceof_function(const zend_class_entry *instance_ce, const zend_class_entry *ce TSRMLS_DC)
1903 {
1904 return instanceof_function_ex(instance_ce, ce, 0 TSRMLS_CC);
1905 }
1906
1907
1908 #define LOWER_CASE 1
1909 #define UPPER_CASE 2
1910 #define NUMERIC 3
1911
1912 static void increment_string(zval *str)
1913 {
1914 int carry=0;
1915 int pos=Z_STRLEN_P(str)-1;
1916 char *s=Z_STRVAL_P(str);
1917 char *t;
1918 int last=0;
1919 int ch;
1920
1921 if (Z_STRLEN_P(str) == 0) {
1922 str_efree(Z_STRVAL_P(str));
1923 Z_STRVAL_P(str) = estrndup("1", sizeof("1")-1);
1924 Z_STRLEN_P(str) = 1;
1925 return;
1926 }
1927
1928 if (IS_INTERNED(s)) {
1929 Z_STRVAL_P(str) = s = estrndup(s, Z_STRLEN_P(str));
1930 }
1931
1932 while (pos >= 0) {
1933 ch = s[pos];
1934 if (ch >= 'a' && ch <= 'z') {
1935 if (ch == 'z') {
1936 s[pos] = 'a';
1937 carry=1;
1938 } else {
1939 s[pos]++;
1940 carry=0;
1941 }
1942 last=LOWER_CASE;
1943 } else if (ch >= 'A' && ch <= 'Z') {
1944 if (ch == 'Z') {
1945 s[pos] = 'A';
1946 carry=1;
1947 } else {
1948 s[pos]++;
1949 carry=0;
1950 }
1951 last=UPPER_CASE;
1952 } else if (ch >= '0' && ch <= '9') {
1953 if (ch == '9') {
1954 s[pos] = '0';
1955 carry=1;
1956 } else {
1957 s[pos]++;
1958 carry=0;
1959 }
1960 last = NUMERIC;
1961 } else {
1962 carry=0;
1963 break;
1964 }
1965 if (carry == 0) {
1966 break;
1967 }
1968 pos--;
1969 }
1970
1971 if (carry) {
1972 t = (char *) emalloc(Z_STRLEN_P(str)+1+1);
1973 memcpy(t+1, Z_STRVAL_P(str), Z_STRLEN_P(str));
1974 Z_STRLEN_P(str)++;
1975 t[Z_STRLEN_P(str)] = '\0';
1976 switch (last) {
1977 case NUMERIC:
1978 t[0] = '1';
1979 break;
1980 case UPPER_CASE:
1981 t[0] = 'A';
1982 break;
1983 case LOWER_CASE:
1984 t[0] = 'a';
1985 break;
1986 }
1987 str_efree(Z_STRVAL_P(str));
1988 Z_STRVAL_P(str) = t;
1989 }
1990 }
1991
1992
1993 ZEND_API int increment_function(zval *op1)
1994 {
1995 switch (Z_TYPE_P(op1)) {
1996 case IS_LONG:
1997 if (Z_LVAL_P(op1) == LONG_MAX) {
1998
1999 double d = (double)Z_LVAL_P(op1);
2000 ZVAL_DOUBLE(op1, d+1);
2001 } else {
2002 Z_LVAL_P(op1)++;
2003 }
2004 break;
2005 case IS_DOUBLE:
2006 Z_DVAL_P(op1) = Z_DVAL_P(op1) + 1;
2007 break;
2008 case IS_NULL:
2009 ZVAL_LONG(op1, 1);
2010 break;
2011 case IS_STRING: {
2012 long lval;
2013 double dval;
2014
2015 switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
2016 case IS_LONG:
2017 str_efree(Z_STRVAL_P(op1));
2018 if (lval == LONG_MAX) {
2019
2020 double d = (double)lval;
2021 ZVAL_DOUBLE(op1, d+1);
2022 } else {
2023 ZVAL_LONG(op1, lval+1);
2024 }
2025 break;
2026 case IS_DOUBLE:
2027 str_efree(Z_STRVAL_P(op1));
2028 ZVAL_DOUBLE(op1, dval+1);
2029 break;
2030 default:
2031
2032 increment_string(op1);
2033 break;
2034 }
2035 }
2036 break;
2037 case IS_OBJECT:
2038 if (Z_OBJ_HANDLER_P(op1, do_operation)) {
2039 zval *op2;
2040 int res;
2041 TSRMLS_FETCH();
2042
2043 MAKE_STD_ZVAL(op2);
2044 ZVAL_LONG(op2, 1);
2045 res = Z_OBJ_HANDLER_P(op1, do_operation)(ZEND_ADD, op1, op1, op2 TSRMLS_CC);
2046 zval_ptr_dtor(&op2);
2047
2048 return res;
2049 }
2050 return FAILURE;
2051 default:
2052 return FAILURE;
2053 }
2054 return SUCCESS;
2055 }
2056
2057
2058 ZEND_API int decrement_function(zval *op1)
2059 {
2060 long lval;
2061 double dval;
2062
2063 switch (Z_TYPE_P(op1)) {
2064 case IS_LONG:
2065 if (Z_LVAL_P(op1) == LONG_MIN) {
2066 double d = (double)Z_LVAL_P(op1);
2067 ZVAL_DOUBLE(op1, d-1);
2068 } else {
2069 Z_LVAL_P(op1)--;
2070 }
2071 break;
2072 case IS_DOUBLE:
2073 Z_DVAL_P(op1) = Z_DVAL_P(op1) - 1;
2074 break;
2075 case IS_STRING:
2076 if (Z_STRLEN_P(op1) == 0) {
2077 str_efree(Z_STRVAL_P(op1));
2078 ZVAL_LONG(op1, -1);
2079 break;
2080 }
2081 switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
2082 case IS_LONG:
2083 str_efree(Z_STRVAL_P(op1));
2084 if (lval == LONG_MIN) {
2085 double d = (double)lval;
2086 ZVAL_DOUBLE(op1, d-1);
2087 } else {
2088 ZVAL_LONG(op1, lval-1);
2089 }
2090 break;
2091 case IS_DOUBLE:
2092 str_efree(Z_STRVAL_P(op1));
2093 ZVAL_DOUBLE(op1, dval - 1);
2094 break;
2095 }
2096 break;
2097 case IS_OBJECT:
2098 if (Z_OBJ_HANDLER_P(op1, do_operation)) {
2099 zval *op2;
2100 int res;
2101 TSRMLS_FETCH();
2102
2103 MAKE_STD_ZVAL(op2);
2104 ZVAL_LONG(op2, 1);
2105 res = Z_OBJ_HANDLER_P(op1, do_operation)(ZEND_SUB, op1, op1, op2 TSRMLS_CC);
2106 zval_ptr_dtor(&op2);
2107
2108 return res;
2109 }
2110 return FAILURE;
2111 default:
2112 return FAILURE;
2113 }
2114
2115 return SUCCESS;
2116 }
2117
2118
2119 ZEND_API int zval_is_true(zval *op)
2120 {
2121 convert_to_boolean(op);
2122 return (Z_LVAL_P(op) ? 1 : 0);
2123 }
2124
2125
2126 #ifdef ZEND_USE_TOLOWER_L
2127 ZEND_API void zend_update_current_locale(void)
2128 {
2129 current_locale = _get_current_locale();
2130 }
2131
2132 #endif
2133
2134 ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length)
2135 {
2136 register unsigned char *str = (unsigned char*)source;
2137 register unsigned char *result = (unsigned char*)dest;
2138 register unsigned char *end = str + length;
2139
2140 while (str < end) {
2141 *result++ = zend_tolower_ascii(*str++);
2142 }
2143 *result = '\0';
2144
2145 return dest;
2146 }
2147
2148
2149 ZEND_API char *zend_str_tolower_dup(const char *source, unsigned int length)
2150 {
2151 return zend_str_tolower_copy((char *)emalloc(length+1), source, length);
2152 }
2153
2154
2155 ZEND_API void zend_str_tolower(char *str, unsigned int length)
2156 {
2157 register unsigned char *p = (unsigned char*)str;
2158 register unsigned char *end = p + length;
2159
2160 while (p < end) {
2161 *p = zend_tolower_ascii(*p);
2162 p++;
2163 }
2164 }
2165
2166
2167 ZEND_API int zend_binary_strcmp(const char *s1, uint len1, const char *s2, uint len2)
2168 {
2169 int retval;
2170
2171 if (s1 == s2) {
2172 return 0;
2173 }
2174 retval = memcmp(s1, s2, MIN(len1, len2));
2175 if (!retval) {
2176 return (len1 - len2);
2177 } else {
2178 return retval;
2179 }
2180 }
2181
2182
2183 ZEND_API int zend_binary_strncmp(const char *s1, uint len1, const char *s2, uint len2, uint length)
2184 {
2185 int retval;
2186
2187 if (s1 == s2) {
2188 return 0;
2189 }
2190 retval = memcmp(s1, s2, MIN(length, MIN(len1, len2)));
2191 if (!retval) {
2192 return (MIN(length, len1) - MIN(length, len2));
2193 } else {
2194 return retval;
2195 }
2196 }
2197
2198
2199 ZEND_API int zend_binary_strcasecmp(const char *s1, uint len1, const char *s2, uint len2)
2200 {
2201 int len;
2202 int c1, c2;
2203
2204 if (s1 == s2) {
2205 return 0;
2206 }
2207
2208 len = MIN(len1, len2);
2209 while (len--) {
2210 c1 = zend_tolower_ascii(*(unsigned char *)s1++);
2211 c2 = zend_tolower_ascii(*(unsigned char *)s2++);
2212 if (c1 != c2) {
2213 return c1 - c2;
2214 }
2215 }
2216
2217 return len1 - len2;
2218 }
2219
2220
2221 ZEND_API int zend_binary_strncasecmp(const char *s1, uint len1, const char *s2, uint len2, uint length)
2222 {
2223 int len;
2224 int c1, c2;
2225
2226 if (s1 == s2) {
2227 return 0;
2228 }
2229 len = MIN(length, MIN(len1, len2));
2230 while (len--) {
2231 c1 = zend_tolower_ascii(*(unsigned char *)s1++);
2232 c2 = zend_tolower_ascii(*(unsigned char *)s2++);
2233 if (c1 != c2) {
2234 return c1 - c2;
2235 }
2236 }
2237
2238 return MIN(length, len1) - MIN(length, len2);
2239 }
2240
2241
2242 ZEND_API int zend_binary_strcasecmp_l(const char *s1, uint len1, const char *s2, uint len2)
2243 {
2244 int len;
2245 int c1, c2;
2246
2247 if (s1 == s2) {
2248 return 0;
2249 }
2250
2251 len = MIN(len1, len2);
2252 while (len--) {
2253 c1 = zend_tolower((int)*(unsigned char *)s1++);
2254 c2 = zend_tolower((int)*(unsigned char *)s2++);
2255 if (c1 != c2) {
2256 return c1 - c2;
2257 }
2258 }
2259
2260 return len1 - len2;
2261 }
2262
2263
2264 ZEND_API int zend_binary_strncasecmp_l(const char *s1, uint len1, const char *s2, uint len2, uint length)
2265 {
2266 int len;
2267 int c1, c2;
2268
2269 if (s1 == s2) {
2270 return 0;
2271 }
2272 len = MIN(length, MIN(len1, len2));
2273 while (len--) {
2274 c1 = zend_tolower((int)*(unsigned char *)s1++);
2275 c2 = zend_tolower((int)*(unsigned char *)s2++);
2276 if (c1 != c2) {
2277 return c1 - c2;
2278 }
2279 }
2280
2281 return MIN(length, len1) - MIN(length, len2);
2282 }
2283
2284
2285 ZEND_API int zend_binary_zval_strcmp(zval *s1, zval *s2)
2286 {
2287 return zend_binary_strcmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2));
2288 }
2289
2290
2291 ZEND_API int zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3)
2292 {
2293 return zend_binary_strncmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2), Z_LVAL_P(s3));
2294 }
2295
2296
2297 ZEND_API int zend_binary_zval_strcasecmp(zval *s1, zval *s2)
2298 {
2299 return zend_binary_strcasecmp_l(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2));
2300 }
2301
2302
2303 ZEND_API int zend_binary_zval_strncasecmp(zval *s1, zval *s2, zval *s3)
2304 {
2305 return zend_binary_strncasecmp_l(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2), Z_LVAL_P(s3));
2306 }
2307
2308
2309 ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2)
2310 {
2311 int ret1, ret2;
2312 int oflow1, oflow2;
2313 long lval1 = 0, lval2 = 0;
2314 double dval1 = 0.0, dval2 = 0.0;
2315
2316 if ((ret1=is_numeric_string_ex(Z_STRVAL_P(s1), Z_STRLEN_P(s1), &lval1, &dval1, 0, &oflow1)) &&
2317 (ret2=is_numeric_string_ex(Z_STRVAL_P(s2), Z_STRLEN_P(s2), &lval2, &dval2, 0, &oflow2))) {
2318 #if ULONG_MAX == 0xFFFFFFFF
2319 if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0. &&
2320 ((oflow1 == 1 && dval1 > 9007199254740991. )
2321 || (oflow1 == -1 && dval1 < -9007199254740991.))) {
2322 #else
2323 if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0.) {
2324 #endif
2325
2326
2327 goto string_cmp;
2328 }
2329 if ((ret1==IS_DOUBLE) || (ret2==IS_DOUBLE)) {
2330 if (ret1!=IS_DOUBLE) {
2331 if (oflow2) {
2332
2333 ZVAL_LONG(result, -1 * oflow2);
2334 return;
2335 }
2336 dval1 = (double) lval1;
2337 } else if (ret2!=IS_DOUBLE) {
2338 if (oflow1) {
2339 ZVAL_LONG(result, oflow1);
2340 return;
2341 }
2342 dval2 = (double) lval2;
2343 } else if (dval1 == dval2 && !zend_finite(dval1)) {
2344
2345
2346 goto string_cmp;
2347 }
2348 Z_DVAL_P(result) = dval1 - dval2;
2349 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
2350 } else {
2351 ZVAL_LONG(result, lval1 > lval2 ? 1 : (lval1 < lval2 ? -1 : 0));
2352 }
2353 } else {
2354 string_cmp:
2355 Z_LVAL_P(result) = zend_binary_zval_strcmp(s1, s2);
2356 ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(result)));
2357 }
2358 }
2359
2360
2361 static int hash_zval_compare_function(const zval **z1, const zval **z2 TSRMLS_DC)
2362 {
2363 zval result;
2364
2365 if (compare_function(&result, (zval *) *z1, (zval *) *z2 TSRMLS_CC)==FAILURE) {
2366 return 1;
2367 }
2368 return Z_LVAL(result);
2369 }
2370
2371
2372 ZEND_API int zend_compare_symbol_tables_i(HashTable *ht1, HashTable *ht2 TSRMLS_DC)
2373 {
2374 return ht1 == ht2 ? 0 : zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC);
2375 }
2376
2377
2378 ZEND_API void zend_compare_symbol_tables(zval *result, HashTable *ht1, HashTable *ht2 TSRMLS_DC)
2379 {
2380 ZVAL_LONG(result, ht1 == ht2 ? 0 : zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC));
2381 }
2382
2383
2384 ZEND_API void zend_compare_arrays(zval *result, zval *a1, zval *a2 TSRMLS_DC)
2385 {
2386 zend_compare_symbol_tables(result, Z_ARRVAL_P(a1), Z_ARRVAL_P(a2) TSRMLS_CC);
2387 }
2388
2389
2390 ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC)
2391 {
2392 Z_TYPE_P(result) = IS_LONG;
2393
2394 if (Z_OBJ_HANDLE_P(o1) == Z_OBJ_HANDLE_P(o2)) {
2395 Z_LVAL_P(result) = 0;
2396 return;
2397 }
2398
2399 if (Z_OBJ_HT_P(o1)->compare_objects == NULL) {
2400 Z_LVAL_P(result) = 1;
2401 } else {
2402 Z_LVAL_P(result) = Z_OBJ_HT_P(o1)->compare_objects(o1, o2 TSRMLS_CC);
2403 }
2404 }
2405
2406
2407 ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC)
2408 {
2409 TSRMLS_FETCH();
2410
2411 Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "%.*G", (int) EG(precision), (double)Z_DVAL_P(op));
2412 }
2413
2414
2415
2416
2417
2418
2419
2420
2421