1/*
2   +----------------------------------------------------------------------+
3   | Zend Engine                                                          |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1998-2015 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$ */
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>
36static _locale_t current_locale = NULL;
37/* this is true global! may lead to strange effects on ZTS, but so may setlocale() */
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
45static const unsigned char tolower_map[256] = {
460x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
470x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
480x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
490x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
500x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
510x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x5b,0x5c,0x5d,0x5e,0x5f,
520x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
530x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
540x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
550x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
560xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
570xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
580xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
590xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
600xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
610xf0,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 * Functions using locale lowercase:
68        zend_binary_strncasecmp_l
69        zend_binary_strcasecmp_l
70        zend_binary_zval_strcasecmp
71        zend_binary_zval_strncasecmp
72        string_compare_function_ex
73        string_case_compare_function
74 * Functions using ascii lowercase:
75        zend_str_tolower_copy
76        zend_str_tolower_dup
77        zend_str_tolower
78        zend_binary_strcasecmp
79        zend_binary_strncasecmp
80 */
81
82ZEND_API int ZEND_FASTCALL zend_atoi(const char *str, int str_len) /* {{{ */
83{
84    int retval;
85
86    if (!str_len) {
87        str_len = (int)strlen(str);
88    }
89    retval = ZEND_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                /* break intentionally missing */
96            case 'm':
97            case 'M':
98                retval *= 1024;
99                /* break intentionally missing */
100            case 'k':
101            case 'K':
102                retval *= 1024;
103                break;
104        }
105    }
106    return retval;
107}
108/* }}} */
109
110ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, int str_len) /* {{{ */
111{
112    zend_long retval;
113
114    if (!str_len) {
115        str_len = (int)strlen(str);
116    }
117    retval = ZEND_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                /* break intentionally missing */
124            case 'm':
125            case 'M':
126                retval *= 1024;
127                /* break intentionally missing */
128            case 'k':
129            case 'K':
130                retval *= 1024;
131                break;
132        }
133    }
134    return retval;
135}
136/* }}} */
137
138static zend_always_inline void zend_unwrap_reference(zval *op) /* {{{ */
139{
140    if (Z_REFCOUNT_P(op) == 1) {
141        ZVAL_UNREF(op);
142    } else {
143        Z_DELREF_P(op);
144        ZVAL_COPY(op, Z_REFVAL_P(op));
145    }
146}
147/* }}} */
148
149ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */
150{
151try_again:
152    switch (Z_TYPE_P(op)) {
153        case IS_REFERENCE:
154            zend_unwrap_reference(op);
155            goto try_again;
156        case IS_STRING:
157            {
158                zend_string *str;
159
160                str = Z_STR_P(op);
161                if ((Z_TYPE_INFO_P(op)=is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), &Z_LVAL_P(op), &Z_DVAL_P(op), 1)) == 0) {
162                    ZVAL_LONG(op, 0);
163                }
164                zend_string_release(str);
165                break;
166            }
167        case IS_NULL:
168        case IS_FALSE:
169            ZVAL_LONG(op, 0);
170            break;
171        case IS_TRUE:
172            ZVAL_LONG(op, 1);
173            break;
174        case IS_RESOURCE:
175            {
176                zend_long l = Z_RES_HANDLE_P(op);
177                zval_ptr_dtor(op);
178                ZVAL_LONG(op, l);
179            }
180            break;
181        case IS_OBJECT:
182            convert_to_long_base(op, 10);
183            break;
184    }
185}
186/* }}} */
187
188/* {{{ zendi_convert_scalar_to_number */
189#define zendi_convert_scalar_to_number(op, holder, result)          \
190    if (op==result) {                                               \
191        if (Z_TYPE_P(op) != IS_LONG) {                              \
192            convert_scalar_to_number(op);                   \
193        }                                                           \
194    } else {                                                        \
195        switch (Z_TYPE_P(op)) {                                     \
196            case IS_STRING:                                         \
197                {                                                   \
198                    if ((Z_TYPE_INFO(holder)=is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &Z_LVAL(holder), &Z_DVAL(holder), 1)) == 0) {    \
199                        ZVAL_LONG(&(holder), 0);                            \
200                    }                                                       \
201                    (op) = &(holder);                                       \
202                    break;                                                  \
203                }                                                           \
204            case IS_NULL:                                                   \
205            case IS_FALSE:                                                  \
206                ZVAL_LONG(&(holder), 0);                                    \
207                (op) = &(holder);                                           \
208                break;                                                      \
209            case IS_TRUE:                                                   \
210                ZVAL_LONG(&(holder), 1);                                    \
211                (op) = &(holder);                                           \
212                break;                                                      \
213            case IS_RESOURCE:                                               \
214                ZVAL_LONG(&(holder), Z_RES_HANDLE_P(op));                   \
215                (op) = &(holder);                                           \
216                break;                                                      \
217            case IS_OBJECT:                                                 \
218                ZVAL_COPY(&(holder), op);                                       \
219                convert_to_long_base(&(holder), 10);                        \
220                if (Z_TYPE(holder) == IS_LONG) {                            \
221                    (op) = &(holder);                                       \
222                }                                                           \
223                break;                                                      \
224        }                                                                   \
225    }
226
227/* }}} */
228
229/* {{{ convert_object_to_type: dst will be either ctype or UNDEF */
230#define convert_object_to_type(op, dst, ctype, conv_func)                                   \
231    ZVAL_UNDEF(dst);                                                                        \
232    if (Z_OBJ_HT_P(op)->cast_object) {                                                      \
233        if (Z_OBJ_HT_P(op)->cast_object(op, dst, ctype) == FAILURE) {               \
234            zend_error(E_RECOVERABLE_ERROR,                                                 \
235                "Object of class %s could not be converted to %s", ZSTR_VAL(Z_OBJCE_P(op)->name),\
236            zend_get_type_by_const(ctype));                                                 \
237        }                                                                                   \
238    } else if (Z_OBJ_HT_P(op)->get) {                                                       \
239        zval *newop = Z_OBJ_HT_P(op)->get(op, dst);                             \
240        if (Z_TYPE_P(newop) != IS_OBJECT) {                                                 \
241            /* for safety - avoid loop */                                                   \
242            ZVAL_COPY_VALUE(dst, newop);                                                    \
243            conv_func(dst);                                                                 \
244        }                                                                                   \
245    }
246
247/* }}} */
248
249#define convert_op1_op2_long(op1, op1_lval, op2, op2_lval, op, op_func) \
250    do {                                                                \
251        if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {                     \
252            if (Z_ISREF_P(op1)) {                                       \
253                op1 = Z_REFVAL_P(op1);                                  \
254                if (Z_TYPE_P(op1) == IS_LONG) {                         \
255                    op1_lval = Z_LVAL_P(op1);                           \
256                    break;                                              \
257                }                                                       \
258            }                                                           \
259            ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(op, op_func);          \
260            op1_lval = _zval_get_long_func(op1);                        \
261        } else {                                                        \
262            op1_lval = Z_LVAL_P(op1);                                   \
263        }                                                               \
264    } while (0);                                                        \
265    do {                                                                \
266        if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {                     \
267            if (Z_ISREF_P(op2)) {                                       \
268                op2 = Z_REFVAL_P(op2);                                  \
269                if (Z_TYPE_P(op2) == IS_LONG) {                         \
270                    op2_lval = Z_LVAL_P(op2);                           \
271                    break;                                              \
272                }                                                       \
273            }                                                           \
274            ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(op);                   \
275            op2_lval = _zval_get_long_func(op2);                        \
276        } else {                                                        \
277            op2_lval = Z_LVAL_P(op2);                                   \
278        }                                                               \
279    } while (0);
280
281ZEND_API void ZEND_FASTCALL convert_to_long(zval *op) /* {{{ */
282{
283    if (Z_TYPE_P(op) != IS_LONG) {
284        convert_to_long_base(op, 10);
285    }
286}
287/* }}} */
288
289ZEND_API void ZEND_FASTCALL convert_to_long_base(zval *op, int base) /* {{{ */
290{
291    zend_long tmp;
292
293try_again:
294    switch (Z_TYPE_P(op)) {
295        case IS_NULL:
296        case IS_FALSE:
297            ZVAL_LONG(op, 0);
298            break;
299        case IS_TRUE:
300            ZVAL_LONG(op, 1);
301            break;
302        case IS_RESOURCE:
303            tmp = Z_RES_HANDLE_P(op);
304            zval_ptr_dtor(op);
305            ZVAL_LONG(op, tmp);
306            break;
307        case IS_LONG:
308            break;
309        case IS_DOUBLE:
310            ZVAL_LONG(op, zend_dval_to_lval(Z_DVAL_P(op)));
311            break;
312        case IS_STRING:
313            {
314                zend_string *str = Z_STR_P(op);
315
316                ZVAL_LONG(op, ZEND_STRTOL(ZSTR_VAL(str), NULL, base));
317                zend_string_release(str);
318            }
319            break;
320        case IS_ARRAY:
321            tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
322            zval_ptr_dtor(op);
323            ZVAL_LONG(op, tmp);
324            break;
325        case IS_OBJECT:
326            {
327                zval dst;
328
329                convert_object_to_type(op, &dst, IS_LONG, convert_to_long);
330                zval_dtor(op);
331
332                if (Z_TYPE(dst) == IS_LONG) {
333                    ZVAL_COPY_VALUE(op, &dst);
334                } else {
335
336                    ZVAL_LONG(op, 1);
337                }
338                return;
339            }
340        case IS_REFERENCE:
341            zend_unwrap_reference(op);
342            goto try_again;
343        EMPTY_SWITCH_DEFAULT_CASE()
344    }
345}
346/* }}} */
347
348ZEND_API void ZEND_FASTCALL convert_to_double(zval *op) /* {{{ */
349{
350    double tmp;
351
352try_again:
353    switch (Z_TYPE_P(op)) {
354        case IS_NULL:
355        case IS_FALSE:
356            ZVAL_DOUBLE(op, 0.0);
357            break;
358        case IS_TRUE:
359            ZVAL_DOUBLE(op, 1.0);
360            break;
361        case IS_RESOURCE: {
362                double d = (double) Z_RES_HANDLE_P(op);
363                zval_ptr_dtor(op);
364                ZVAL_DOUBLE(op, d);
365            }
366            break;
367        case IS_LONG:
368            ZVAL_DOUBLE(op, (double) Z_LVAL_P(op));
369            break;
370        case IS_DOUBLE:
371            break;
372        case IS_STRING:
373            {
374                zend_string *str = Z_STR_P(op);
375
376                ZVAL_DOUBLE(op, zend_strtod(ZSTR_VAL(str), NULL));
377                zend_string_release(str);
378            }
379            break;
380        case IS_ARRAY:
381            tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
382            zval_ptr_dtor(op);
383            ZVAL_DOUBLE(op, tmp);
384            break;
385        case IS_OBJECT:
386            {
387                zval dst;
388
389                convert_object_to_type(op, &dst, IS_DOUBLE, convert_to_double);
390                zval_dtor(op);
391
392                if (Z_TYPE(dst) == IS_DOUBLE) {
393                    ZVAL_COPY_VALUE(op, &dst);
394                } else {
395                    ZVAL_DOUBLE(op, 1.0);
396                }
397                break;
398            }
399        case IS_REFERENCE:
400            zend_unwrap_reference(op);
401            goto try_again;
402        EMPTY_SWITCH_DEFAULT_CASE()
403    }
404}
405/* }}} */
406
407ZEND_API void ZEND_FASTCALL convert_to_null(zval *op) /* {{{ */
408{
409    if (Z_TYPE_P(op) == IS_OBJECT) {
410        if (Z_OBJ_HT_P(op)->cast_object) {
411            zval org;
412
413            ZVAL_COPY_VALUE(&org, op);
414            if (Z_OBJ_HT_P(op)->cast_object(&org, op, IS_NULL) == SUCCESS) {
415                zval_dtor(&org);
416                return;
417            }
418            ZVAL_COPY_VALUE(op, &org);
419        }
420    }
421
422    zval_ptr_dtor(op);
423    ZVAL_NULL(op);
424}
425/* }}} */
426
427ZEND_API void ZEND_FASTCALL convert_to_boolean(zval *op) /* {{{ */
428{
429    int tmp;
430
431try_again:
432    switch (Z_TYPE_P(op)) {
433        case IS_FALSE:
434        case IS_TRUE:
435            break;
436        case IS_NULL:
437            ZVAL_FALSE(op);
438            break;
439        case IS_RESOURCE: {
440                zend_long l = (Z_RES_HANDLE_P(op) ? 1 : 0);
441
442                zval_ptr_dtor(op);
443                ZVAL_BOOL(op, l);
444            }
445            break;
446        case IS_LONG:
447            ZVAL_BOOL(op, Z_LVAL_P(op) ? 1 : 0);
448            break;
449        case IS_DOUBLE:
450            ZVAL_BOOL(op, Z_DVAL_P(op) ? 1 : 0);
451            break;
452        case IS_STRING:
453            {
454                zend_string *str = Z_STR_P(op);
455
456                if (ZSTR_LEN(str) == 0
457                    || (ZSTR_LEN(str) == 1 && ZSTR_VAL(str)[0] == '0')) {
458                    ZVAL_FALSE(op);
459                } else {
460                    ZVAL_TRUE(op);
461                }
462                zend_string_release(str);
463            }
464            break;
465        case IS_ARRAY:
466            tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
467            zval_ptr_dtor(op);
468            ZVAL_BOOL(op, tmp);
469            break;
470        case IS_OBJECT:
471            {
472                zval dst;
473
474                convert_object_to_type(op, &dst, _IS_BOOL, convert_to_boolean);
475                zval_dtor(op);
476
477                if (Z_TYPE(dst) == IS_FALSE || Z_TYPE(dst) == IS_TRUE) {
478                    ZVAL_COPY_VALUE(op, &dst);
479                } else {
480                    ZVAL_TRUE(op);
481                }
482                break;
483            }
484        case IS_REFERENCE:
485            zend_unwrap_reference(op);
486            goto try_again;
487        EMPTY_SWITCH_DEFAULT_CASE()
488    }
489}
490/* }}} */
491
492ZEND_API void ZEND_FASTCALL _convert_to_cstring(zval *op ZEND_FILE_LINE_DC) /* {{{ */
493{
494    _convert_to_string(op ZEND_FILE_LINE_CC);
495}
496/* }}} */
497
498ZEND_API void ZEND_FASTCALL _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{{ */
499{
500try_again:
501    switch (Z_TYPE_P(op)) {
502        case IS_UNDEF:
503        case IS_NULL:
504        case IS_FALSE: {
505            ZVAL_EMPTY_STRING(op);
506            break;
507        }
508        case IS_TRUE:
509            if (CG(one_char_string)['1']) {
510                ZVAL_INTERNED_STR(op, CG(one_char_string)['1']);
511            } else {
512                ZVAL_NEW_STR(op, zend_string_init("1", 1, 0));
513            }
514            break;
515        case IS_STRING:
516            break;
517        case IS_RESOURCE: {
518            char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG];
519            int len = snprintf(buf, sizeof(buf), "Resource id #" ZEND_LONG_FMT, (zend_long)Z_RES_HANDLE_P(op));
520            zval_ptr_dtor(op);
521            ZVAL_NEW_STR(op, zend_string_init(buf, len, 0));
522            break;
523        }
524        case IS_LONG: {
525            ZVAL_NEW_STR(op, zend_long_to_str(Z_LVAL_P(op)));
526            break;
527        }
528        case IS_DOUBLE: {
529            zend_string *str;
530            double dval = Z_DVAL_P(op);
531
532            str = zend_strpprintf(0, "%.*G", (int) EG(precision), dval);
533            /* %G already handles removing trailing zeros from the fractional part, yay */
534            ZVAL_NEW_STR(op, str);
535            break;
536        }
537        case IS_ARRAY:
538            zend_error(E_NOTICE, "Array to string conversion");
539            zval_ptr_dtor(op);
540            ZVAL_NEW_STR(op, zend_string_init("Array", sizeof("Array")-1, 0));
541            break;
542        case IS_OBJECT: {
543            zval dst;
544
545            convert_object_to_type(op, &dst, IS_STRING, convert_to_string);
546            zval_dtor(op);
547
548            if (Z_TYPE(dst) == IS_STRING) {
549                ZVAL_COPY_VALUE(op, &dst);
550            } else {
551                ZVAL_NEW_STR(op, zend_string_init("Object", sizeof("Object")-1, 0));
552            }
553            break;
554        }
555        case IS_REFERENCE:
556            zend_unwrap_reference(op);
557            goto try_again;
558        EMPTY_SWITCH_DEFAULT_CASE()
559    }
560}
561/* }}} */
562
563static void convert_scalar_to_array(zval *op) /* {{{ */
564{
565    zval entry;
566
567    ZVAL_COPY_VALUE(&entry, op);
568
569    ZVAL_NEW_ARR(op);
570    zend_hash_init(Z_ARRVAL_P(op), 8, NULL, ZVAL_PTR_DTOR, 0);
571    zend_hash_index_add_new(Z_ARRVAL_P(op), 0, &entry);
572}
573/* }}} */
574
575ZEND_API void ZEND_FASTCALL convert_to_array(zval *op) /* {{{ */
576{
577try_again:
578    switch (Z_TYPE_P(op)) {
579        case IS_ARRAY:
580            break;
581/* OBJECTS_OPTIMIZE */
582        case IS_OBJECT:
583            if (Z_OBJCE_P(op) == zend_ce_closure) {
584                convert_scalar_to_array(op);
585            } else {
586                if (Z_OBJ_HT_P(op)->get_properties) {
587                    HashTable *obj_ht = Z_OBJ_HT_P(op)->get_properties(op);
588                    if (obj_ht) {
589                        zval arr;
590
591                        if (!Z_OBJCE_P(op)->default_properties_count && obj_ht == Z_OBJ_P(op)->properties) {
592                            /* fast copy */
593                            if (EXPECTED(Z_OBJ_P(op)->handlers == &std_object_handlers)) {
594                                ZVAL_ARR(&arr, obj_ht);
595                                if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(op)->properties) & IS_ARRAY_IMMUTABLE))) {
596                                    GC_REFCOUNT(Z_OBJ_P(op)->properties)++;
597                                }
598                            } else {
599                                ZVAL_ARR(&arr, zend_array_dup(obj_ht));
600                            }
601                            zval_dtor(op);
602                            ZVAL_COPY_VALUE(op, &arr);
603                        } else {
604                            ZVAL_ARR(&arr, zend_array_dup(obj_ht));
605                            zval_dtor(op);
606                            ZVAL_COPY_VALUE(op, &arr);
607                        }
608                        return;
609                    }
610                } else {
611                    zval dst;
612                    convert_object_to_type(op, &dst, IS_ARRAY, convert_to_array);
613
614                    if (Z_TYPE(dst) == IS_ARRAY) {
615                        zval_dtor(op);
616                        ZVAL_COPY_VALUE(op, &dst);
617                        return;
618                    }
619                }
620
621                zval_dtor(op);
622                array_init(op);
623            }
624            break;
625        case IS_NULL:
626            ZVAL_NEW_ARR(op);
627            zend_hash_init(Z_ARRVAL_P(op), 8, NULL, ZVAL_PTR_DTOR, 0);
628            break;
629        case IS_REFERENCE:
630            zend_unwrap_reference(op);
631            goto try_again;
632        default:
633            convert_scalar_to_array(op);
634            break;
635    }
636}
637/* }}} */
638
639ZEND_API void ZEND_FASTCALL convert_to_object(zval *op) /* {{{ */
640{
641try_again:
642    switch (Z_TYPE_P(op)) {
643        case IS_ARRAY:
644            {
645                zval tmp;
646                ZVAL_COPY_VALUE(&tmp, op);
647                SEPARATE_ARRAY(&tmp);
648                object_and_properties_init(op, zend_standard_class_def, Z_ARR(tmp));
649                break;
650            }
651        case IS_OBJECT:
652            break;
653        case IS_NULL:
654            object_init(op);
655            break;
656        case IS_REFERENCE:
657            zend_unwrap_reference(op);
658            goto try_again;
659        default: {
660            zval tmp;
661            ZVAL_COPY_VALUE(&tmp, op);
662            object_init(op);
663            zend_hash_str_add_new(Z_OBJPROP_P(op), "scalar", sizeof("scalar")-1, &tmp);
664            break;
665        }
666    }
667}
668/* }}} */
669
670ZEND_API void multi_convert_to_long_ex(int argc, ...) /* {{{ */
671{
672    zval *arg;
673    va_list ap;
674
675    va_start(ap, argc);
676
677    while (argc--) {
678        arg = va_arg(ap, zval *);
679        convert_to_long_ex(arg);
680    }
681
682    va_end(ap);
683}
684/* }}} */
685
686ZEND_API void multi_convert_to_double_ex(int argc, ...) /* {{{ */
687{
688    zval *arg;
689    va_list ap;
690
691    va_start(ap, argc);
692
693    while (argc--) {
694        arg = va_arg(ap, zval *);
695        convert_to_double_ex(arg);
696    }
697
698    va_end(ap);
699}
700/* }}} */
701
702ZEND_API void multi_convert_to_string_ex(int argc, ...) /* {{{ */
703{
704    zval *arg;
705    va_list ap;
706
707    va_start(ap, argc);
708
709    while (argc--) {
710        arg = va_arg(ap, zval *);
711        convert_to_string_ex(arg);
712    }
713
714    va_end(ap);
715}
716/* }}} */
717
718ZEND_API zend_long ZEND_FASTCALL _zval_get_long_func(zval *op) /* {{{ */
719{
720try_again:
721    switch (Z_TYPE_P(op)) {
722        case IS_NULL:
723        case IS_FALSE:
724            return 0;
725        case IS_TRUE:
726            return 1;
727        case IS_RESOURCE:
728            return Z_RES_HANDLE_P(op);
729        case IS_LONG:
730            return Z_LVAL_P(op);
731        case IS_DOUBLE:
732            return zend_dval_to_lval(Z_DVAL_P(op));
733        case IS_STRING:
734            return ZEND_STRTOL(Z_STRVAL_P(op), NULL, 10);
735        case IS_ARRAY:
736            return zend_hash_num_elements(Z_ARRVAL_P(op)) ? 1 : 0;
737        case IS_OBJECT:
738            {
739                zval dst;
740                convert_object_to_type(op, &dst, IS_LONG, convert_to_long);
741                if (Z_TYPE(dst) == IS_LONG) {
742                    return Z_LVAL(dst);
743                } else {
744                    return 1;
745                }
746            }
747        case IS_REFERENCE:
748            op = Z_REFVAL_P(op);
749            goto try_again;
750        EMPTY_SWITCH_DEFAULT_CASE()
751    }
752    return 0;
753}
754/* }}} */
755
756ZEND_API double ZEND_FASTCALL _zval_get_double_func(zval *op) /* {{{ */
757{
758try_again:
759    switch (Z_TYPE_P(op)) {
760        case IS_NULL:
761        case IS_FALSE:
762            return 0.0;
763        case IS_TRUE:
764            return 1.0;
765        case IS_RESOURCE:
766            return (double) Z_RES_HANDLE_P(op);
767        case IS_LONG:
768            return (double) Z_LVAL_P(op);
769        case IS_DOUBLE:
770            return Z_DVAL_P(op);
771        case IS_STRING:
772            return zend_strtod(Z_STRVAL_P(op), NULL);
773        case IS_ARRAY:
774            return zend_hash_num_elements(Z_ARRVAL_P(op)) ? 1.0 : 0.0;
775        case IS_OBJECT:
776            {
777                zval dst;
778                convert_object_to_type(op, &dst, IS_DOUBLE, convert_to_double);
779
780                if (Z_TYPE(dst) == IS_DOUBLE) {
781                    return Z_DVAL(dst);
782                } else {
783                    return 1.0;
784                }
785            }
786        case IS_REFERENCE:
787            op = Z_REFVAL_P(op);
788            goto try_again;
789        EMPTY_SWITCH_DEFAULT_CASE()
790    }
791    return 0.0;
792}
793/* }}} */
794
795ZEND_API zend_string* ZEND_FASTCALL _zval_get_string_func(zval *op) /* {{{ */
796{
797try_again:
798    switch (Z_TYPE_P(op)) {
799        case IS_UNDEF:
800        case IS_NULL:
801        case IS_FALSE:
802            return ZSTR_EMPTY_ALLOC();
803        case IS_TRUE:
804            if (CG(one_char_string)['1']) {
805                return CG(one_char_string)['1'];
806            } else {
807                return zend_string_init("1", 1, 0);
808            }
809        case IS_RESOURCE: {
810            char buf[sizeof("Resource id #") + MAX_LENGTH_OF_LONG];
811            int len;
812
813            len = snprintf(buf, sizeof(buf), "Resource id #" ZEND_LONG_FMT, (zend_long)Z_RES_HANDLE_P(op));
814            return zend_string_init(buf, len, 0);
815        }
816        case IS_LONG: {
817            return zend_long_to_str(Z_LVAL_P(op));
818        }
819        case IS_DOUBLE: {
820            return zend_strpprintf(0, "%.*G", (int) EG(precision), Z_DVAL_P(op));
821        }
822        case IS_ARRAY:
823            zend_error(E_NOTICE, "Array to string conversion");
824            return zend_string_init("Array", sizeof("Array")-1, 0);
825        case IS_OBJECT: {
826            zval tmp;
827            if (Z_OBJ_HT_P(op)->cast_object) {
828                if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, IS_STRING) == SUCCESS) {
829                    return Z_STR(tmp);
830                }
831            } else if (Z_OBJ_HT_P(op)->get) {
832                zval *z = Z_OBJ_HT_P(op)->get(op, &tmp);
833                if (Z_TYPE_P(z) != IS_OBJECT) {
834                    zend_string *str = zval_get_string(z);
835                    zval_ptr_dtor(z);
836                    return str;
837                }
838                zval_ptr_dtor(z);
839            }
840            zend_error(EG(exception) ? E_ERROR : E_RECOVERABLE_ERROR, "Object of class %s could not be converted to string", ZSTR_VAL(Z_OBJCE_P(op)->name));
841            return ZSTR_EMPTY_ALLOC();
842        }
843        case IS_REFERENCE:
844            op = Z_REFVAL_P(op);
845            goto try_again;
846        case IS_STRING:
847            return zend_string_copy(Z_STR_P(op));
848        EMPTY_SWITCH_DEFAULT_CASE()
849    }
850    return NULL;
851}
852/* }}} */
853
854ZEND_API int ZEND_FASTCALL add_function(zval *result, zval *op1, zval *op2) /* {{{ */
855{
856    zval op1_copy, op2_copy;
857    int converted = 0;
858
859    while (1) {
860        switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
861            case TYPE_PAIR(IS_LONG, IS_LONG): {
862                zend_long lval = Z_LVAL_P(op1) + Z_LVAL_P(op2);
863
864                /* check for overflow by comparing sign bits */
865                if ((Z_LVAL_P(op1) & LONG_SIGN_MASK) == (Z_LVAL_P(op2) & LONG_SIGN_MASK)
866                    && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {
867
868                    ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2));
869                } else {
870                    ZVAL_LONG(result, lval);
871                }
872                return SUCCESS;
873            }
874
875            case TYPE_PAIR(IS_LONG, IS_DOUBLE):
876                ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2));
877                return SUCCESS;
878
879            case TYPE_PAIR(IS_DOUBLE, IS_LONG):
880                ZVAL_DOUBLE(result, Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2)));
881                return SUCCESS;
882
883            case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
884                ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2));
885                return SUCCESS;
886
887            case TYPE_PAIR(IS_ARRAY, IS_ARRAY):
888                if ((result == op1) && (result == op2)) {
889                    /* $a += $a */
890                    return SUCCESS;
891                }
892                if (result != op1) {
893                    ZVAL_DUP(result, op1);
894                }
895                zend_hash_merge(Z_ARRVAL_P(result), Z_ARRVAL_P(op2), zval_add_ref, 0);
896                return SUCCESS;
897
898            default:
899                if (Z_ISREF_P(op1)) {
900                    op1 = Z_REFVAL_P(op1);
901                } else if (Z_ISREF_P(op2)) {
902                    op2 = Z_REFVAL_P(op2);
903                } else if (!converted) {
904                    ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_ADD, add_function);
905
906                    zendi_convert_scalar_to_number(op1, op1_copy, result);
907                    zendi_convert_scalar_to_number(op2, op2_copy, result);
908                    converted = 1;
909                } else {
910                    zend_throw_error(NULL, "Unsupported operand types");
911                    return FAILURE; /* unknown datatype */
912                }
913        }
914    }
915}
916/* }}} */
917
918ZEND_API int ZEND_FASTCALL sub_function(zval *result, zval *op1, zval *op2) /* {{{ */
919{
920    zval op1_copy, op2_copy;
921    int converted = 0;
922
923    while (1) {
924        switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
925            case TYPE_PAIR(IS_LONG, IS_LONG): {
926                zend_long lval = Z_LVAL_P(op1) - Z_LVAL_P(op2);
927
928                /* check for overflow by comparing sign bits */
929                if ((Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(op2) & LONG_SIGN_MASK)
930                    && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {
931
932                    ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2));
933                } else {
934                    ZVAL_LONG(result, lval);
935                }
936                return SUCCESS;
937
938            }
939            case TYPE_PAIR(IS_LONG, IS_DOUBLE):
940                ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2));
941                return SUCCESS;
942
943            case TYPE_PAIR(IS_DOUBLE, IS_LONG):
944                ZVAL_DOUBLE(result, Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2)));
945                return SUCCESS;
946
947            case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
948                ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2));
949                return SUCCESS;
950
951            default:
952                if (Z_ISREF_P(op1)) {
953                    op1 = Z_REFVAL_P(op1);
954                } else if (Z_ISREF_P(op2)) {
955                    op2 = Z_REFVAL_P(op2);
956                } else if (!converted) {
957                    ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SUB, sub_function);
958
959                    zendi_convert_scalar_to_number(op1, op1_copy, result);
960                    zendi_convert_scalar_to_number(op2, op2_copy, result);
961                    converted = 1;
962                } else {
963                    zend_throw_error(NULL, "Unsupported operand types");
964                    return FAILURE; /* unknown datatype */
965                }
966        }
967    }
968}
969/* }}} */
970
971ZEND_API int ZEND_FASTCALL mul_function(zval *result, zval *op1, zval *op2) /* {{{ */
972{
973    zval op1_copy, op2_copy;
974    int converted = 0;
975
976    while (1) {
977        switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
978            case TYPE_PAIR(IS_LONG, IS_LONG): {
979                zend_long overflow;
980
981                ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1),Z_LVAL_P(op2), Z_LVAL_P(result),Z_DVAL_P(result),overflow);
982                Z_TYPE_INFO_P(result) = overflow ? IS_DOUBLE : IS_LONG;
983                return SUCCESS;
984
985            }
986            case TYPE_PAIR(IS_LONG, IS_DOUBLE):
987                ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) * Z_DVAL_P(op2));
988                return SUCCESS;
989
990            case TYPE_PAIR(IS_DOUBLE, IS_LONG):
991                ZVAL_DOUBLE(result, Z_DVAL_P(op1) * ((double)Z_LVAL_P(op2)));
992                return SUCCESS;
993
994            case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
995                ZVAL_DOUBLE(result, Z_DVAL_P(op1) * Z_DVAL_P(op2));
996                return SUCCESS;
997
998            default:
999                if (Z_ISREF_P(op1)) {
1000                    op1 = Z_REFVAL_P(op1);
1001                } else if (Z_ISREF_P(op2)) {
1002                    op2 = Z_REFVAL_P(op2);
1003                } else if (!converted) {
1004                    ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_MUL, mul_function);
1005
1006                    zendi_convert_scalar_to_number(op1, op1_copy, result);
1007                    zendi_convert_scalar_to_number(op2, op2_copy, result);
1008                    converted = 1;
1009                } else {
1010                    zend_throw_error(NULL, "Unsupported operand types");
1011                    return FAILURE; /* unknown datatype */
1012                }
1013        }
1014    }
1015}
1016/* }}} */
1017
1018ZEND_API int ZEND_FASTCALL pow_function(zval *result, zval *op1, zval *op2) /* {{{ */
1019{
1020    zval op1_copy, op2_copy;
1021    int converted = 0;
1022
1023    while (1) {
1024        switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
1025            case TYPE_PAIR(IS_LONG, IS_LONG):
1026                if (Z_LVAL_P(op2) >= 0) {
1027                    zend_long l1 = 1, l2 = Z_LVAL_P(op1), i = Z_LVAL_P(op2);
1028
1029                    if (i == 0) {
1030                        ZVAL_LONG(result, 1L);
1031                        return SUCCESS;
1032                    } else if (l2 == 0) {
1033                        ZVAL_LONG(result, 0);
1034                        return SUCCESS;
1035                    }
1036
1037                    while (i >= 1) {
1038                        zend_long overflow;
1039                        double dval = 0.0;
1040
1041                        if (i % 2) {
1042                            --i;
1043                            ZEND_SIGNED_MULTIPLY_LONG(l1, l2, l1, dval, overflow);
1044                            if (overflow) {
1045                                ZVAL_DOUBLE(result, dval * pow(l2, i));
1046                                return SUCCESS;
1047                            }
1048                        } else {
1049                            i /= 2;
1050                            ZEND_SIGNED_MULTIPLY_LONG(l2, l2, l2, dval, overflow);
1051                            if (overflow) {
1052                                ZVAL_DOUBLE(result, (double)l1 * pow(dval, i));
1053                                return SUCCESS;
1054                            }
1055                        }
1056                    }
1057                    /* i == 0 */
1058                    ZVAL_LONG(result, l1);
1059                } else {
1060                    ZVAL_DOUBLE(result, pow((double)Z_LVAL_P(op1), (double)Z_LVAL_P(op2)));
1061                }
1062                return SUCCESS;
1063
1064            case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1065                ZVAL_DOUBLE(result, pow((double)Z_LVAL_P(op1), Z_DVAL_P(op2)));
1066                return SUCCESS;
1067
1068            case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1069                ZVAL_DOUBLE(result, pow(Z_DVAL_P(op1), (double)Z_LVAL_P(op2)));
1070                return SUCCESS;
1071
1072            case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1073                ZVAL_DOUBLE(result, pow(Z_DVAL_P(op1), Z_DVAL_P(op2)));
1074                return SUCCESS;
1075
1076            default:
1077                if (Z_ISREF_P(op1)) {
1078                    op1 = Z_REFVAL_P(op1);
1079                } else if (Z_ISREF_P(op2)) {
1080                    op2 = Z_REFVAL_P(op2);
1081                } else if (!converted) {
1082                    ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_POW, pow_function);
1083
1084                    if (Z_TYPE_P(op1) == IS_ARRAY) {
1085                        ZVAL_LONG(result, 0);
1086                        return SUCCESS;
1087                    } else {
1088                        zendi_convert_scalar_to_number(op1, op1_copy, result);
1089                    }
1090                    if (Z_TYPE_P(op2) == IS_ARRAY) {
1091                        ZVAL_LONG(result, 1L);
1092                        return SUCCESS;
1093                    } else {
1094                        zendi_convert_scalar_to_number(op2, op2_copy, result);
1095                    }
1096                    converted = 1;
1097                } else {
1098                    zend_throw_error(NULL, "Unsupported operand types");
1099                    return FAILURE;
1100                }
1101        }
1102    }
1103}
1104/* }}} */
1105
1106ZEND_API int ZEND_FASTCALL div_function(zval *result, zval *op1, zval *op2) /* {{{ */
1107{
1108    zval op1_copy, op2_copy;
1109    int converted = 0;
1110
1111    while (1) {
1112        switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
1113            case TYPE_PAIR(IS_LONG, IS_LONG):
1114                if (Z_LVAL_P(op2) == 0) {
1115                    zend_error(E_WARNING, "Division by zero");
1116                    ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1) / (double) Z_LVAL_P(op2)));
1117                    return SUCCESS;
1118                } else if (Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == ZEND_LONG_MIN) {
1119                    /* Prevent overflow error/crash */
1120                    ZVAL_DOUBLE(result, (double) ZEND_LONG_MIN / -1);
1121                    return SUCCESS;
1122                }
1123                if (Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0) { /* integer */
1124                    ZVAL_LONG(result, Z_LVAL_P(op1) / Z_LVAL_P(op2));
1125                } else {
1126                    ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1)) / Z_LVAL_P(op2));
1127                }
1128                return SUCCESS;
1129
1130            case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1131                if (Z_LVAL_P(op2) == 0) {
1132                    zend_error(E_WARNING, "Division by zero");
1133                }
1134                ZVAL_DOUBLE(result, Z_DVAL_P(op1) / (double)Z_LVAL_P(op2));
1135                return SUCCESS;
1136
1137            case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1138                if (Z_DVAL_P(op2) == 0) {
1139                    zend_error(E_WARNING, "Division by zero");
1140                }
1141                ZVAL_DOUBLE(result, (double)Z_LVAL_P(op1) / Z_DVAL_P(op2));
1142                return SUCCESS;
1143
1144            case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1145                if (Z_DVAL_P(op2) == 0) {
1146                    zend_error(E_WARNING, "Division by zero");
1147                }
1148                ZVAL_DOUBLE(result, Z_DVAL_P(op1) / Z_DVAL_P(op2));
1149                return SUCCESS;
1150
1151            default:
1152                if (Z_ISREF_P(op1)) {
1153                    op1 = Z_REFVAL_P(op1);
1154                } else if (Z_ISREF_P(op2)) {
1155                    op2 = Z_REFVAL_P(op2);
1156                } else if (!converted) {
1157                    ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_DIV, div_function);
1158
1159                    zendi_convert_scalar_to_number(op1, op1_copy, result);
1160                    zendi_convert_scalar_to_number(op2, op2_copy, result);
1161                    converted = 1;
1162                } else {
1163                    zend_throw_error(NULL, "Unsupported operand types");
1164                    return FAILURE; /* unknown datatype */
1165                }
1166        }
1167    }
1168}
1169/* }}} */
1170
1171ZEND_API int ZEND_FASTCALL mod_function(zval *result, zval *op1, zval *op2) /* {{{ */
1172{
1173    zend_long op1_lval, op2_lval;
1174
1175    convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_MOD, mod_function);
1176
1177    if (op1 == result) {
1178        zval_dtor(result);
1179    }
1180
1181    if (op2_lval == 0) {
1182        /* modulus by zero */
1183        if (EG(current_execute_data) && !CG(in_compilation)) {
1184            zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Modulo by zero");
1185        } else {
1186            zend_error_noreturn(E_ERROR, "Modulo by zero");
1187        }
1188        ZVAL_UNDEF(result);
1189        return FAILURE;
1190    }
1191
1192    if (op2_lval == -1) {
1193        /* Prevent overflow error/crash if op1==LONG_MIN */
1194        ZVAL_LONG(result, 0);
1195        return SUCCESS;
1196    }
1197
1198    ZVAL_LONG(result, op1_lval % op2_lval);
1199    return SUCCESS;
1200}
1201/* }}} */
1202
1203ZEND_API int ZEND_FASTCALL boolean_xor_function(zval *result, zval *op1, zval *op2) /* {{{ */
1204{
1205    int op1_val, op2_val;
1206
1207    do {
1208        if (Z_TYPE_P(op1) == IS_FALSE) {
1209            op1_val = 0;
1210        } else if (EXPECTED(Z_TYPE_P(op1) == IS_TRUE)) {
1211            op1_val = 1;
1212        } else {
1213            if (Z_ISREF_P(op1)) {
1214                op1 = Z_REFVAL_P(op1);
1215                if (Z_TYPE_P(op1) == IS_FALSE) {
1216                    op1_val = 0;
1217                    break;
1218                } else if (EXPECTED(Z_TYPE_P(op1) == IS_TRUE)) {
1219                    op1_val = 1;
1220                    break;
1221                }
1222            }
1223            ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BOOL_XOR, boolean_xor_function);
1224            op1_val = zval_is_true(op1);
1225        }
1226    } while (0);
1227    do {
1228        if (Z_TYPE_P(op2) == IS_FALSE) {
1229            op2_val = 0;
1230        } else if (EXPECTED(Z_TYPE_P(op2) == IS_TRUE)) {
1231            op2_val = 1;
1232        } else {
1233            if (Z_ISREF_P(op2)) {
1234                op2 = Z_REFVAL_P(op2);
1235                if (Z_TYPE_P(op2) == IS_FALSE) {
1236                    op2_val = 0;
1237                    break;
1238                } else if (EXPECTED(Z_TYPE_P(op2) == IS_TRUE)) {
1239                    op2_val = 1;
1240                    break;
1241                }
1242            }
1243            ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BOOL_XOR);
1244            op2_val = zval_is_true(op2);
1245        }
1246    } while (0);
1247
1248    ZVAL_BOOL(result, op1_val ^ op2_val);
1249    return SUCCESS;
1250}
1251/* }}} */
1252
1253ZEND_API int ZEND_FASTCALL boolean_not_function(zval *result, zval *op1) /* {{{ */
1254{
1255    if (Z_TYPE_P(op1) < IS_TRUE) {
1256        ZVAL_TRUE(result);
1257    } else if (EXPECTED(Z_TYPE_P(op1) == IS_TRUE)) {
1258        ZVAL_FALSE(result);
1259    } else {
1260        if (Z_ISREF_P(op1)) {
1261            op1 = Z_REFVAL_P(op1);
1262            if (Z_TYPE_P(op1) < IS_TRUE) {
1263                ZVAL_TRUE(result);
1264                return SUCCESS;
1265            } else if (EXPECTED(Z_TYPE_P(op1) == IS_TRUE)) {
1266                ZVAL_FALSE(result);
1267                return SUCCESS;
1268            }
1269        }
1270        ZEND_TRY_UNARY_OBJECT_OPERATION(ZEND_BOOL_NOT);
1271
1272        ZVAL_BOOL(result, !zval_is_true(op1));
1273    }
1274    return SUCCESS;
1275}
1276/* }}} */
1277
1278ZEND_API int ZEND_FASTCALL bitwise_not_function(zval *result, zval *op1) /* {{{ */
1279{
1280try_again:
1281    switch (Z_TYPE_P(op1)) {
1282        case IS_LONG:
1283            ZVAL_LONG(result, ~Z_LVAL_P(op1));
1284            return SUCCESS;
1285        case IS_DOUBLE:
1286            ZVAL_LONG(result, ~zend_dval_to_lval(Z_DVAL_P(op1)));
1287            return SUCCESS;
1288        case IS_STRING: {
1289            size_t i;
1290
1291            if (Z_STRLEN_P(op1) == 1) {
1292                zend_uchar not = (zend_uchar) ~*Z_STRVAL_P(op1);
1293                if (CG(one_char_string)[not]) {
1294                    ZVAL_INTERNED_STR(result, CG(one_char_string)[not]);
1295                } else {
1296                    ZVAL_NEW_STR(result, zend_string_init((char *) &not, 1, 0));
1297                }
1298            } else {
1299                ZVAL_NEW_STR(result, zend_string_alloc(Z_STRLEN_P(op1), 0));
1300                for (i = 0; i < Z_STRLEN_P(op1); i++) {
1301                    Z_STRVAL_P(result)[i] = ~Z_STRVAL_P(op1)[i];
1302                }
1303                Z_STRVAL_P(result)[i] = 0;
1304            }
1305            return SUCCESS;
1306        }
1307        case IS_REFERENCE:
1308            op1 = Z_REFVAL_P(op1);
1309            goto try_again;
1310        default:
1311            ZEND_TRY_UNARY_OBJECT_OPERATION(ZEND_BW_NOT);
1312
1313            zend_throw_error(NULL, "Unsupported operand types");
1314            return FAILURE;
1315    }
1316}
1317/* }}} */
1318
1319ZEND_API int ZEND_FASTCALL bitwise_or_function(zval *result, zval *op1, zval *op2) /* {{{ */
1320{
1321    zend_long op1_lval, op2_lval;
1322
1323    if (EXPECTED(Z_TYPE_P(op1) == IS_LONG) && EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
1324        ZVAL_LONG(result, Z_LVAL_P(op1) | Z_LVAL_P(op2));
1325        return SUCCESS;
1326    }
1327
1328    ZVAL_DEREF(op1);
1329    ZVAL_DEREF(op2);
1330
1331    if (Z_TYPE_P(op1) == IS_STRING && EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
1332        zval *longer, *shorter;
1333        zend_string *str;
1334        size_t i;
1335
1336        if (EXPECTED(Z_STRLEN_P(op1) >= Z_STRLEN_P(op2))) {
1337            if (EXPECTED(Z_STRLEN_P(op1) == Z_STRLEN_P(op2)) && Z_STRLEN_P(op1) == 1) {
1338                zend_uchar or = (zend_uchar) (*Z_STRVAL_P(op1) | *Z_STRVAL_P(op2));
1339                if (CG(one_char_string)[or]) {
1340                    ZVAL_INTERNED_STR(result, CG(one_char_string)[or]);
1341                } else {
1342                    ZVAL_NEW_STR(result, zend_string_init((char *) &or, 1, 0));
1343                }
1344                return SUCCESS;
1345            }
1346            longer = op1;
1347            shorter = op2;
1348        } else {
1349            longer = op2;
1350            shorter = op1;
1351        }
1352
1353        str = zend_string_alloc(Z_STRLEN_P(longer), 0);
1354        for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1355            ZSTR_VAL(str)[i] = Z_STRVAL_P(longer)[i] | Z_STRVAL_P(shorter)[i];
1356        }
1357        memcpy(ZSTR_VAL(str) + i, Z_STRVAL_P(longer) + i, Z_STRLEN_P(longer) - i + 1);
1358        if (result==op1) {
1359            zend_string_release(Z_STR_P(result));
1360        }
1361        ZVAL_NEW_STR(result, str);
1362        return SUCCESS;
1363    }
1364
1365    if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
1366        ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_OR, bitwise_or_function);
1367        op1_lval = _zval_get_long_func(op1);
1368    } else {
1369        op1_lval = Z_LVAL_P(op1);
1370    }
1371    if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {
1372        ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_OR);
1373        op2_lval = _zval_get_long_func(op2);
1374    } else {
1375        op2_lval = Z_LVAL_P(op2);
1376    }
1377
1378    if (op1 == result) {
1379        zval_dtor(result);
1380    }
1381    ZVAL_LONG(result, op1_lval | op2_lval);
1382    return SUCCESS;
1383}
1384/* }}} */
1385
1386ZEND_API int ZEND_FASTCALL bitwise_and_function(zval *result, zval *op1, zval *op2) /* {{{ */
1387{
1388    zend_long op1_lval, op2_lval;
1389
1390    if (EXPECTED(Z_TYPE_P(op1) == IS_LONG) && EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
1391        ZVAL_LONG(result, Z_LVAL_P(op1) & Z_LVAL_P(op2));
1392        return SUCCESS;
1393    }
1394
1395    ZVAL_DEREF(op1);
1396    ZVAL_DEREF(op2);
1397
1398    if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1399        zval *longer, *shorter;
1400        zend_string *str;
1401        size_t i;
1402
1403        if (EXPECTED(Z_STRLEN_P(op1) >= Z_STRLEN_P(op2))) {
1404            if (EXPECTED(Z_STRLEN_P(op1) == Z_STRLEN_P(op2)) && Z_STRLEN_P(op1) == 1) {
1405                zend_uchar and = (zend_uchar) (*Z_STRVAL_P(op1) & *Z_STRVAL_P(op2));
1406                if (CG(one_char_string)[and]) {
1407                    ZVAL_INTERNED_STR(result, CG(one_char_string)[and]);
1408                } else {
1409                    ZVAL_NEW_STR(result, zend_string_init((char *) &and, 1, 0));
1410                }
1411                return SUCCESS;
1412            }
1413            longer = op1;
1414            shorter = op2;
1415        } else {
1416            longer = op2;
1417            shorter = op1;
1418        }
1419
1420        str = zend_string_alloc(Z_STRLEN_P(shorter), 0);
1421        for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1422            ZSTR_VAL(str)[i] = Z_STRVAL_P(shorter)[i] & Z_STRVAL_P(longer)[i];
1423        }
1424        ZSTR_VAL(str)[i] = 0;
1425        if (result==op1) {
1426            zend_string_release(Z_STR_P(result));
1427        }
1428        ZVAL_NEW_STR(result, str);
1429        return SUCCESS;
1430    }
1431
1432    if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
1433        ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_AND, bitwise_and_function);
1434        op1_lval = _zval_get_long_func(op1);
1435    } else {
1436        op1_lval = Z_LVAL_P(op1);
1437    }
1438    if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {
1439        ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_AND);
1440        op2_lval = _zval_get_long_func(op2);
1441    } else {
1442        op2_lval = Z_LVAL_P(op2);
1443    }
1444
1445    if (op1 == result) {
1446        zval_dtor(result);
1447    }
1448    ZVAL_LONG(result, op1_lval & op2_lval);
1449    return SUCCESS;
1450}
1451/* }}} */
1452
1453ZEND_API int ZEND_FASTCALL bitwise_xor_function(zval *result, zval *op1, zval *op2) /* {{{ */
1454{
1455    zend_long op1_lval, op2_lval;
1456
1457    if (EXPECTED(Z_TYPE_P(op1) == IS_LONG) && EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
1458        ZVAL_LONG(result, Z_LVAL_P(op1) ^ Z_LVAL_P(op2));
1459        return SUCCESS;
1460    }
1461
1462    ZVAL_DEREF(op1);
1463    ZVAL_DEREF(op2);
1464
1465    if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1466        zval *longer, *shorter;
1467        zend_string *str;
1468        size_t i;
1469
1470        if (EXPECTED(Z_STRLEN_P(op1) >= Z_STRLEN_P(op2))) {
1471            if (EXPECTED(Z_STRLEN_P(op1) == Z_STRLEN_P(op2)) && Z_STRLEN_P(op1) == 1) {
1472                zend_uchar xor = (zend_uchar) (*Z_STRVAL_P(op1) ^ *Z_STRVAL_P(op2));
1473                if (CG(one_char_string)[xor]) {
1474                    ZVAL_INTERNED_STR(result, CG(one_char_string)[xor]);
1475                } else {
1476                    ZVAL_NEW_STR(result, zend_string_init((char *) &xor, 1, 0));
1477                }
1478                return SUCCESS;
1479            }
1480            longer = op1;
1481            shorter = op2;
1482        } else {
1483            longer = op2;
1484            shorter = op1;
1485        }
1486
1487        str = zend_string_alloc(Z_STRLEN_P(shorter), 0);
1488        for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1489            ZSTR_VAL(str)[i] = Z_STRVAL_P(shorter)[i] ^ Z_STRVAL_P(longer)[i];
1490        }
1491        ZSTR_VAL(str)[i] = 0;
1492        if (result==op1) {
1493            zend_string_release(Z_STR_P(result));
1494        }
1495        ZVAL_NEW_STR(result, str);
1496        return SUCCESS;
1497    }
1498
1499    if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
1500        ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_XOR, bitwise_xor_function);
1501        op1_lval = _zval_get_long_func(op1);
1502    } else {
1503        op1_lval = Z_LVAL_P(op1);
1504    }
1505    if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) {
1506        ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_XOR);
1507        op2_lval = _zval_get_long_func(op2);
1508    } else {
1509        op2_lval = Z_LVAL_P(op2);
1510    }
1511
1512    if (op1 == result) {
1513        zval_dtor(result);
1514    }
1515    ZVAL_LONG(result, op1_lval ^ op2_lval);
1516    return SUCCESS;
1517}
1518/* }}} */
1519
1520ZEND_API int ZEND_FASTCALL shift_left_function(zval *result, zval *op1, zval *op2) /* {{{ */
1521{
1522    zend_long op1_lval, op2_lval;
1523
1524    convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_SL, shift_left_function);
1525
1526    if (op1 == result) {
1527        zval_dtor(result);
1528    }
1529
1530    /* prevent wrapping quirkiness on some processors where << 64 + x == << x */
1531    if (UNEXPECTED((zend_ulong)op2_lval >= SIZEOF_ZEND_LONG * 8)) {
1532        if (EXPECTED(op2_lval > 0)) {
1533            ZVAL_LONG(result, 0);
1534            return SUCCESS;
1535        } else {
1536            if (EG(current_execute_data) && !CG(in_compilation)) {
1537                zend_throw_exception_ex(zend_ce_arithmetic_error, 0, "Bit shift by negative number");
1538            } else {
1539                zend_error_noreturn(E_ERROR, "Bit shift by negative number");
1540            }
1541            ZVAL_UNDEF(result);
1542            return FAILURE;
1543        }
1544    }
1545
1546    ZVAL_LONG(result, op1_lval << op2_lval);
1547    return SUCCESS;
1548}
1549/* }}} */
1550
1551ZEND_API int ZEND_FASTCALL shift_right_function(zval *result, zval *op1, zval *op2) /* {{{ */
1552{
1553    zend_long op1_lval, op2_lval;
1554
1555    convert_op1_op2_long(op1, op1_lval, op2, op2_lval, ZEND_SR, shift_right_function);
1556
1557    if (op1 == result) {
1558        zval_dtor(result);
1559    }
1560
1561    /* prevent wrapping quirkiness on some processors where >> 64 + x == >> x */
1562    if (UNEXPECTED((zend_ulong)op2_lval >= SIZEOF_ZEND_LONG * 8)) {
1563        if (EXPECTED(op2_lval > 0)) {
1564            ZVAL_LONG(result, (op1_lval < 0) ? -1 : 0);
1565            return SUCCESS;
1566        } else {
1567            if (EG(current_execute_data) && !CG(in_compilation)) {
1568                zend_throw_exception_ex(zend_ce_arithmetic_error, 0, "Bit shift by negative number");
1569            } else {
1570                zend_error_noreturn(E_ERROR, "Bit shift by negative number");
1571            }
1572            ZVAL_UNDEF(result);
1573            return FAILURE;
1574        }
1575    }
1576
1577    ZVAL_LONG(result, op1_lval >> op2_lval);
1578    return SUCCESS;
1579}
1580/* }}} */
1581
1582ZEND_API int ZEND_FASTCALL concat_function(zval *result, zval *op1, zval *op2) /* {{{ */
1583{
1584    zval op1_copy, op2_copy;
1585    int use_copy1 = 0, use_copy2 = 0;
1586
1587    do {
1588        if (UNEXPECTED(Z_TYPE_P(op1) != IS_STRING)) {
1589            if (Z_ISREF_P(op1)) {
1590                op1 = Z_REFVAL_P(op1);
1591                if (Z_TYPE_P(op1) == IS_STRING) break;
1592            }
1593            ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_CONCAT, concat_function);
1594            use_copy1 = zend_make_printable_zval(op1, &op1_copy);
1595            if (use_copy1) {
1596                /* We have created a converted copy of op1. Therefore, op1 won't become the result so
1597                 * we have to free it.
1598                 */
1599                if (result == op1) {
1600                    zval_dtor(op1);
1601                    if (UNEXPECTED(op1 == op2)) {
1602                        op2 = &op1_copy;
1603                    }
1604                }
1605                op1 = &op1_copy;
1606            }
1607        }
1608    } while (0);
1609    do {
1610        if (UNEXPECTED(Z_TYPE_P(op2) != IS_STRING)) {
1611            if (Z_ISREF_P(op2)) {
1612                op2 = Z_REFVAL_P(op2);
1613                if (Z_TYPE_P(op2) == IS_STRING) break;
1614            }
1615            ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_CONCAT);
1616            use_copy2 = zend_make_printable_zval(op2, &op2_copy);
1617            if (use_copy2) {
1618                op2 = &op2_copy;
1619            }
1620        }
1621    } while (0);
1622
1623    {
1624        size_t op1_len = Z_STRLEN_P(op1);
1625        size_t op2_len = Z_STRLEN_P(op2);
1626        size_t result_len = op1_len + op2_len;
1627        zend_string *result_str;
1628
1629        if (UNEXPECTED(op1_len > SIZE_MAX - op2_len)) {
1630            zend_throw_error(NULL, "String size overflow");
1631            ZVAL_FALSE(result);
1632            return FAILURE;
1633        }
1634
1635        if (result == op1 && Z_REFCOUNTED_P(result)) {
1636            /* special case, perform operations on result */
1637            result_str = zend_string_extend(Z_STR_P(result), result_len, 0);
1638        } else {
1639            result_str = zend_string_alloc(result_len, 0);
1640            memcpy(ZSTR_VAL(result_str), Z_STRVAL_P(op1), op1_len);
1641        }
1642
1643        /* This has to happen first to account for the cases where result == op1 == op2 and
1644         * the realloc is done. In this case this line will also update Z_STRVAL_P(op2) to
1645         * point to the new string. The first op2_len bytes of result will still be the same. */
1646        ZVAL_NEW_STR(result, result_str);
1647
1648        memcpy(ZSTR_VAL(result_str) + op1_len, Z_STRVAL_P(op2), op2_len);
1649        ZSTR_VAL(result_str)[result_len] = '\0';
1650    }
1651
1652    if (UNEXPECTED(use_copy1)) {
1653        zval_dtor(op1);
1654    }
1655    if (UNEXPECTED(use_copy2)) {
1656        zval_dtor(op2);
1657    }
1658    return SUCCESS;
1659}
1660/* }}} */
1661
1662ZEND_API int string_compare_function_ex(zval *result, zval *op1, zval *op2, zend_bool case_insensitive) /* {{{ */
1663{
1664    zend_string *str1 = zval_get_string(op1);
1665    zend_string *str2 = zval_get_string(op2);
1666
1667    if (case_insensitive) {
1668        ZVAL_LONG(result, zend_binary_strcasecmp_l(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str1)));
1669    } else {
1670        ZVAL_LONG(result, zend_binary_strcmp(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str2)));
1671    }
1672
1673    zend_string_release(str1);
1674    zend_string_release(str2);
1675    return SUCCESS;
1676}
1677/* }}} */
1678
1679ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2) /* {{{ */
1680{
1681    if (EXPECTED(Z_TYPE_P(op1) == IS_STRING) &&
1682        EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
1683        if (Z_STR_P(op1) == Z_STR_P(op2)) {
1684            ZVAL_LONG(result, 0);
1685        } else {
1686            ZVAL_LONG(result, zend_binary_strcmp(Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2)));
1687        }
1688    } else {
1689        zend_string *str1 = zval_get_string(op1);
1690        zend_string *str2 = zval_get_string(op2);
1691
1692        ZVAL_LONG(result, zend_binary_strcmp(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str2)));
1693
1694        zend_string_release(str1);
1695        zend_string_release(str2);
1696    }
1697    return SUCCESS;
1698}
1699/* }}} */
1700
1701ZEND_API int string_case_compare_function(zval *result, zval *op1, zval *op2) /* {{{ */
1702{
1703    if (EXPECTED(Z_TYPE_P(op1) == IS_STRING) &&
1704        EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
1705        if (Z_STR_P(op1) == Z_STR_P(op2)) {
1706            ZVAL_LONG(result, 0);
1707        } else {
1708            ZVAL_LONG(result, zend_binary_strcasecmp_l(Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2)));
1709        }
1710    } else {
1711        zend_string *str1 = zval_get_string(op1);
1712        zend_string *str2 = zval_get_string(op2);
1713
1714        ZVAL_LONG(result, zend_binary_strcasecmp_l(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str1)));
1715
1716        zend_string_release(str1);
1717        zend_string_release(str2);
1718    }
1719    return SUCCESS;
1720}
1721/* }}} */
1722
1723#if HAVE_STRCOLL
1724ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2) /* {{{ */
1725{
1726    zend_string *str1 = zval_get_string(op1);
1727    zend_string *str2 = zval_get_string(op2);
1728
1729    ZVAL_LONG(result, strcoll(ZSTR_VAL(str1), ZSTR_VAL(str2)));
1730
1731    zend_string_release(str1);
1732    zend_string_release(str2);
1733    return SUCCESS;
1734}
1735/* }}} */
1736#endif
1737
1738ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2) /* {{{ */
1739{
1740    double d1, d2;
1741
1742    d1 = zval_get_double(op1);
1743    d2 = zval_get_double(op2);
1744
1745    ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(d1 - d2));
1746
1747    return SUCCESS;
1748}
1749/* }}} */
1750
1751static inline void zend_free_obj_get_result(zval *op) /* {{{ */
1752{
1753    if (Z_REFCOUNTED_P(op)) {
1754        if (Z_REFCOUNT_P(op) == 0) {
1755            zval_dtor(op);
1756        } else {
1757            zval_ptr_dtor(op);
1758        }
1759    }
1760}
1761/* }}} */
1762
1763ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2) /* {{{ */
1764{
1765    int ret;
1766    int converted = 0;
1767    zval op1_copy, op2_copy;
1768    zval *op_free, tmp_free;
1769
1770    while (1) {
1771        switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
1772            case TYPE_PAIR(IS_LONG, IS_LONG):
1773                ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0));
1774                return SUCCESS;
1775
1776            case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1777                Z_DVAL_P(result) = Z_DVAL_P(op1) - (double)Z_LVAL_P(op2);
1778                ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1779                return SUCCESS;
1780
1781            case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1782                Z_DVAL_P(result) = (double)Z_LVAL_P(op1) - Z_DVAL_P(op2);
1783                ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1784                return SUCCESS;
1785
1786            case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1787                if (Z_DVAL_P(op1) == Z_DVAL_P(op2)) {
1788                    ZVAL_LONG(result, 0);
1789                } else {
1790                    Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2);
1791                    ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1792                }
1793                return SUCCESS;
1794
1795            case TYPE_PAIR(IS_ARRAY, IS_ARRAY):
1796                ZVAL_LONG(result, zend_compare_arrays(op1, op2));
1797                return SUCCESS;
1798
1799            case TYPE_PAIR(IS_NULL, IS_NULL):
1800            case TYPE_PAIR(IS_NULL, IS_FALSE):
1801            case TYPE_PAIR(IS_FALSE, IS_NULL):
1802            case TYPE_PAIR(IS_FALSE, IS_FALSE):
1803            case TYPE_PAIR(IS_TRUE, IS_TRUE):
1804                ZVAL_LONG(result, 0);
1805                return SUCCESS;
1806
1807            case TYPE_PAIR(IS_NULL, IS_TRUE):
1808                ZVAL_LONG(result, -1);
1809                return SUCCESS;
1810
1811            case TYPE_PAIR(IS_TRUE, IS_NULL):
1812                ZVAL_LONG(result, 1);
1813                return SUCCESS;
1814
1815            case TYPE_PAIR(IS_STRING, IS_STRING):
1816                if (Z_STR_P(op1) == Z_STR_P(op2)) {
1817                    ZVAL_LONG(result, 0);
1818                    return SUCCESS;
1819                }
1820                ZVAL_LONG(result, zendi_smart_strcmp(op1, op2));
1821                return SUCCESS;
1822
1823            case TYPE_PAIR(IS_NULL, IS_STRING):
1824                ZVAL_LONG(result, Z_STRLEN_P(op2) == 0 ? 0 : -1);
1825                return SUCCESS;
1826
1827            case TYPE_PAIR(IS_STRING, IS_NULL):
1828                ZVAL_LONG(result, Z_STRLEN_P(op1) == 0 ? 0 : 1);
1829                return SUCCESS;
1830
1831            case TYPE_PAIR(IS_OBJECT, IS_NULL):
1832                ZVAL_LONG(result, 1);
1833                return SUCCESS;
1834
1835            case TYPE_PAIR(IS_NULL, IS_OBJECT):
1836                ZVAL_LONG(result, -1);
1837                return SUCCESS;
1838
1839            default:
1840                if (Z_ISREF_P(op1)) {
1841                    op1 = Z_REFVAL_P(op1);
1842                    continue;
1843                } else if (Z_ISREF_P(op2)) {
1844                    op2 = Z_REFVAL_P(op2);
1845                    continue;
1846                }
1847
1848                if (Z_TYPE_P(op1) == IS_OBJECT && Z_OBJ_HANDLER_P(op1, compare)) {
1849                    return Z_OBJ_HANDLER_P(op1, compare)(result, op1, op2);
1850                } else if (Z_TYPE_P(op2) == IS_OBJECT && Z_OBJ_HANDLER_P(op2, compare)) {
1851                    return Z_OBJ_HANDLER_P(op2, compare)(result, op1, op2);
1852                }
1853
1854                if (Z_TYPE_P(op1) == IS_OBJECT && Z_TYPE_P(op2) == IS_OBJECT) {
1855                    if (Z_OBJ_P(op1) == Z_OBJ_P(op2)) {
1856                        /* object handles are identical, apparently this is the same object */
1857                        ZVAL_LONG(result, 0);
1858                        return SUCCESS;
1859                    }
1860                    if (Z_OBJ_HANDLER_P(op1, compare_objects) == Z_OBJ_HANDLER_P(op2, compare_objects)) {
1861                        ZVAL_LONG(result, Z_OBJ_HANDLER_P(op1, compare_objects)(op1, op2));
1862                        return SUCCESS;
1863                    }
1864                }
1865                if (Z_TYPE_P(op1) == IS_OBJECT) {
1866                    if (Z_OBJ_HT_P(op1)->get) {
1867                        zval rv;
1868                        op_free = Z_OBJ_HT_P(op1)->get(op1, &rv);
1869                        ret = compare_function(result, op_free, op2);
1870                        zend_free_obj_get_result(op_free);
1871                        return ret;
1872                    } else if (Z_TYPE_P(op2) != IS_OBJECT && Z_OBJ_HT_P(op1)->cast_object) {
1873                        ZVAL_UNDEF(&tmp_free);
1874                        if (Z_OBJ_HT_P(op1)->cast_object(op1, &tmp_free, ((Z_TYPE_P(op2) == IS_FALSE || Z_TYPE_P(op2) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(op2))) == FAILURE) {
1875                            ZVAL_LONG(result, 1);
1876                            zend_free_obj_get_result(&tmp_free);
1877                            return SUCCESS;
1878                        }
1879                        ret = compare_function(result, &tmp_free, op2);
1880                        zend_free_obj_get_result(&tmp_free);
1881                        return ret;
1882                    }
1883                }
1884                if (Z_TYPE_P(op2) == IS_OBJECT) {
1885                    if (Z_OBJ_HT_P(op2)->get) {
1886                        zval rv;
1887                        op_free = Z_OBJ_HT_P(op2)->get(op2, &rv);
1888                        ret = compare_function(result, op1, op_free);
1889                        zend_free_obj_get_result(op_free);
1890                        return ret;
1891                    } else if (Z_TYPE_P(op1) != IS_OBJECT && Z_OBJ_HT_P(op2)->cast_object) {
1892                        ZVAL_UNDEF(&tmp_free);
1893                        if (Z_OBJ_HT_P(op2)->cast_object(op2, &tmp_free, ((Z_TYPE_P(op1) == IS_FALSE || Z_TYPE_P(op1) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(op1))) == FAILURE) {
1894                            ZVAL_LONG(result, -1);
1895                            zend_free_obj_get_result(&tmp_free);
1896                            return SUCCESS;
1897                        }
1898                        ret = compare_function(result, op1, &tmp_free);
1899                        zend_free_obj_get_result(&tmp_free);
1900                        return ret;
1901                    } else if (Z_TYPE_P(op1) == IS_OBJECT) {
1902                        ZVAL_LONG(result, 1);
1903                        return SUCCESS;
1904                    }
1905                }
1906                if (!converted) {
1907                    if (Z_TYPE_P(op1) == IS_NULL || Z_TYPE_P(op1) == IS_FALSE) {
1908                        ZVAL_LONG(result, zval_is_true(op2) ? -1 : 0);
1909                        return SUCCESS;
1910                    } else if (Z_TYPE_P(op2) == IS_NULL || Z_TYPE_P(op2) == IS_FALSE) {
1911                        ZVAL_LONG(result, zval_is_true(op1) ? 1 : 0);
1912                        return SUCCESS;
1913                    } else if (Z_TYPE_P(op1) == IS_TRUE) {
1914                        ZVAL_LONG(result, zval_is_true(op2) ? 0 : 1);
1915                        return SUCCESS;
1916                    } else if (Z_TYPE_P(op2) == IS_TRUE) {
1917                        ZVAL_LONG(result, zval_is_true(op1) ? 0 : -1);
1918                        return SUCCESS;
1919                    } else {
1920                        zendi_convert_scalar_to_number(op1, op1_copy, result);
1921                        zendi_convert_scalar_to_number(op2, op2_copy, result);
1922                        converted = 1;
1923                    }
1924                } else if (Z_TYPE_P(op1)==IS_ARRAY) {
1925                    ZVAL_LONG(result, 1);
1926                    return SUCCESS;
1927                } else if (Z_TYPE_P(op2)==IS_ARRAY) {
1928                    ZVAL_LONG(result, -1);
1929                    return SUCCESS;
1930                } else if (Z_TYPE_P(op1)==IS_OBJECT) {
1931                    ZVAL_LONG(result, 1);
1932                    return SUCCESS;
1933                } else if (Z_TYPE_P(op2)==IS_OBJECT) {
1934                    ZVAL_LONG(result, -1);
1935                    return SUCCESS;
1936                } else {
1937                    ZVAL_LONG(result, 0);
1938                    return FAILURE;
1939                }
1940        }
1941    }
1942}
1943/* }}} */
1944
1945ZEND_API int zval_compare_function(zval *result, zval *op1, zval *op2) /* {{{ */
1946{
1947    return compare_function(result, op1, op2);
1948}
1949/* }}} */
1950
1951static int hash_zval_identical_function(zval *z1, zval *z2) /* {{{ */
1952{
1953    zval result;
1954
1955    /* is_identical_function() returns 1 in case of identity and 0 in case
1956     * of a difference;
1957     * whereas this comparison function is expected to return 0 on identity,
1958     * and non zero otherwise.
1959     */
1960    ZVAL_DEREF(z1);
1961    ZVAL_DEREF(z2);
1962    if (is_identical_function(&result, z1, z2)==FAILURE) {
1963        return 1;
1964    }
1965    return Z_TYPE(result) != IS_TRUE;
1966}
1967/* }}} */
1968
1969ZEND_API int ZEND_FASTCALL zend_is_identical(zval *op1, zval *op2) /* {{{ */
1970{
1971    if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) {
1972        return 0;
1973    }
1974    switch (Z_TYPE_P(op1)) {
1975        case IS_NULL:
1976        case IS_FALSE:
1977        case IS_TRUE:
1978            return 1;
1979        case IS_LONG:
1980            return (Z_LVAL_P(op1) == Z_LVAL_P(op2));
1981        case IS_RESOURCE:
1982            return (Z_RES_P(op1) == Z_RES_P(op2));
1983        case IS_DOUBLE:
1984            return (Z_DVAL_P(op1) == Z_DVAL_P(op2));
1985        case IS_STRING:
1986            return (Z_STR_P(op1) == Z_STR_P(op2) ||
1987                (Z_STRLEN_P(op1) == Z_STRLEN_P(op2) &&
1988                 memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1)) == 0));
1989        case IS_ARRAY:
1990            return (Z_ARRVAL_P(op1) == Z_ARRVAL_P(op2) ||
1991                zend_hash_compare(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2), (compare_func_t) hash_zval_identical_function, 1) == 0);
1992        case IS_OBJECT:
1993            return (Z_OBJ_P(op1) == Z_OBJ_P(op2) && Z_OBJ_HT_P(op1) == Z_OBJ_HT_P(op2));
1994        default:
1995            return 0;
1996    }
1997}
1998/* }}} */
1999
2000ZEND_API int ZEND_FASTCALL is_identical_function(zval *result, zval *op1, zval *op2) /* {{{ */
2001{
2002    ZVAL_BOOL(result, zend_is_identical(op1, op2));
2003    return SUCCESS;
2004}
2005/* }}} */
2006
2007ZEND_API int ZEND_FASTCALL is_not_identical_function(zval *result, zval *op1, zval *op2) /* {{{ */
2008{
2009    ZVAL_BOOL(result, !zend_is_identical(op1, op2));
2010    return SUCCESS;
2011}
2012/* }}} */
2013
2014ZEND_API int ZEND_FASTCALL is_equal_function(zval *result, zval *op1, zval *op2) /* {{{ */
2015{
2016    if (compare_function(result, op1, op2) == FAILURE) {
2017        return FAILURE;
2018    }
2019    ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
2020    return SUCCESS;
2021}
2022/* }}} */
2023
2024ZEND_API int ZEND_FASTCALL is_not_equal_function(zval *result, zval *op1, zval *op2) /* {{{ */
2025{
2026    if (compare_function(result, op1, op2) == FAILURE) {
2027        return FAILURE;
2028    }
2029    ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
2030    return SUCCESS;
2031}
2032/* }}} */
2033
2034ZEND_API int ZEND_FASTCALL is_smaller_function(zval *result, zval *op1, zval *op2) /* {{{ */
2035{
2036    if (compare_function(result, op1, op2) == FAILURE) {
2037        return FAILURE;
2038    }
2039    ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
2040    return SUCCESS;
2041}
2042/* }}} */
2043
2044ZEND_API int ZEND_FASTCALL is_smaller_or_equal_function(zval *result, zval *op1, zval *op2) /* {{{ */
2045{
2046    if (compare_function(result, op1, op2) == FAILURE) {
2047        return FAILURE;
2048    }
2049    ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
2050    return SUCCESS;
2051}
2052/* }}} */
2053
2054static zend_bool ZEND_FASTCALL instanceof_interface_only(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */
2055{
2056    uint32_t i;
2057
2058    for (i = 0; i < instance_ce->num_interfaces; i++) {
2059        if (instanceof_interface_only(instance_ce->interfaces[i], ce)) {
2060            return 1;
2061        }
2062    }
2063    return 0;
2064}
2065/* }}} */
2066
2067static zend_always_inline zend_bool instanceof_class(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */
2068{
2069    while (instance_ce) {
2070        if (instance_ce == ce) {
2071            return 1;
2072        }
2073        instance_ce = instance_ce->parent;
2074    }
2075    return 0;
2076}
2077/* }}} */
2078
2079static zend_bool ZEND_FASTCALL instanceof_interface(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */
2080{
2081    uint32_t i;
2082
2083    for (i = 0; i < instance_ce->num_interfaces; i++) {
2084        if (instanceof_interface(instance_ce->interfaces[i], ce)) {
2085            return 1;
2086        }
2087    }
2088    return instanceof_class(instance_ce, ce);
2089}
2090/* }}} */
2091
2092ZEND_API zend_bool ZEND_FASTCALL instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool interfaces_only) /* {{{ */
2093{
2094    if (ce->ce_flags & ZEND_ACC_INTERFACE) {
2095        if (!interfaces_only) {
2096            if (instanceof_interface_only(instance_ce, ce)) {
2097                return 1;
2098            }
2099        } else {
2100            return instanceof_interface(instance_ce, ce);
2101        }
2102    }
2103    if (!interfaces_only) {
2104        return instanceof_class(instance_ce, ce);
2105    }
2106    return 0;
2107}
2108/* }}} */
2109
2110ZEND_API zend_bool ZEND_FASTCALL instanceof_function(const zend_class_entry *instance_ce, const zend_class_entry *ce) /* {{{ */
2111{
2112    if (ce->ce_flags & ZEND_ACC_INTERFACE) {
2113        return instanceof_interface(instance_ce, ce);
2114    } else {
2115        return instanceof_class(instance_ce, ce);
2116    }
2117}
2118/* }}} */
2119
2120#define LOWER_CASE 1
2121#define UPPER_CASE 2
2122#define NUMERIC 3
2123
2124static void ZEND_FASTCALL increment_string(zval *str) /* {{{ */
2125{
2126    int carry=0;
2127    size_t pos=Z_STRLEN_P(str)-1;
2128    char *s;
2129    zend_string *t;
2130    int last=0; /* Shut up the compiler warning */
2131    int ch;
2132
2133    if (Z_STRLEN_P(str) == 0) {
2134        zend_string_release(Z_STR_P(str));
2135        if (CG(one_char_string)['1']) {
2136            ZVAL_INTERNED_STR(str, CG(one_char_string)['1']);
2137        } else {
2138            Z_STR_P(str) = zend_string_init("1", sizeof("1")-1, 0);
2139            Z_TYPE_INFO_P(str) = IS_STRING_EX;
2140        }
2141        return;
2142    }
2143
2144    if (!Z_REFCOUNTED_P(str)) {
2145        Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
2146        Z_TYPE_INFO_P(str) = IS_STRING_EX;
2147    } else if (Z_REFCOUNT_P(str) > 1) {
2148        Z_DELREF_P(str);
2149        Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
2150    } else {
2151        zend_string_forget_hash_val(Z_STR_P(str));
2152    }
2153    s = Z_STRVAL_P(str);
2154
2155    do {
2156        ch = s[pos];
2157        if (ch >= 'a' && ch <= 'z') {
2158            if (ch == 'z') {
2159                s[pos] = 'a';
2160                carry=1;
2161            } else {
2162                s[pos]++;
2163                carry=0;
2164            }
2165            last=LOWER_CASE;
2166        } else if (ch >= 'A' && ch <= 'Z') {
2167            if (ch == 'Z') {
2168                s[pos] = 'A';
2169                carry=1;
2170            } else {
2171                s[pos]++;
2172                carry=0;
2173            }
2174            last=UPPER_CASE;
2175        } else if (ch >= '0' && ch <= '9') {
2176            if (ch == '9') {
2177                s[pos] = '0';
2178                carry=1;
2179            } else {
2180                s[pos]++;
2181                carry=0;
2182            }
2183            last = NUMERIC;
2184        } else {
2185            carry=0;
2186            break;
2187        }
2188        if (carry == 0) {
2189            break;
2190        }
2191    } while (pos-- > 0);
2192
2193    if (carry) {
2194        t = zend_string_alloc(Z_STRLEN_P(str)+1, 0);
2195        memcpy(ZSTR_VAL(t) + 1, Z_STRVAL_P(str), Z_STRLEN_P(str));
2196        ZSTR_VAL(t)[Z_STRLEN_P(str) + 1] = '\0';
2197        switch (last) {
2198            case NUMERIC:
2199                ZSTR_VAL(t)[0] = '1';
2200                break;
2201            case UPPER_CASE:
2202                ZSTR_VAL(t)[0] = 'A';
2203                break;
2204            case LOWER_CASE:
2205                ZSTR_VAL(t)[0] = 'a';
2206                break;
2207        }
2208        zend_string_free(Z_STR_P(str));
2209        ZVAL_NEW_STR(str, t);
2210    }
2211}
2212/* }}} */
2213
2214ZEND_API int ZEND_FASTCALL increment_function(zval *op1) /* {{{ */
2215{
2216try_again:
2217    switch (Z_TYPE_P(op1)) {
2218        case IS_LONG:
2219            fast_long_increment_function(op1);
2220            break;
2221        case IS_DOUBLE:
2222            Z_DVAL_P(op1) = Z_DVAL_P(op1) + 1;
2223            break;
2224        case IS_NULL:
2225            ZVAL_LONG(op1, 1);
2226            break;
2227        case IS_STRING: {
2228                zend_long lval;
2229                double dval;
2230
2231                switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
2232                    case IS_LONG:
2233                        zend_string_release(Z_STR_P(op1));
2234                        if (lval == ZEND_LONG_MAX) {
2235                            /* switch to double */
2236                            double d = (double)lval;
2237                            ZVAL_DOUBLE(op1, d+1);
2238                        } else {
2239                            ZVAL_LONG(op1, lval+1);
2240                        }
2241                        break;
2242                    case IS_DOUBLE:
2243                        zend_string_release(Z_STR_P(op1));
2244                        ZVAL_DOUBLE(op1, dval+1);
2245                        break;
2246                    default:
2247                        /* Perl style string increment */
2248                        increment_string(op1);
2249                        break;
2250                }
2251            }
2252            break;
2253        case IS_OBJECT:
2254            if (Z_OBJ_HANDLER_P(op1, get)
2255               && Z_OBJ_HANDLER_P(op1, set)) {
2256                /* proxy object */
2257                zval rv;
2258                zval *val;
2259
2260                val = Z_OBJ_HANDLER_P(op1, get)(op1, &rv);
2261                Z_ADDREF_P(val);
2262                increment_function(val);
2263                Z_OBJ_HANDLER_P(op1, set)(op1, val);
2264                zval_ptr_dtor(val);
2265            } else if (Z_OBJ_HANDLER_P(op1, do_operation)) {
2266                zval op2;
2267                int res;
2268
2269                ZVAL_LONG(&op2, 1);
2270                res = Z_OBJ_HANDLER_P(op1, do_operation)(ZEND_ADD, op1, op1, &op2);
2271                zval_ptr_dtor(&op2);
2272
2273                return res;
2274            }
2275            return FAILURE;
2276        case IS_REFERENCE:
2277            op1 = Z_REFVAL_P(op1);
2278            goto try_again;
2279        default:
2280            return FAILURE;
2281    }
2282    return SUCCESS;
2283}
2284/* }}} */
2285
2286ZEND_API int ZEND_FASTCALL decrement_function(zval *op1) /* {{{ */
2287{
2288    zend_long lval;
2289    double dval;
2290
2291try_again:
2292    switch (Z_TYPE_P(op1)) {
2293        case IS_LONG:
2294            fast_long_decrement_function(op1);
2295            break;
2296        case IS_DOUBLE:
2297            Z_DVAL_P(op1) = Z_DVAL_P(op1) - 1;
2298            break;
2299        case IS_STRING:     /* Like perl we only support string increment */
2300            if (Z_STRLEN_P(op1) == 0) { /* consider as 0 */
2301                zend_string_release(Z_STR_P(op1));
2302                ZVAL_LONG(op1, -1);
2303                break;
2304            }
2305            switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
2306                case IS_LONG:
2307                    zend_string_release(Z_STR_P(op1));
2308                    if (lval == ZEND_LONG_MIN) {
2309                        double d = (double)lval;
2310                        ZVAL_DOUBLE(op1, d-1);
2311                    } else {
2312                        ZVAL_LONG(op1, lval-1);
2313                    }
2314                    break;
2315                case IS_DOUBLE:
2316                    zend_string_release(Z_STR_P(op1));
2317                    ZVAL_DOUBLE(op1, dval - 1);
2318                    break;
2319            }
2320            break;
2321        case IS_OBJECT:
2322            if (Z_OBJ_HANDLER_P(op1, get)
2323               && Z_OBJ_HANDLER_P(op1, set)) {
2324                /* proxy object */
2325                zval rv;
2326                zval *val;
2327
2328                val = Z_OBJ_HANDLER_P(op1, get)(op1, &rv);
2329                Z_ADDREF_P(val);
2330                decrement_function(val);
2331                Z_OBJ_HANDLER_P(op1, set)(op1, val);
2332                zval_ptr_dtor(val);
2333            } else if (Z_OBJ_HANDLER_P(op1, do_operation)) {
2334                zval op2;
2335                int res;
2336
2337                ZVAL_LONG(&op2, 1);
2338                res = Z_OBJ_HANDLER_P(op1, do_operation)(ZEND_SUB, op1, op1, &op2);
2339                zval_ptr_dtor(&op2);
2340
2341                return res;
2342            }
2343            return FAILURE;
2344        case IS_REFERENCE:
2345            op1 = Z_REFVAL_P(op1);
2346            goto try_again;
2347        default:
2348            return FAILURE;
2349    }
2350
2351    return SUCCESS;
2352}
2353/* }}} */
2354
2355ZEND_API int ZEND_FASTCALL zend_is_true(zval *op) /* {{{ */
2356{
2357    return i_zend_is_true(op);
2358}
2359/* }}} */
2360
2361ZEND_API int ZEND_FASTCALL zend_object_is_true(zval *op) /* {{{ */
2362{
2363    if (Z_OBJ_HT_P(op)->cast_object) {
2364        zval tmp;
2365        if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, _IS_BOOL) == SUCCESS) {
2366            return Z_TYPE(tmp) == IS_TRUE;
2367        }
2368        zend_error(E_RECOVERABLE_ERROR, "Object of class %s could not be converted to boolean", ZSTR_VAL(Z_OBJ_P(op)->ce->name));
2369    } else if (Z_OBJ_HT_P(op)->get) {
2370        int result;
2371        zval rv;
2372        zval *tmp = Z_OBJ_HT_P(op)->get(op, &rv);
2373
2374        if (Z_TYPE_P(tmp) != IS_OBJECT) {
2375            /* for safety - avoid loop */
2376            result = i_zend_is_true(tmp);
2377            zval_ptr_dtor(tmp);
2378            return result;
2379        }
2380    }
2381    return 1;
2382}
2383/* }}} */
2384
2385#ifdef ZEND_USE_TOLOWER_L
2386ZEND_API void zend_update_current_locale(void) /* {{{ */
2387{
2388    current_locale = _get_current_locale();
2389}
2390/* }}} */
2391#endif
2392
2393ZEND_API char* ZEND_FASTCALL zend_str_tolower_copy(char *dest, const char *source, size_t length) /* {{{ */
2394{
2395    register unsigned char *str = (unsigned char*)source;
2396    register unsigned char *result = (unsigned char*)dest;
2397    register unsigned char *end = str + length;
2398
2399    while (str < end) {
2400        *result++ = zend_tolower_ascii(*str++);
2401    }
2402    *result = '\0';
2403
2404    return dest;
2405}
2406/* }}} */
2407
2408ZEND_API char* ZEND_FASTCALL zend_str_tolower_dup(const char *source, size_t length) /* {{{ */
2409{
2410    return zend_str_tolower_copy((char *)emalloc(length+1), source, length);
2411}
2412/* }}} */
2413
2414ZEND_API void ZEND_FASTCALL zend_str_tolower(char *str, size_t length) /* {{{ */
2415{
2416    register unsigned char *p = (unsigned char*)str;
2417    register unsigned char *end = p + length;
2418
2419    while (p < end) {
2420        *p = zend_tolower_ascii(*p);
2421        p++;
2422    }
2423}
2424/* }}} */
2425
2426ZEND_API char* ZEND_FASTCALL zend_str_tolower_dup_ex(const char *source, size_t length) /* {{{ */
2427{
2428    register const unsigned char *p = (const unsigned char*)source;
2429    register const unsigned char *end = p + length;
2430
2431    while (p < end) {
2432        if (*p != zend_tolower_ascii(*p)) {
2433            char *res = (char*)emalloc(length + 1);
2434            register unsigned char *r;
2435
2436            if (p != (const unsigned char*)source) {
2437                memcpy(res, source, p - (const unsigned char*)source);
2438            }
2439            r = (unsigned char*)p + (res - source);
2440            while (p < end) {
2441                *r = zend_tolower_ascii(*p);
2442                p++;
2443                r++;
2444            }
2445            *r = '\0';
2446            return res;
2447        }
2448        p++;
2449    }
2450    return NULL;
2451}
2452/* }}} */
2453
2454ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower(zend_string *str) /* {{{ */
2455{
2456    register unsigned char *p = (unsigned char*)ZSTR_VAL(str);
2457    register unsigned char *end = p + ZSTR_LEN(str);
2458
2459    while (p < end) {
2460        if (*p != zend_tolower_ascii(*p)) {
2461            zend_string *res = zend_string_alloc(ZSTR_LEN(str), 0);
2462            register unsigned char *r;
2463
2464            if (p != (unsigned char*)ZSTR_VAL(str)) {
2465                memcpy(ZSTR_VAL(res), ZSTR_VAL(str), p - (unsigned char*)ZSTR_VAL(str));
2466            }
2467            r = p + (ZSTR_VAL(res) - ZSTR_VAL(str));
2468            while (p < end) {
2469                *r = zend_tolower_ascii(*p);
2470                p++;
2471                r++;
2472            }
2473            *r = '\0';
2474            return res;
2475        }
2476        p++;
2477    }
2478    return zend_string_copy(str);
2479}
2480/* }}} */
2481
2482ZEND_API int ZEND_FASTCALL zend_binary_strcmp(const char *s1, size_t len1, const char *s2, size_t len2) /* {{{ */
2483{
2484    int retval;
2485
2486    if (s1 == s2) {
2487        return 0;
2488    }
2489    retval = memcmp(s1, s2, MIN(len1, len2));
2490    if (!retval) {
2491        return (int)(len1 - len2);
2492    } else {
2493        return retval;
2494    }
2495}
2496/* }}} */
2497
2498ZEND_API int ZEND_FASTCALL zend_binary_strncmp(const char *s1, size_t len1, const char *s2, size_t len2, size_t length) /* {{{ */
2499{
2500    int retval;
2501
2502    if (s1 == s2) {
2503        return 0;
2504    }
2505    retval = memcmp(s1, s2, MIN(length, MIN(len1, len2)));
2506    if (!retval) {
2507        return (int)(MIN(length, len1) - MIN(length, len2));
2508    } else {
2509        return retval;
2510    }
2511}
2512/* }}} */
2513
2514ZEND_API int ZEND_FASTCALL zend_binary_strcasecmp(const char *s1, size_t len1, const char *s2, size_t len2) /* {{{ */
2515{
2516    size_t len;
2517    int c1, c2;
2518
2519    if (s1 == s2) {
2520        return 0;
2521    }
2522
2523    len = MIN(len1, len2);
2524    while (len--) {
2525        c1 = zend_tolower_ascii(*(unsigned char *)s1++);
2526        c2 = zend_tolower_ascii(*(unsigned char *)s2++);
2527        if (c1 != c2) {
2528            return c1 - c2;
2529        }
2530    }
2531
2532    return (int)(len1 - len2);
2533}
2534/* }}} */
2535
2536ZEND_API int ZEND_FASTCALL zend_binary_strncasecmp(const char *s1, size_t len1, const char *s2, size_t len2, size_t length) /* {{{ */
2537{
2538    size_t len;
2539    int c1, c2;
2540
2541    if (s1 == s2) {
2542        return 0;
2543    }
2544    len = MIN(length, MIN(len1, len2));
2545    while (len--) {
2546        c1 = zend_tolower_ascii(*(unsigned char *)s1++);
2547        c2 = zend_tolower_ascii(*(unsigned char *)s2++);
2548        if (c1 != c2) {
2549            return c1 - c2;
2550        }
2551    }
2552
2553    return (int)(MIN(length, len1) - MIN(length, len2));
2554}
2555/* }}} */
2556
2557ZEND_API int ZEND_FASTCALL zend_binary_strcasecmp_l(const char *s1, size_t len1, const char *s2, size_t len2) /* {{{ */
2558{
2559    size_t len;
2560    int c1, c2;
2561
2562    if (s1 == s2) {
2563        return 0;
2564    }
2565
2566    len = MIN(len1, len2);
2567    while (len--) {
2568        c1 = zend_tolower((int)*(unsigned char *)s1++);
2569        c2 = zend_tolower((int)*(unsigned char *)s2++);
2570        if (c1 != c2) {
2571            return c1 - c2;
2572        }
2573    }
2574
2575    return (int)(len1 - len2);
2576}
2577/* }}} */
2578
2579ZEND_API int ZEND_FASTCALL zend_binary_strncasecmp_l(const char *s1, size_t len1, const char *s2, size_t len2, size_t length) /* {{{ */
2580{
2581    size_t len;
2582    int c1, c2;
2583
2584    if (s1 == s2) {
2585        return 0;
2586    }
2587    len = MIN(length, MIN(len1, len2));
2588    while (len--) {
2589        c1 = zend_tolower((int)*(unsigned char *)s1++);
2590        c2 = zend_tolower((int)*(unsigned char *)s2++);
2591        if (c1 != c2) {
2592            return c1 - c2;
2593        }
2594    }
2595
2596    return (int)(MIN(length, len1) - MIN(length, len2));
2597}
2598/* }}} */
2599
2600ZEND_API int ZEND_FASTCALL zend_binary_zval_strcmp(zval *s1, zval *s2) /* {{{ */
2601{
2602    return zend_binary_strcmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2));
2603}
2604/* }}} */
2605
2606ZEND_API int ZEND_FASTCALL zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3) /* {{{ */
2607{
2608    return zend_binary_strncmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2), Z_LVAL_P(s3));
2609}
2610/* }}} */
2611
2612ZEND_API int ZEND_FASTCALL zend_binary_zval_strcasecmp(zval *s1, zval *s2) /* {{{ */
2613{
2614    return zend_binary_strcasecmp_l(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2));
2615}
2616/* }}} */
2617
2618ZEND_API int ZEND_FASTCALL zend_binary_zval_strncasecmp(zval *s1, zval *s2, zval *s3) /* {{{ */
2619{
2620    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));
2621}
2622/* }}} */
2623
2624ZEND_API zend_long ZEND_FASTCALL zendi_smart_strcmp(zval *s1, zval *s2) /* {{{ */
2625{
2626    int ret1, ret2;
2627    int oflow1, oflow2;
2628    zend_long lval1 = 0, lval2 = 0;
2629    double dval1 = 0.0, dval2 = 0.0;
2630
2631    if ((ret1 = is_numeric_string_ex(Z_STRVAL_P(s1), Z_STRLEN_P(s1), &lval1, &dval1, 0, &oflow1)) &&
2632        (ret2 = is_numeric_string_ex(Z_STRVAL_P(s2), Z_STRLEN_P(s2), &lval2, &dval2, 0, &oflow2))) {
2633#if ZEND_ULONG_MAX == 0xFFFFFFFF
2634        if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0. &&
2635            ((oflow1 == 1 && dval1 > 9007199254740991. /*0x1FFFFFFFFFFFFF*/)
2636            || (oflow1 == -1 && dval1 < -9007199254740991.))) {
2637#else
2638        if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0.) {
2639#endif
2640            /* both values are integers overflown to the same side, and the
2641             * double comparison may have resulted in crucial accuracy lost */
2642            goto string_cmp;
2643        }
2644        if ((ret1 == IS_DOUBLE) || (ret2 == IS_DOUBLE)) {
2645            if (ret1 != IS_DOUBLE) {
2646                if (oflow2) {
2647                    /* 2nd operand is integer > LONG_MAX (oflow2==1) or < LONG_MIN (-1) */
2648                    return -1 * oflow2;
2649                }
2650                dval1 = (double) lval1;
2651            } else if (ret2 != IS_DOUBLE) {
2652                if (oflow1) {
2653                    return oflow1;
2654                }
2655                dval2 = (double) lval2;
2656            } else if (dval1 == dval2 && !zend_finite(dval1)) {
2657                /* Both values overflowed and have the same sign,
2658                 * so a numeric comparison would be inaccurate */
2659                goto string_cmp;
2660            }
2661            dval1 = dval1 - dval2;
2662            return ZEND_NORMALIZE_BOOL(dval1);
2663        } else { /* they both have to be long's */
2664            return lval1 > lval2 ? 1 : (lval1 < lval2 ? -1 : 0);
2665        }
2666    } else {
2667        int strcmp_ret;
2668string_cmp:
2669        strcmp_ret = zend_binary_strcmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2));
2670        return ZEND_NORMALIZE_BOOL(strcmp_ret);
2671    }
2672}
2673/* }}} */
2674
2675static int hash_zval_compare_function(zval *z1, zval *z2) /* {{{ */
2676{
2677    zval result;
2678
2679    if (compare_function(&result, z1, z2)==FAILURE) {
2680        return 1;
2681    }
2682    return Z_LVAL(result);
2683}
2684/* }}} */
2685
2686ZEND_API int ZEND_FASTCALL zend_compare_symbol_tables(HashTable *ht1, HashTable *ht2) /* {{{ */
2687{
2688    return ht1 == ht2 ? 0 : zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0);
2689}
2690/* }}} */
2691
2692ZEND_API int ZEND_FASTCALL zend_compare_arrays(zval *a1, zval *a2) /* {{{ */
2693{
2694    return zend_compare_symbol_tables(Z_ARRVAL_P(a1), Z_ARRVAL_P(a2));
2695}
2696/* }}} */
2697
2698ZEND_API int ZEND_FASTCALL zend_compare_objects(zval *o1, zval *o2) /* {{{ */
2699{
2700    if (Z_OBJ_P(o1) == Z_OBJ_P(o2)) {
2701        return 0;
2702    }
2703
2704    if (Z_OBJ_HT_P(o1)->compare_objects == NULL) {
2705        return 1;
2706    } else {
2707        return Z_OBJ_HT_P(o1)->compare_objects(o1, o2);
2708    }
2709}
2710/* }}} */
2711
2712ZEND_API void ZEND_FASTCALL zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC) /* {{{ */
2713{
2714    zend_string *str;
2715
2716    str = zend_strpprintf(0, "%.*G", (int) EG(precision), (double)Z_DVAL_P(op));
2717    ZVAL_NEW_STR(op, str);
2718}
2719/* }}} */
2720
2721ZEND_API zend_string* ZEND_FASTCALL zend_long_to_str(zend_long num) /* {{{ */
2722{
2723    char buf[MAX_LENGTH_OF_LONG + 1];
2724    char *res = zend_print_long_to_buf(buf + sizeof(buf) - 1, num);
2725    return zend_string_init(res, buf + sizeof(buf) - 1 - res, 0);
2726}
2727/* }}} */
2728
2729ZEND_API zend_uchar ZEND_FASTCALL is_numeric_str_function(const zend_string *str, zend_long *lval, double *dval) /* {{{ */ {
2730    return is_numeric_string_ex(ZSTR_VAL(str), ZSTR_LEN(str), lval, dval, -1, NULL);
2731}
2732/* }}} */
2733
2734ZEND_API zend_uchar ZEND_FASTCALL _is_numeric_string_ex(const char *str, size_t length, zend_long *lval, double *dval, int allow_errors, int *oflow_info) /* {{{ */
2735{
2736    const char *ptr;
2737    int digits = 0, dp_or_e = 0;
2738    double local_dval = 0.0;
2739    zend_uchar type;
2740    zend_long tmp_lval = 0;
2741    int neg = 0;
2742
2743    if (!length) {
2744        return 0;
2745    }
2746
2747    if (oflow_info != NULL) {
2748        *oflow_info = 0;
2749    }
2750
2751    /* Skip any whitespace
2752     * This is much faster than the isspace() function */
2753    while (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r' || *str == '\v' || *str == '\f') {
2754        str++;
2755        length--;
2756    }
2757    ptr = str;
2758
2759    if (*ptr == '-') {
2760        neg = 1;
2761        ptr++;
2762    } else if (*ptr == '+') {
2763        ptr++;
2764    }
2765
2766    if (ZEND_IS_DIGIT(*ptr)) {
2767        /* Skip any leading 0s */
2768        while (*ptr == '0') {
2769            ptr++;
2770        }
2771
2772        /* Count the number of digits. If a decimal point/exponent is found,
2773         * it's a double. Otherwise, if there's a dval or no need to check for
2774         * a full match, stop when there are too many digits for a long */
2775        for (type = IS_LONG; !(digits >= MAX_LENGTH_OF_LONG && (dval || allow_errors == 1)); digits++, ptr++) {
2776check_digits:
2777            if (ZEND_IS_DIGIT(*ptr)) {
2778                tmp_lval = tmp_lval * 10 + (*ptr) - '0';
2779                continue;
2780            } else if (*ptr == '.' && dp_or_e < 1) {
2781                goto process_double;
2782            } else if ((*ptr == 'e' || *ptr == 'E') && dp_or_e < 2) {
2783                const char *e = ptr + 1;
2784
2785                if (*e == '-' || *e == '+') {
2786                    ptr = e++;
2787                }
2788                if (ZEND_IS_DIGIT(*e)) {
2789                    goto process_double;
2790                }
2791            }
2792
2793            break;
2794        }
2795
2796        if (digits >= MAX_LENGTH_OF_LONG) {
2797            if (oflow_info != NULL) {
2798                *oflow_info = *str == '-' ? -1 : 1;
2799            }
2800            dp_or_e = -1;
2801            goto process_double;
2802        }
2803    } else if (*ptr == '.' && ZEND_IS_DIGIT(ptr[1])) {
2804process_double:
2805        type = IS_DOUBLE;
2806
2807        /* If there's a dval, do the conversion; else continue checking
2808         * the digits if we need to check for a full match */
2809        if (dval) {
2810            local_dval = zend_strtod(str, &ptr);
2811        } else if (allow_errors != 1 && dp_or_e != -1) {
2812            dp_or_e = (*ptr++ == '.') ? 1 : 2;
2813            goto check_digits;
2814        }
2815    } else {
2816        return 0;
2817    }
2818
2819    if (ptr != str + length) {
2820        if (!allow_errors) {
2821            return 0;
2822        }
2823        if (allow_errors == -1) {
2824            zend_error(E_NOTICE, "A non well formed numeric value encountered");
2825        }
2826    }
2827
2828    if (type == IS_LONG) {
2829        if (digits == MAX_LENGTH_OF_LONG - 1) {
2830            int cmp = strcmp(&ptr[-digits], long_min_digits);
2831
2832            if (!(cmp < 0 || (cmp == 0 && *str == '-'))) {
2833                if (dval) {
2834                    *dval = zend_strtod(str, NULL);
2835                }
2836                if (oflow_info != NULL) {
2837                    *oflow_info = *str == '-' ? -1 : 1;
2838                }
2839
2840                return IS_DOUBLE;
2841            }
2842        }
2843
2844        if (lval) {
2845            if (neg) {
2846                tmp_lval = -tmp_lval;
2847            }
2848            *lval = tmp_lval;
2849        }
2850
2851        return IS_LONG;
2852    } else {
2853        if (dval) {
2854            *dval = local_dval;
2855        }
2856
2857        return IS_DOUBLE;
2858    }
2859}
2860/* }}} */
2861
2862/*
2863 * String matching - Sunday algorithm
2864 * http://www.iti.fh-flensburg.de/lang/algorithmen/pattern/sundayen.htm
2865 */
2866static zend_always_inline void zend_memnstr_ex_pre(unsigned int td[], const char *needle, size_t needle_len, int reverse) /* {{{ */ {
2867    int i;
2868
2869    for (i = 0; i < 256; i++) {
2870        td[i] = needle_len + 1;
2871    }
2872
2873    if (reverse) {
2874        for (i = needle_len - 1; i >= 0; i--) {
2875            td[(unsigned char)needle[i]] = i + 1;
2876        }
2877    } else {
2878        for (i = 0; i < needle_len; i++) {
2879            td[(unsigned char)needle[i]] = (int)needle_len - i;
2880        }
2881    }
2882}
2883/* }}} */
2884
2885ZEND_API const char* ZEND_FASTCALL zend_memnstr_ex(const char *haystack, const char *needle, size_t needle_len, const char *end) /* {{{ */
2886{
2887    unsigned int td[256];
2888    register size_t i;
2889    register const char *p;
2890
2891    if (needle_len == 0 || (end - haystack) == 0) {
2892        return NULL;
2893    }
2894
2895    zend_memnstr_ex_pre(td, needle, needle_len, 0);
2896
2897    p = haystack;
2898    end -= needle_len;
2899
2900    while (p <= end) {
2901        for (i = 0; i < needle_len; i++) {
2902            if (needle[i] != p[i]) {
2903                break;
2904            }
2905        }
2906        if (i == needle_len) {
2907            return p;
2908        }
2909        p += td[(unsigned char)(p[needle_len])];
2910    }
2911
2912    return NULL;
2913}
2914/* }}} */
2915
2916ZEND_API const char* ZEND_FASTCALL zend_memnrstr_ex(const char *haystack, const char *needle, size_t needle_len, const char *end) /* {{{ */
2917{
2918    unsigned int td[256];
2919    register size_t i;
2920    register const char *p;
2921
2922    if (needle_len == 0 || (end - haystack) == 0) {
2923        return NULL;
2924    }
2925
2926    zend_memnstr_ex_pre(td, needle, needle_len, 1);
2927
2928    p = end;
2929    p -= needle_len;
2930
2931    while (p >= haystack) {
2932        for (i = 0; i < needle_len; i++) {
2933            if (needle[i] != p[i]) {
2934                break;
2935            }
2936        }
2937
2938        if (i == needle_len) {
2939            return (const char *)p;
2940        }
2941
2942        if (UNEXPECTED(p == haystack)) {
2943            return NULL;
2944        }
2945
2946        p -= td[(unsigned char)(p[-1])];
2947    }
2948
2949    return NULL;
2950}
2951/* }}} */
2952
2953#if !ZEND_DVAL_TO_LVAL_CAST_OK
2954# if SIZEOF_ZEND_LONG == 4
2955ZEND_API zend_long ZEND_FASTCALL zend_dval_to_lval_slow(double d)
2956{
2957    double  two_pow_32 = pow(2., 32.),
2958            dmod;
2959
2960    dmod = fmod(d, two_pow_32);
2961    if (dmod < 0) {
2962        /* we're going to make this number positive; call ceil()
2963         * to simulate rounding towards 0 of the negative number */
2964        dmod = ceil(dmod);// + two_pow_32;
2965    }
2966    return (zend_long)(zend_ulong)dmod;
2967}
2968#else
2969ZEND_API zend_long ZEND_FASTCALL zend_dval_to_lval_slow(double d)
2970{
2971    double  two_pow_64 = pow(2., 64.),
2972            dmod;
2973
2974    dmod = fmod(d, two_pow_64);
2975    if (dmod < 0) {
2976        /* no need to call ceil; original double must have had no
2977         * fractional part, hence dmod does not have one either */
2978        dmod += two_pow_64;
2979    }
2980    return (zend_long)(zend_ulong)dmod;
2981}
2982#endif
2983#endif
2984
2985/*
2986 * Local variables:
2987 * tab-width: 4
2988 * c-basic-offset: 4
2989 * indent-tabs-mode: t
2990 * End:
2991 */
2992