PageRenderTime 59ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/Zend/zend_operators.c

http://github.com/infusion/PHP
C | 2079 lines | 1697 code | 246 blank | 136 comment | 369 complexity | b7a5cc4688dec887b0da9930c4eb747e MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

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

Large files files are truncated, but you can click here to view the full file