File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / Zend / zend_operators.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:47:52 2012 UTC (12 years, 4 months ago) by misho
Branches: php, MAIN
CVS tags: v5_3_10, HEAD
php

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>