PageRenderTime 48ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/2.1/Source/ExtSupport/PHP4/Variables.cpp

#
C++ | 3574 lines | 2902 code | 469 blank | 203 comment | 661 complexity | ccf186d0a57acaa894deee49e80d345c MD5 | raw file
Possible License(s): CPL-1.0, GPL-2.0, CC-BY-SA-3.0, MPL-2.0-no-copyleft-exception, Apache-2.0

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

  1. //
  2. // ExtSupport.PHP4 - substitute for php4ts.dll
  3. //
  4. // Variables.cpp
  5. // - contains definitions of variables related functions
  6. //
  7. #include "stdafx.h"
  8. #include "Variables.h"
  9. #include "Helpers.h"
  10. #include "ExtSupport.h"
  11. #include "Memory.h"
  12. #include "Errors.h"
  13. #include "Hash.h"
  14. #include "Resources.h"
  15. #include "TsrmLs.h"
  16. #include "Request.h"
  17. #include "Constants.h"
  18. #include "Unsupported.h"
  19. #include "Spprintf.h"
  20. #include "Parameters.h"
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <limits.h>
  24. #include <math.h>
  25. using namespace System;
  26. using namespace PHP::ExtManager;
  27. #pragma unmanaged
  28. static inline char *
  29. zend_str_tolower_dup(const char *source, unsigned int length)
  30. {
  31. return zend_str_tolower_copy((char *)emalloc(length+1), source, length);
  32. }
  33. char *empty_string = ""; /* in order to save emalloc() and efree() time for
  34. * empty strings (usually used to denote empty
  35. * return values in failed functions).
  36. * The macro STR_FREE() will not efree() it.
  37. */
  38. #define LONG_SIGN_MASK (1L << (8*sizeof(long)-1))
  39. #define zend_strtod(str, endptr) strtod(str, endptr)
  40. zval zval_used_for_init = { NULL, IS_NULL, 0, 1 };
  41. zend_utility_values zend_uv = { ".php", 4, 1 };
  42. // copied from zend_API.c and slightly modified
  43. #define zendi_convert_scalar_to_number(op, holder, result) \
  44. if (op==result) { \
  45. convert_scalar_to_number(op TSRMLS_CC); \
  46. } else { \
  47. switch ((op)->type) { \
  48. case IS_STRING: \
  49. { \
  50. switch (((holder).type=is_numeric_string((op)->value.str.val, (op)->value.str.len, &(holder).value.lval, &(holder).value.dval, 1))) { \
  51. case IS_DOUBLE: \
  52. case IS_LONG: \
  53. break; \
  54. default: \
  55. (holder).value.lval = strtol((op)->value.str.val, NULL, 10); \
  56. (holder).type = IS_LONG; \
  57. break; \
  58. } \
  59. (op) = &(holder); \
  60. break; \
  61. } \
  62. case IS_BOOL: \
  63. case IS_RESOURCE: \
  64. (holder).value.lval = (op)->value.lval; \
  65. (holder).type = IS_LONG; \
  66. (op) = &(holder); \
  67. break; \
  68. case IS_NULL: \
  69. (holder).value.lval = 0; \
  70. (holder).type = IS_LONG; \
  71. (op) = &(holder); \
  72. break; \
  73. } \
  74. }
  75. // copied from zend_API.c
  76. #define DVAL_TO_LVAL(d, l) (l) = (d) > LONG_MAX ? (unsigned long) (d) : (long) (d)
  77. // copied from zend_API.c
  78. #define zendi_convert_to_long(op, holder, result) \
  79. if (op==result) { \
  80. convert_to_long(op); \
  81. } else if ((op)->type != IS_LONG) { \
  82. switch ((op)->type) { \
  83. case IS_NULL: \
  84. (holder).value.lval = 0; \
  85. break; \
  86. case IS_DOUBLE: \
  87. DVAL_TO_LVAL((op)->value.dval, (holder).value.lval); \
  88. break; \
  89. case IS_STRING: \
  90. (holder).value.lval = strtol((op)->value.str.val, NULL, 10); \
  91. break; \
  92. case IS_ARRAY: \
  93. (holder).value.lval = (zend_hash_num_elements((op)->value.ht)?1:0); \
  94. break; \
  95. case IS_OBJECT: \
  96. (holder).value.lval = (zend_hash_num_elements(Z_OBJPROP_P(op))?1:0); \
  97. break; \
  98. case IS_BOOL: \
  99. case IS_RESOURCE: \
  100. (holder).value.lval = (op)->value.lval; \
  101. break; \
  102. default: \
  103. zend_error(E_WARNING, "Cannot convert to ordinal value"); \
  104. (holder).value.lval = 0; \
  105. break; \
  106. } \
  107. (holder).type = IS_LONG; \
  108. (op) = &(holder); \
  109. }
  110. // copied from zend_API.c
  111. #define zendi_convert_to_boolean(op, holder, result) \
  112. if (op==result) { \
  113. convert_to_boolean(op); \
  114. } else if ((op)->type != IS_BOOL) { \
  115. switch ((op)->type) { \
  116. case IS_NULL: \
  117. (holder).value.lval = 0; \
  118. break; \
  119. case IS_RESOURCE: \
  120. case IS_LONG: \
  121. (holder).value.lval = ((op)->value.lval ? 1 : 0); \
  122. break; \
  123. case IS_DOUBLE: \
  124. (holder).value.lval = ((op)->value.dval ? 1 : 0); \
  125. break; \
  126. case IS_STRING: \
  127. if ((op)->value.str.len == 0 \
  128. || ((op)->value.str.len==1 && (op)->value.str.val[0]=='0')) { \
  129. (holder).value.lval = 0; \
  130. } else { \
  131. (holder).value.lval = 1; \
  132. } \
  133. break; \
  134. case IS_ARRAY: \
  135. (holder).value.lval = (zend_hash_num_elements((op)->value.ht)?1:0); \
  136. break; \
  137. case IS_OBJECT: \
  138. (holder).value.lval = (zend_hash_num_elements(Z_OBJPROP_P(op))?1:0); \
  139. break; \
  140. default: \
  141. (holder).value.lval = 0; \
  142. break; \
  143. } \
  144. (holder).type = IS_BOOL; \
  145. (op) = &(holder); \
  146. }
  147. // copied from zend_API.c and beautified
  148. ZEND_API char *zend_zval_type_name(zval *arg)
  149. {
  150. switch (arg->type)
  151. {
  152. case IS_NULL: return "null";
  153. case IS_LONG: return "integer";
  154. case IS_DOUBLE: return "double";
  155. case IS_STRING: return "string";
  156. case IS_ARRAY: return "array";
  157. case IS_OBJECT: return "object";
  158. case IS_BOOL: return "boolean";
  159. case IS_RESOURCE: return "resource";
  160. default: return "unknown";
  161. }
  162. }
  163. // copied from zend_variables.c, slightly modified and beautified
  164. #ifdef PHP4TS
  165. ZEND_API int _zval_copy_ctor(zval *zvalue ZEND_FILE_LINE_DC)
  166. {
  167. switch (zvalue->type)
  168. {
  169. case IS_RESOURCE: {
  170. TSRMLS_FETCH();
  171. _zend_list_addref(zvalue->value.lval, tsrm_ls);
  172. }
  173. break;
  174. case IS_BOOL:
  175. case IS_LONG:
  176. case IS_NULL: break;
  177. case IS_CONSTANT:
  178. case IS_STRING: if (zvalue->value.str.val)
  179. {
  180. if (zvalue->value.str.len==0)
  181. {
  182. zvalue->value.str.val = empty_string;
  183. return SUCCESS;
  184. }
  185. }
  186. CHECK_ZVAL_STRING_REL(zvalue);
  187. zvalue->value.str.val = (char *)estrndup_rel(zvalue->value.str.val, zvalue->value.str.len);
  188. break;
  189. case IS_ARRAY:
  190. case IS_CONSTANT_ARRAY:
  191. {
  192. zval *tmp;
  193. HashTable *original_ht = zvalue->value.ht;
  194. TSRMLS_FETCH();
  195. if (zvalue->value.ht == &EG(symbol_table)) return SUCCESS;
  196. ALLOC_HASHTABLE_REL(zvalue->value.ht);
  197. zend_hash_init(zvalue->value.ht, 0, NULL, ZVAL_PTR_DTOR, 0);
  198. zend_hash_copy(zvalue->value.ht, original_ht, (copy_ctor_func_t)zval_add_ref, (void *)&tmp, sizeof(zval *));
  199. }
  200. break;
  201. case IS_OBJECT: {
  202. zval *tmp;
  203. HashTable *original_ht = Z_OBJPROP_P(zvalue);
  204. TSRMLS_FETCH();
  205. if (original_ht == &EG(symbol_table)) return SUCCESS; /* do nothing */
  206. ALLOC_HASHTABLE_REL(Z_OBJPROP_P(zvalue));
  207. zend_hash_init(Z_OBJPROP_P(zvalue), 0, NULL, ZVAL_PTR_DTOR, 0);
  208. zend_hash_copy(Z_OBJPROP_P(zvalue), original_ht,
  209. (copy_ctor_func_t)zval_add_ref, (void *) &tmp, sizeof(zval *));
  210. }
  211. break;
  212. }
  213. return SUCCESS;
  214. }
  215. #elif defined(PHP5TS)
  216. ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
  217. {
  218. switch (zvalue->type) {
  219. case IS_RESOURCE: {
  220. TSRMLS_FETCH();
  221. zend_list_addref(zvalue->value.lval);
  222. }
  223. break;
  224. case IS_BOOL:
  225. case IS_LONG:
  226. case IS_NULL:
  227. break;
  228. case IS_CONSTANT:
  229. case IS_STRING:
  230. CHECK_ZVAL_STRING_REL(zvalue);
  231. zvalue->value.str.val = (char *) estrndup_rel(zvalue->value.str.val, zvalue->value.str.len);
  232. break;
  233. case IS_ARRAY:
  234. case IS_CONSTANT_ARRAY: {
  235. zval *tmp;
  236. HashTable *original_ht = zvalue->value.ht;
  237. HashTable *tmp_ht = NULL;
  238. TSRMLS_FETCH();
  239. if (zvalue->value.ht == &EG(symbol_table)) {
  240. return; /* do nothing */
  241. }
  242. ALLOC_HASHTABLE_REL(tmp_ht);
  243. zend_hash_init(tmp_ht, zend_hash_num_elements(original_ht), NULL, ZVAL_PTR_DTOR, 0);
  244. zend_hash_copy(tmp_ht, original_ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
  245. zvalue->value.ht = tmp_ht;
  246. }
  247. break;
  248. case IS_OBJECT:
  249. {
  250. TSRMLS_FETCH();
  251. Z_OBJ_HT_P(zvalue)->add_ref(zvalue TSRMLS_CC);
  252. }
  253. break;
  254. }
  255. }
  256. #endif
  257. #pragma managed
  258. // copied from zend_variables.c, slightly modified and beautified
  259. #ifdef PHP4TS
  260. ZEND_API void _zval_dtor(zval *zvalue ZEND_FILE_LINE_DC)
  261. {
  262. if (zvalue->type == IS_LONG) return;
  263. switch (zvalue->type & ~IS_CONSTANT_INDEX)
  264. {
  265. case IS_STRING:
  266. case IS_CONSTANT: CHECK_ZVAL_STRING_REL(zvalue);
  267. STR_FREE_REL(zvalue->value.str.val);
  268. break;
  269. case IS_ARRAY:
  270. case IS_CONSTANT_ARRAY:
  271. {
  272. TSRMLS_FETCH();
  273. if (zvalue->value.ht && (zvalue->value.ht != &EG(symbol_table)))
  274. {
  275. zend_hash_destroy(zvalue->value.ht);
  276. FREE_HASHTABLE(zvalue->value.ht);
  277. }
  278. }
  279. break;
  280. case IS_OBJECT: {
  281. TSRMLS_FETCH();
  282. zend_hash_destroy(Z_OBJPROP_P(zvalue));
  283. FREE_HASHTABLE(Z_OBJPROP_P(zvalue));
  284. }
  285. break;
  286. case IS_RESOURCE: {
  287. // NEVER DESTROY RESOURCES LIKE THIS - causes many problems
  288. // destroy resource
  289. //if (Request::GetCurrentRequest()->DontDestroyResources == false)
  290. //{
  291. // TSRMLS_FETCH();
  292. // _zend_list_delete(zvalue->value.lval, tsrm_ls);
  293. //}
  294. }
  295. break;
  296. case IS_LONG: case IS_DOUBLE:
  297. case IS_BOOL: case IS_NULL:
  298. default:
  299. return;
  300. }
  301. }
  302. #elif defined(PHP5TS)
  303. ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC)
  304. {
  305. switch (zvalue->type & ~IS_CONSTANT_INDEX) {
  306. case IS_STRING:
  307. case IS_CONSTANT:
  308. CHECK_ZVAL_STRING_REL(zvalue);
  309. STR_FREE_REL(zvalue->value.str.val);
  310. break;
  311. case IS_ARRAY:
  312. case IS_CONSTANT_ARRAY: {
  313. TSRMLS_FETCH();
  314. if (zvalue->value.ht && (zvalue->value.ht != &EG(symbol_table))) {
  315. zend_hash_destroy(zvalue->value.ht);
  316. FREE_HASHTABLE(zvalue->value.ht);
  317. }
  318. }
  319. break;
  320. case IS_OBJECT:
  321. {
  322. TSRMLS_FETCH();
  323. Z_OBJ_HT_P(zvalue)->del_ref(zvalue TSRMLS_CC);
  324. }
  325. break;
  326. case IS_RESOURCE:
  327. {
  328. // NEVER DESTROY RESOURCES LIKE THIS - causes many problems
  329. // destroy resource
  330. //if (Request::GetCurrentRequest()->DontDestroyResources == false)
  331. //{
  332. //TSRMLS_FETCH();
  333. ///* destroy resource */
  334. //zend_list_delete(zvalue->value.lval);
  335. //}
  336. }
  337. break;
  338. case IS_LONG:
  339. case IS_DOUBLE:
  340. case IS_BOOL:
  341. case IS_NULL:
  342. default:
  343. return;
  344. break;
  345. }
  346. }
  347. #endif
  348. #pragma unmanaged
  349. // copied from zend_variables.c and beautified
  350. ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC)
  351. {
  352. switch (zvalue->type & ~IS_CONSTANT_INDEX)
  353. {
  354. case IS_STRING:
  355. case IS_CONSTANT:
  356. CHECK_ZVAL_STRING_REL(zvalue);
  357. if (zvalue->value.str.val != empty_string) free(zvalue->value.str.val);
  358. break;
  359. case IS_ARRAY:
  360. case IS_CONSTANT_ARRAY:
  361. case IS_OBJECT:
  362. case IS_RESOURCE:
  363. zend_error(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
  364. break;
  365. case IS_LONG:
  366. case IS_DOUBLE:
  367. case IS_BOOL:
  368. case IS_NULL:
  369. default:
  370. break;
  371. }
  372. }
  373. // copied from zend_execute.h, slightly modified and beautified
  374. static inline void safe_free_zval_ptr(zval *p)
  375. {
  376. TSRMLS_FETCH();
  377. if (p != EG(uninitialized_zval_ptr))
  378. {
  379. FREE_ZVAL(p);
  380. }
  381. }
  382. // copied from zend_execute_API.c, slightly modified and beautified
  383. ZEND_API void _zval_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC)
  384. {
  385. (*zval_ptr)->refcount--;
  386. if ((*zval_ptr)->refcount == 0)
  387. {
  388. zval_dtor(*zval_ptr);
  389. safe_free_zval_ptr(*zval_ptr);
  390. }
  391. else if (((*zval_ptr)->refcount == 1) && ((*zval_ptr)->type != IS_OBJECT))
  392. {
  393. (*zval_ptr)->is_ref = 0;
  394. }
  395. }
  396. // copied from zend_execute_API.c, slightly modified and beautified
  397. ZEND_API void _zval_internal_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC)
  398. {
  399. (*zval_ptr)->refcount--;
  400. if ((*zval_ptr)->refcount == 0)
  401. {
  402. zval_internal_dtor(*zval_ptr);
  403. free(*zval_ptr);
  404. }
  405. else if ((*zval_ptr)->refcount == 1) (*zval_ptr)->is_ref = 0;
  406. }
  407. // copied from zend_variables.c
  408. ZEND_API void zval_add_ref(zval **p)
  409. {
  410. (*p)->refcount++;
  411. }
  412. // copied from zend_operators.c, slightly modified and beautified
  413. #ifdef PHP4TS
  414. ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC)
  415. {
  416. switch (op->type)
  417. {
  418. case IS_STRING:
  419. {
  420. char *strval;
  421. strval = op->value.str.val;
  422. switch ((op->type = is_numeric_string(strval, op->value.str.len, &op->value.lval, &op->value.dval, 1)))
  423. {
  424. case IS_DOUBLE:
  425. case IS_LONG:
  426. break;
  427. default:
  428. op->value.lval = strtol(op->value.str.val, NULL, 10);
  429. op->type = IS_LONG;
  430. break;
  431. }
  432. STR_FREE(strval);
  433. break;
  434. }
  435. case IS_BOOL: op->type = IS_LONG;
  436. break;
  437. case IS_RESOURCE: _zend_list_delete(op->value.lval, tsrm_ls);
  438. op->type = IS_LONG;
  439. break;
  440. case IS_NULL: op->type = IS_LONG;
  441. op->value.lval = 0;
  442. break;
  443. }
  444. }
  445. // copied from zend_operators.c and beautified
  446. static void convert_scalar_to_array(zval *op, int type)
  447. {
  448. zval *entry;
  449. ALLOC_ZVAL(entry);
  450. *entry = *op;
  451. INIT_PZVAL(entry);
  452. switch (type)
  453. {
  454. case IS_ARRAY:
  455. ALLOC_HASHTABLE(op->value.ht);
  456. zend_hash_init(op->value.ht, 0, NULL, ZVAL_PTR_DTOR, 0);
  457. zend_hash_index_update(op->value.ht, 0, (void *) &entry, sizeof(zval *), NULL);
  458. op->type = IS_ARRAY;
  459. break;
  460. case IS_OBJECT:
  461. ALLOC_HASHTABLE(Z_OBJPROP_P(op));
  462. zend_hash_init(Z_OBJPROP_P(op), 0, NULL, ZVAL_PTR_DTOR, 0);
  463. zend_hash_update(Z_OBJPROP_P(op), "scalar", sizeof("scalar"), (void *)&entry, sizeof(zval *), NULL);
  464. Z_OBJCE_P(op) = &zend_standard_class_def;
  465. Z_TYPE_P(op) = IS_OBJECT;
  466. break;
  467. }
  468. }
  469. // copied from zend_operators.c, slightly modified and beautified
  470. ZEND_API void convert_to_array(zval *op)
  471. {
  472. TSRMLS_FETCH();
  473. switch(op->type)
  474. {
  475. case IS_ARRAY: return;
  476. /* OBJECTS_OPTIMIZE */
  477. case IS_OBJECT:
  478. op->type = IS_ARRAY;
  479. op->value.ht = Z_OBJPROP_P(op);
  480. return;
  481. case IS_NULL: ALLOC_HASHTABLE(op->value.ht);
  482. zend_hash_init(op->value.ht, 0, NULL, ZVAL_PTR_DTOR, 0);
  483. op->type = IS_ARRAY;
  484. break;
  485. default: convert_scalar_to_array(op, IS_ARRAY);
  486. break;
  487. }
  488. }
  489. // copied from zend_operators.c and beautified
  490. ZEND_API void convert_to_boolean(zval *op)
  491. {
  492. char *strval;
  493. int tmp;
  494. switch (op->type)
  495. {
  496. case IS_BOOL:
  497. break;
  498. case IS_NULL:
  499. op->value.lval = 0;
  500. break;
  501. case IS_RESOURCE:
  502. {
  503. TSRMLS_FETCH();
  504. zend_list_delete(op->value.lval);
  505. }
  506. /* break missing intentionally */
  507. case IS_LONG:
  508. op->value.lval = (op->value.lval ? 1 : 0);
  509. break;
  510. case IS_DOUBLE:
  511. op->value.lval = (op->value.dval ? 1 : 0);
  512. break;
  513. case IS_STRING:
  514. strval = op->value.str.val;
  515. if (op->value.str.len == 0 || (op->value.str.len == 1 && op->value.str.val[0] == '0')) op->value.lval = 0;
  516. else op->value.lval = 1;
  517. STR_FREE(strval);
  518. break;
  519. case IS_ARRAY:
  520. tmp = (zend_hash_num_elements(op->value.ht) ? 1 : 0);
  521. zval_dtor(op);
  522. op->value.lval = tmp;
  523. break;
  524. case IS_OBJECT:
  525. tmp = (zend_hash_num_elements(Z_OBJPROP_P(op)) ? 1 : 0);
  526. zval_dtor(op);
  527. op->value.lval = tmp;
  528. break;
  529. default:
  530. zval_dtor(op);
  531. op->value.lval = 0;
  532. break;
  533. }
  534. op->type = IS_BOOL;
  535. }
  536. // copied from zend_operators.c and beautified
  537. ZEND_API void convert_to_double(zval *op)
  538. {
  539. char *strval;
  540. double tmp;
  541. switch (op->type)
  542. {
  543. case IS_NULL:
  544. op->value.dval = 0.0;
  545. break;
  546. case IS_RESOURCE:
  547. {
  548. TSRMLS_FETCH();
  549. zend_list_delete(op->value.lval);
  550. }
  551. /* break missing intentionally */
  552. case IS_BOOL:
  553. case IS_LONG:
  554. op->value.dval = (double)op->value.lval;
  555. break;
  556. case IS_DOUBLE:
  557. break;
  558. case IS_STRING:
  559. strval = op->value.str.val;
  560. op->value.dval = strtod(strval, NULL);
  561. STR_FREE(strval);
  562. break;
  563. case IS_ARRAY:
  564. tmp = (zend_hash_num_elements(op->value.ht) ? 1 : 0);
  565. zval_dtor(op);
  566. op->value.dval = tmp;
  567. break;
  568. case IS_OBJECT:
  569. tmp = (zend_hash_num_elements(Z_OBJPROP_P(op))? 1 : 0);
  570. zval_dtor(op);
  571. op->value.dval = tmp;
  572. break;
  573. default:
  574. zend_error(E_WARNING, "Cannot convert to real value (type=%d)", op->type);
  575. zval_dtor(op);
  576. op->value.dval = 0;
  577. break;
  578. }
  579. op->type = IS_DOUBLE;
  580. }
  581. // copied from zend_operators.c and beautified
  582. ZEND_API void convert_to_long(zval *op)
  583. {
  584. convert_to_long_base(op, 10);
  585. }
  586. // copied from zend_operators.c and beautified
  587. ZEND_API void convert_to_long_base(zval *op, int base)
  588. {
  589. char *strval;
  590. long tmp;
  591. switch (op->type)
  592. {
  593. case IS_NULL:
  594. op->value.lval = 0;
  595. break;
  596. case IS_RESOURCE:
  597. {
  598. TSRMLS_FETCH();
  599. zend_list_delete(op->value.lval);
  600. }
  601. /* break missing intentionally */
  602. case IS_BOOL:
  603. case IS_LONG:
  604. break;
  605. case IS_DOUBLE:
  606. DVAL_TO_LVAL(op->value.dval, op->value.lval);
  607. break;
  608. case IS_STRING:
  609. strval = op->value.str.val;
  610. op->value.lval = strtol(strval, NULL, base);
  611. STR_FREE(strval);
  612. break;
  613. case IS_ARRAY:
  614. tmp = (zend_hash_num_elements(op->value.ht) ? 1 : 0);
  615. zval_dtor(op);
  616. op->value.lval = tmp;
  617. break;
  618. case IS_OBJECT:
  619. tmp = (zend_hash_num_elements(Z_OBJPROP_P(op))?1:0);
  620. zval_dtor(op);
  621. op->value.lval = tmp;
  622. break;
  623. default:
  624. zend_error(E_WARNING, "Cannot convert to ordinal value");
  625. zval_dtor(op);
  626. op->value.lval = 0;
  627. break;
  628. }
  629. op->type = IS_LONG;
  630. }
  631. // copied from zend_operators.c and beautified
  632. ZEND_API void convert_to_null(zval *op)
  633. {
  634. zval_dtor(op);
  635. op->type = IS_NULL;
  636. }
  637. // copied from zend_operators.c, slightly modified and beautified
  638. ZEND_API void convert_to_object(zval *op)
  639. {
  640. switch (op->type)
  641. {
  642. /* OBJECTS_FIXME */
  643. case IS_ARRAY:
  644. Z_TYPE_P(op) = IS_OBJECT;
  645. Z_OBJPROP_P(op) = op->value.ht;
  646. Z_OBJCE_P(op) = &zend_standard_class_def;
  647. return;
  648. case IS_OBJECT:
  649. return;
  650. /* OBJECTS_FIXME */
  651. case IS_NULL:
  652. ALLOC_HASHTABLE(Z_OBJPROP_P(op));
  653. zend_hash_init(Z_OBJPROP_P(op), 0, NULL, ZVAL_PTR_DTOR, 0);
  654. Z_OBJCE_P(op) = &zend_standard_class_def;
  655. Z_TYPE_P(op) = IS_OBJECT;
  656. break;
  657. default:
  658. convert_scalar_to_array(op, IS_OBJECT);
  659. break;
  660. }
  661. }
  662. // copied from zend_operators.c, slightly modified and beautified
  663. ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC)
  664. {
  665. long lval;
  666. double dval;
  667. TSRMLS_FETCH();
  668. switch (op->type)
  669. {
  670. case IS_NULL: op->value.str.val = empty_string;
  671. op->value.str.len = 0;
  672. break;
  673. case IS_STRING: break;
  674. case IS_BOOL: if (op->value.lval)
  675. {
  676. op->value.str.val = estrndup_rel("1", 1);
  677. op->value.str.len = 1;
  678. }
  679. else
  680. {
  681. op->value.str.val = empty_string;
  682. op->value.str.len = 0;
  683. }
  684. break;
  685. case IS_RESOURCE:
  686. {
  687. long tmp = op->value.lval;
  688. _zend_list_delete(op->value.lval, tsrm_ls);
  689. op->value.str.val = (char *)emalloc(sizeof("Resource id #") - 1 + MAX_LENGTH_OF_LONG);
  690. op->value.str.len = sprintf(op->value.str.val, "Resource id #%ld", tmp);
  691. break;
  692. }
  693. case IS_LONG: lval = op->value.lval;
  694. op->value.str.val = (char *) emalloc_rel(MAX_LENGTH_OF_LONG + 1);
  695. op->value.str.len = zend_sprintf(op->value.str.val, "%ld", lval); /* SAFE */
  696. break;
  697. case IS_DOUBLE: {
  698. dval = op->value.dval;
  699. op->value.str.val = (char *)emalloc_rel(MAX_LENGTH_OF_DOUBLE + EG_precision + 1);
  700. op->value.str.len = zend_sprintf(op->value.str.val, "%.*G", (int)EG_precision, dval); /* SAFE */
  701. /* %G already handles removing trailing zeros from the fractional part, yay */
  702. break;
  703. }
  704. case IS_ARRAY: zval_dtor(op);
  705. op->value.str.val = estrndup_rel("Array", sizeof("Array") - 1);
  706. op->value.str.len = sizeof("Array") - 1;
  707. zend_error(E_NOTICE, "Array to string conversion");
  708. break;
  709. case IS_OBJECT: zval_dtor(op);
  710. op->value.str.val = estrndup_rel("Object", sizeof("Object") - 1);
  711. op->value.str.len = sizeof("Object") - 1;
  712. zend_error(E_NOTICE, "Object to string conversion");
  713. break;
  714. default: zval_dtor(op);
  715. ZVAL_BOOL(op, 0);
  716. break;
  717. }
  718. op->type = IS_STRING;
  719. }
  720. #elif defined(PHP5TS)
  721. #define convert_object_to_type(op, ctype, conv_func) \
  722. if (Z_OBJ_HT_P(op)->cast_object) { \
  723. zval dst; \
  724. if (Z_OBJ_HT_P(op)->cast_object(op, &dst, ctype TSRMLS_CC) == FAILURE) { \
  725. zend_error(E_RECOVERABLE_ERROR, \
  726. "Object of class %s could not be converted to %s", Z_OBJCE_P(op)->name, \
  727. zend_get_type_by_const(ctype)); \
  728. } else { \
  729. zval_dtor(op); \
  730. Z_TYPE_P(op) = ctype; \
  731. op->value = dst.value; \
  732. } \
  733. } else { \
  734. if(Z_OBJ_HT_P(op)->get) { \
  735. zval *newop = Z_OBJ_HT_P(op)->get(op TSRMLS_CC); \
  736. if(Z_TYPE_P(newop) != IS_OBJECT) { \
  737. /* for safety - avoid loop */ \
  738. zval_dtor(op); \
  739. *op = *newop; \
  740. FREE_ZVAL(newop); \
  741. conv_func(op); \
  742. } \
  743. } \
  744. }
  745. /* Argument parsing API -- andrei */
  746. ZEND_API char *zend_get_type_by_const(int type)
  747. {
  748. switch(type) {
  749. case IS_BOOL:
  750. return "boolean";
  751. case IS_LONG:
  752. return "integer";
  753. case IS_DOUBLE:
  754. return "double";
  755. case IS_STRING:
  756. return "string";
  757. case IS_OBJECT:
  758. return "object";
  759. case IS_RESOURCE:
  760. return "resource";
  761. case IS_NULL:
  762. return "null";
  763. case IS_ARRAY:
  764. return "array";
  765. default:
  766. return "unknown";
  767. }
  768. }
  769. ZEND_API void convert_to_long(zval *op)
  770. {
  771. if ((op)->type != IS_LONG) {
  772. convert_to_long_base(op, 10);
  773. }
  774. }
  775. ZEND_API void convert_to_long_base(zval *op, int base)
  776. {
  777. char *strval;
  778. long tmp;
  779. switch (op->type) {
  780. case IS_NULL:
  781. op->value.lval = 0;
  782. break;
  783. case IS_RESOURCE: {
  784. TSRMLS_FETCH();
  785. zend_list_delete(op->value.lval);
  786. }
  787. /* break missing intentionally */
  788. case IS_BOOL:
  789. case IS_LONG:
  790. break;
  791. case IS_DOUBLE:
  792. DVAL_TO_LVAL(op->value.dval, op->value.lval);
  793. break;
  794. case IS_STRING:
  795. strval = op->value.str.val;
  796. op->value.lval = strtol(strval, NULL, base);
  797. STR_FREE(strval);
  798. break;
  799. case IS_ARRAY:
  800. tmp = (zend_hash_num_elements(op->value.ht)?1:0);
  801. zval_dtor(op);
  802. op->value.lval = tmp;
  803. break;
  804. case IS_OBJECT:
  805. {
  806. int retval = 1;
  807. TSRMLS_FETCH();
  808. convert_object_to_type(op, IS_LONG, convert_to_long);
  809. if (op->type == IS_LONG) {
  810. return;
  811. }
  812. if (EG(ze1_compatibility_mode)) {
  813. HashTable *ht = Z_OBJPROP_P(op);
  814. if (ht) {
  815. retval = (zend_hash_num_elements(ht)?1:0);
  816. }
  817. } else {
  818. zend_error(E_NOTICE, "Object of class %s could not be converted to int", Z_OBJCE_P(op)->name);
  819. }
  820. zval_dtor(op);
  821. ZVAL_LONG(op, retval);
  822. return;
  823. }
  824. default:
  825. zend_error(E_WARNING, "Cannot convert to ordinal value");
  826. zval_dtor(op);
  827. op->value.lval = 0;
  828. break;
  829. }
  830. op->type = IS_LONG;
  831. }
  832. ZEND_API void convert_to_double(zval *op)
  833. {
  834. char *strval;
  835. double tmp;
  836. switch (op->type) {
  837. case IS_NULL:
  838. op->value.dval = 0.0;
  839. break;
  840. case IS_RESOURCE: {
  841. TSRMLS_FETCH();
  842. zend_list_delete(op->value.lval);
  843. }
  844. /* break missing intentionally */
  845. case IS_BOOL:
  846. case IS_LONG:
  847. op->value.dval = (double) op->value.lval;
  848. break;
  849. case IS_DOUBLE:
  850. break;
  851. case IS_STRING:
  852. strval = op->value.str.val;
  853. op->value.dval = zend_strtod(strval, NULL);
  854. STR_FREE(strval);
  855. break;
  856. case IS_ARRAY:
  857. tmp = (zend_hash_num_elements(op->value.ht)?1:0);
  858. zval_dtor(op);
  859. op->value.dval = tmp;
  860. break;
  861. case IS_OBJECT:
  862. {
  863. double retval = 1.0;
  864. TSRMLS_FETCH();
  865. convert_object_to_type(op, IS_DOUBLE, convert_to_double);
  866. if (op->type == IS_DOUBLE) {
  867. return;
  868. }
  869. if (EG(ze1_compatibility_mode)) {
  870. HashTable *ht = Z_OBJPROP_P(op);
  871. if (ht) {
  872. retval = (zend_hash_num_elements(ht)?1.0:0.0);
  873. }
  874. } else {
  875. zend_error(E_NOTICE, "Object of class %s could not be converted to double", Z_OBJCE_P(op)->name);
  876. }
  877. zval_dtor(op);
  878. ZVAL_DOUBLE(op, retval);
  879. break;
  880. }
  881. default:
  882. zend_error(E_WARNING, "Cannot convert to real value (type=%d)", op->type);
  883. zval_dtor(op);
  884. op->value.dval = 0;
  885. break;
  886. }
  887. op->type = IS_DOUBLE;
  888. }
  889. ZEND_API void convert_to_null(zval *op)
  890. {
  891. if (Z_TYPE_P(op) == IS_OBJECT) {
  892. if (Z_OBJ_HT_P(op)->cast_object) {
  893. zval *org;
  894. TSRMLS_FETCH();
  895. ALLOC_ZVAL(org);
  896. *org = *op;
  897. if (Z_OBJ_HT_P(op)->cast_object(org, op, IS_NULL TSRMLS_CC) == SUCCESS) {
  898. zval_dtor(org);
  899. return;
  900. }
  901. *op = *org;
  902. FREE_ZVAL(org);
  903. }
  904. }
  905. zval_dtor(op);
  906. Z_TYPE_P(op) = IS_NULL;
  907. }
  908. ZEND_API void convert_to_boolean(zval *op)
  909. {
  910. char *strval;
  911. int tmp;
  912. switch (op->type) {
  913. case IS_BOOL:
  914. break;
  915. case IS_NULL:
  916. op->value.lval = 0;
  917. break;
  918. case IS_RESOURCE: {
  919. TSRMLS_FETCH();
  920. zend_list_delete(op->value.lval);
  921. }
  922. /* break missing intentionally */
  923. case IS_LONG:
  924. op->value.lval = (op->value.lval ? 1 : 0);
  925. break;
  926. case IS_DOUBLE:
  927. op->value.lval = (op->value.dval ? 1 : 0);
  928. break;
  929. case IS_STRING:
  930. strval = op->value.str.val;
  931. if (op->value.str.len == 0
  932. || (op->value.str.len==1 && op->value.str.val[0]=='0')) {
  933. op->value.lval = 0;
  934. } else {
  935. op->value.lval = 1;
  936. }
  937. STR_FREE(strval);
  938. break;
  939. case IS_ARRAY:
  940. tmp = (zend_hash_num_elements(op->value.ht)?1:0);
  941. zval_dtor(op);
  942. op->value.lval = tmp;
  943. break;
  944. case IS_OBJECT:
  945. {
  946. zend_bool retval = 1;
  947. TSRMLS_FETCH();
  948. convert_object_to_type(op, IS_BOOL, convert_to_boolean);
  949. if (op->type == IS_BOOL) {
  950. return;
  951. }
  952. if (EG(ze1_compatibility_mode)) {
  953. HashTable *ht = Z_OBJPROP_P(op);
  954. if (ht) {
  955. retval = (zend_hash_num_elements(ht)?1:0);
  956. }
  957. }
  958. zval_dtor(op);
  959. ZVAL_BOOL(op, retval);
  960. break;
  961. }
  962. default:
  963. zval_dtor(op);
  964. op->value.lval = 0;
  965. break;
  966. }
  967. op->type = IS_BOOL;
  968. }
  969. ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC)
  970. {
  971. long lval;
  972. double dval;
  973. switch (op->type) {
  974. case IS_NULL:
  975. op->value.str.val = STR_EMPTY_ALLOC();
  976. op->value.str.len = 0;
  977. break;
  978. case IS_STRING:
  979. break;
  980. case IS_BOOL:
  981. if (op->value.lval) {
  982. op->value.str.val = estrndup_rel("1", 1);
  983. op->value.str.len = 1;
  984. } else {
  985. op->value.str.val = STR_EMPTY_ALLOC();
  986. op->value.str.len = 0;
  987. }
  988. break;
  989. case IS_RESOURCE: {
  990. long tmp = op->value.lval;
  991. TSRMLS_FETCH();
  992. zend_list_delete(op->value.lval);
  993. op->value.str.len = zend_spprintf(&op->value.str.val, 0, "Resource id #%ld", tmp);
  994. break;
  995. }
  996. case IS_LONG:
  997. lval = op->value.lval;
  998. op->value.str.len = zend_spprintf(&op->value.str.val, 0, "%ld", lval); /* SAFE */
  999. break;
  1000. case IS_DOUBLE: {
  1001. TSRMLS_FETCH();
  1002. dval = op->value.dval;
  1003. op->value.str.len = zend_spprintf(&op->value.str.val, 0, "%.*G", (int) EG(precision), dval); /* SAFE */
  1004. /* %G already handles removing trailing zeros from the fractional part, yay */
  1005. break;
  1006. }
  1007. case IS_ARRAY:
  1008. zend_error(E_NOTICE, "Array to string conversion");
  1009. zval_dtor(op);
  1010. op->value.str.val = estrndup_rel("Array", sizeof("Array")-1);
  1011. op->value.str.len = sizeof("Array")-1;
  1012. break;
  1013. case IS_OBJECT: {
  1014. TSRMLS_FETCH();
  1015. convert_object_to_type(op, IS_STRING, convert_to_string);
  1016. if (op->type == IS_STRING) {
  1017. return;
  1018. }
  1019. zend_error(E_NOTICE, "Object of class %s to string conversion", Z_OBJCE_P(op)->name);
  1020. zval_dtor(op);
  1021. op->value.str.val = estrndup_rel("Object", sizeof("Object")-1);
  1022. op->value.str.len = sizeof("Object")-1;
  1023. break;
  1024. }
  1025. default:
  1026. zval_dtor(op);
  1027. ZVAL_BOOL(op, 0);
  1028. break;
  1029. }
  1030. op->type = IS_STRING;
  1031. }
  1032. static void convert_scalar_to_array(zval *op, int type)
  1033. {
  1034. zval *entry;
  1035. ALLOC_ZVAL(entry);
  1036. *entry = *op;
  1037. INIT_PZVAL(entry);
  1038. switch (type) {
  1039. case IS_ARRAY:
  1040. ALLOC_HASHTABLE(op->value.ht);
  1041. zend_hash_init(op->value.ht, 0, NULL, ZVAL_PTR_DTOR, 0);
  1042. zend_hash_index_update(op->value.ht, 0, (void *) &entry, sizeof(zval *), NULL);
  1043. op->type = IS_ARRAY;
  1044. break;
  1045. case IS_OBJECT:
  1046. {
  1047. /* OBJECTS_OPTIMIZE */
  1048. TSRMLS_FETCH();
  1049. object_init(op);
  1050. zend_hash_update(Z_OBJPROP_P(op), "scalar", sizeof("scalar"), (void *) &entry, sizeof(zval *), NULL);
  1051. }
  1052. break;
  1053. }
  1054. }
  1055. ZEND_API void convert_to_array(zval *op)
  1056. {
  1057. TSRMLS_FETCH();
  1058. switch (op->type) {
  1059. case IS_ARRAY:
  1060. return;
  1061. break;
  1062. /* OBJECTS_OPTIMIZE */
  1063. case IS_OBJECT:
  1064. {
  1065. zval *tmp;
  1066. HashTable *ht;
  1067. ALLOC_HASHTABLE(ht);
  1068. zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
  1069. if (Z_OBJ_HT_P(op)->get_properties) {
  1070. HashTable *obj_ht = Z_OBJ_HT_P(op)->get_properties(op TSRMLS_CC);
  1071. if(obj_ht) {
  1072. zend_hash_copy(ht, obj_ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
  1073. }
  1074. } else {
  1075. convert_object_to_type(op, IS_ARRAY, convert_to_array);
  1076. if (op->type == IS_ARRAY) {
  1077. zend_hash_destroy(ht);
  1078. FREE_HASHTABLE(ht);
  1079. return;
  1080. }
  1081. }
  1082. zval_dtor(op);
  1083. op->type = IS_ARRAY;
  1084. op->value.ht = ht;
  1085. }
  1086. return;
  1087. case IS_NULL:
  1088. ALLOC_HASHTABLE(op->value.ht);
  1089. zend_hash_init(op->value.ht, 0, NULL, ZVAL_PTR_DTOR, 0);
  1090. op->type = IS_ARRAY;
  1091. break;
  1092. default:
  1093. convert_scalar_to_array(op, IS_ARRAY);
  1094. break;
  1095. }
  1096. }
  1097. ZEND_API void convert_to_object(zval *op)
  1098. {
  1099. switch (op->type) {
  1100. case IS_ARRAY:
  1101. {
  1102. /* OBJECTS_OPTIMIZE */
  1103. TSRMLS_FETCH();
  1104. object_and_properties_init(op, &zend_standard_class_def, op->value.ht);
  1105. return;
  1106. break;
  1107. }
  1108. case IS_OBJECT:
  1109. return;
  1110. case IS_NULL:
  1111. {
  1112. /* OBJECTS_OPTIMIZE */
  1113. TSRMLS_FETCH();
  1114. object_init(op);
  1115. break;
  1116. }
  1117. default:
  1118. convert_scalar_to_array(op, IS_OBJECT);
  1119. break;
  1120. }
  1121. }
  1122. ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC)
  1123. {
  1124. switch (op->type) {
  1125. case IS_STRING:
  1126. {
  1127. char *strval;
  1128. strval = op->value.str.val;
  1129. if ((op->type=is_numeric_string(strval, op->value.str.len, &op->value.lval, &op->value.dval, 1)) == 0) {
  1130. op->value.lval = 0;
  1131. op->type = IS_LONG;
  1132. }
  1133. STR_FREE(strval);
  1134. break;
  1135. }
  1136. case IS_BOOL:
  1137. op->type = IS_LONG;
  1138. break;
  1139. case IS_RESOURCE:
  1140. zend_list_delete(op->value.lval);
  1141. op->type = IS_LONG;
  1142. break;
  1143. case IS_OBJECT:
  1144. convert_to_long_base(op, 10);
  1145. break;
  1146. case IS_NULL:
  1147. op->type = IS_LONG;
  1148. op->value.lval = 0;
  1149. break;
  1150. }
  1151. }
  1152. #endif
  1153. // copied from zend_strtod.c
  1154. ZEND_API double zend_hex_strtod(const char *str, char **endptr)
  1155. {
  1156. const char *s = str;
  1157. char c;
  1158. int any = 0;
  1159. double value = 0;
  1160. if (*s == '0' && (s[1] == 'x' || s[1] == 'X')) {
  1161. s += 2;
  1162. }
  1163. while ((c = *s++)) {
  1164. if (c >= '0' && c <= '9') {
  1165. c -= '0';
  1166. } else if (c >= 'A' && c <= 'F') {
  1167. c -= 'A' - 10;
  1168. } else if (c >= 'a' && c <= 'f') {
  1169. c -= 'a' - 10;
  1170. } else {
  1171. break;
  1172. }
  1173. any = 1;
  1174. value = value * 16 + c;
  1175. }
  1176. if (endptr != NULL) {
  1177. *endptr = (char *)(any ? s - 1 : str);
  1178. }
  1179. return value;
  1180. }
  1181. ZEND_API double zend_oct_strtod(const char *str, char **endptr)
  1182. {
  1183. const char *s = str;
  1184. char c;
  1185. double value = 0;
  1186. int any = 0;
  1187. /* skip leading zero */
  1188. s++;
  1189. while ((c = *s++)) {
  1190. if (c < '0' || c > '7') {
  1191. /* break and return the current value if the number is not well-formed
  1192. * that's what Linux strtol() does
  1193. */
  1194. break;
  1195. }
  1196. value = value * 8 + c - '0';
  1197. any = 1;
  1198. }
  1199. if (endptr != NULL) {
  1200. *endptr = (char *)(any ? s - 1 : str);
  1201. }
  1202. return value;
  1203. }
  1204. // copied from zend_operators.c and beautified
  1205. ZEND_API long zend_atol(const char *str, int str_len)
  1206. {
  1207. long retval;
  1208. if (!str_len) {
  1209. str_len = strlen(str);
  1210. }
  1211. retval = strtol(str, NULL, 0);
  1212. if (str_len>0) {
  1213. switch (str[str_len-1]) {
  1214. case 'g':
  1215. case 'G':
  1216. retval *= 1024;
  1217. /* break intentionally missing */
  1218. case 'm':
  1219. case 'M':
  1220. retval *= 1024;
  1221. /* break intentionally missing */
  1222. case 'k':
  1223. case 'K':
  1224. retval *= 1024;
  1225. break;
  1226. }
  1227. }
  1228. return retval;
  1229. }
  1230. ZEND_API int zend_atoi(const char *str, int str_len)
  1231. {
  1232. int retval;
  1233. if (!str_len) str_len = strlen(str);
  1234. retval = strtol(str, NULL, 0);
  1235. if (str_len > 0)
  1236. {
  1237. switch (str[str_len-1])
  1238. {
  1239. case 'k':
  1240. case 'K': retval *= 1024;
  1241. break;
  1242. case 'm':
  1243. case 'M': retval *= 1048576;
  1244. break;
  1245. }
  1246. }
  1247. return retval;
  1248. }
  1249. // copied from zend_operators.c and beautified
  1250. ZEND_API void zend_str_tolower(char *str, unsigned int length)
  1251. {
  1252. register char *p = str, *end = p + length;
  1253. while (p < end)
  1254. {
  1255. if (*p >= 'A' && *p <= 'Z') *p = (*p)+32;
  1256. p++;
  1257. }
  1258. }
  1259. // copied from zend_operators.c and beautified
  1260. ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length)
  1261. {
  1262. register unsigned char *str = (unsigned char *)source;
  1263. register unsigned char *result = (unsigned char *)dest;
  1264. register unsigned char *end = str + length;
  1265. while (str < end) *result++ = tolower((int)*str++);
  1266. *result = *end;
  1267. return dest;
  1268. }
  1269. // copied from zend_operators.c and beautified
  1270. ZEND_API int zend_binary_strcmp(char *s1, uint len1, char *s2, uint len2)
  1271. {
  1272. int retval;
  1273. retval = memcmp(s1, s2, MIN(len1, len2));
  1274. if (!retval) return (len1 - len2);
  1275. else return retval;
  1276. }
  1277. // copied from zend_operators.c and beautified
  1278. ZEND_API int zend_binary_strncmp(char *s1, uint len1, char *s2, uint len2, uint length)
  1279. {
  1280. int retval;
  1281. retval = memcmp(s1, s2, MIN(length, MIN(len1, len2)));
  1282. if (!retval) return (MIN(length, len1) - MIN(length, len2));
  1283. else return retval;
  1284. }
  1285. // copied from zend_operators.c and beautified
  1286. ZEND_API int zend_binary_strcasecmp(char *s1, uint len1, char *s2, uint len2)
  1287. {
  1288. int len;
  1289. int c1, c2;
  1290. len = MIN(len1, len2);
  1291. while (len--)
  1292. {
  1293. c1 = tolower(*s1++);
  1294. c2 = tolower(*s2++);
  1295. if (c1 != c2) return c1 - c2;
  1296. }
  1297. return len1 - len2;
  1298. }
  1299. // copied from zend_operators.c and beautified
  1300. ZEND_API int zend_binary_strncasecmp(char *s1, uint len1, char *s2, uint len2, uint length)
  1301. {
  1302. int len;
  1303. int c1, c2;
  1304. len = MIN(length, MIN(len1, len2));
  1305. while (len--)
  1306. {
  1307. c1 = tolower(*s1++);
  1308. c2 = tolower(*s2++);
  1309. if (c1 != c2) return c1 - c2;
  1310. }
  1311. return MIN(length, len1) - MIN(length, len2);
  1312. }
  1313. // copied from zend_operators.c and beautified
  1314. ZEND_API int zend_binary_zval_strcmp(zval *s1, zval *s2)
  1315. {
  1316. return zend_binary_strcmp(s1->value.str.val, s1->value.str.len, s2->value.str.val, s2->value.str.len);
  1317. }
  1318. // copied from zend_operators.c and beautified
  1319. ZEND_API int zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3)
  1320. {
  1321. return zend_binary_strncmp(s1->value.str.val, s1->value.str.len, s2->value.str.val, s2->value.str.len, s3->value.lval);
  1322. }
  1323. // copied from zend_operators.c and beautified
  1324. ZEND_API int zend_binary_zval_strcasecmp(zval *s1, zval *s2)
  1325. {
  1326. return zend_binary_strcasecmp(s1->value.str.val, s1->value.str.len, s2->value.str.val, s2->value.str.len);
  1327. }
  1328. // copied from zend_operators.c and beautified
  1329. ZEND_API int zend_binary_zval_strncasecmp(zval *s1, zval *s2, zval *s3)
  1330. {
  1331. return zend_binary_strncasecmp(s1->value.str.val, s1->value.str.len, s2->value.str.val, s2->value.str.len, s3->value.lval);
  1332. }
  1333. // copied from zend_operators.c, slightly modified and beautified
  1334. ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2)
  1335. {
  1336. int ret1, ret2;
  1337. long lval1, lval2;
  1338. double dval1, dval2;
  1339. if ((ret1 = is_numeric_string(s1->value.str.val, s1->value.str.len, &lval1, &dval1, 0)) &&
  1340. (ret2 = is_numeric_string(s2->value.str.val, s2->value.str.len, &lval2, &dval2, 0)))
  1341. {
  1342. if (ret1 == IS_DOUBLE || ret2 == IS_DOUBLE)
  1343. {
  1344. if (ret1 != IS_DOUBLE) dval1 = strtod(s1->value.str.val, NULL);
  1345. else if (ret2 != IS_DOUBLE) dval2 = strtod(s2->value.str.val, NULL);
  1346. result->value.dval = dval1 - dval2;
  1347. result->value.lval = ZEND_NORMALIZE_BOOL(result->value.dval);
  1348. result->type = IS_LONG;
  1349. }
  1350. else
  1351. {
  1352. /* they both have to be long's */
  1353. result->value.lval = lval1 - lval2;
  1354. result->value.lval = ZEND_NORMALIZE_BOOL(result->value.lval);
  1355. result->type = IS_LONG;
  1356. }
  1357. }
  1358. else
  1359. {
  1360. result->value.lval = zend_binary_zval_strcmp(s1, s2);
  1361. result->value.lval = ZEND_NORMALIZE_BOOL(result->value.lval);
  1362. result->type = IS_LONG;
  1363. }
  1364. return;
  1365. }
  1366. // copied from zend_operators.c, slightly modified and beautified
  1367. int hash_zval_compare_function(const zval **z1, const zval **z2 TSRMLS_DC)
  1368. {
  1369. zval result;
  1370. if (compare_function(&result, (zval *)*z1, (zval *)*z2 TSRMLS_CC) == FAILURE) return 1;
  1371. return result.value.lval;
  1372. }
  1373. // copied from zend_operators.c and beautified
  1374. ZEND_API void zend_compare_symbol_tables(zval *result, HashTable *ht1, HashTable *ht2 TSRMLS_DC)
  1375. {
  1376. result->type = IS_LONG;
  1377. result->value.lval = zend_hash_compare(ht1, ht2, (compare_func_t)hash_zval_compare_function, 0 TSRMLS_CC);
  1378. }
  1379. // copied from zend_operators.c and beautified
  1380. ZEND_API void zend_compare_arrays(zval *result, zval *a1, zval *a2 TSRMLS_DC)
  1381. {
  1382. zend_compare_symbol_tables(result, a1->value.ht, a2->value.ht TSRMLS_CC);
  1383. }
  1384. // copied from zend_operators.c
  1385. ZEND_API int zend_compare_symbol_tables_i(HashTable *ht1, HashTable *ht2 TSRMLS_DC)
  1386. {
  1387. return zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC);
  1388. }
  1389. // copied from zend_operators.c and beautified
  1390. ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC)
  1391. {
  1392. /* OBJECTS_FIXME */
  1393. if (Z_OBJCE_P(o1) != Z_OBJCE_P(o2))
  1394. {
  1395. result->value.lval = 1; /* Comparing objects of different types is pretty much meaningless */
  1396. result->type = IS_LONG;
  1397. return;
  1398. }
  1399. zend_compare_symbol_tables(result, Z_OBJPROP_P(o1), Z_OBJPROP_P(o2) TSRMLS_CC);
  1400. }
  1401. // copied from zend_operators.c and beautified
  1402. ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
  1403. {
  1404. zval op1_copy, op2_copy;
  1405. int use_copy1, use_copy2;
  1406. zend_make_printable_zval(op1, &op1_copy, &use_copy1);
  1407. zend_make_printable_zval(op2, &op2_copy, &use_copy2);
  1408. if (use_copy1) op1 = &op1_copy;
  1409. if (use_copy2) op2 = &op2_copy;
  1410. result->value.lval = zend_binary_zval_strcmp(op1, op2);
  1411. result->type = IS_LONG;
  1412. if (use_copy1) zval_dtor(op1);
  1413. if (use_copy2) zval_dtor(op2);
  1414. return SUCCESS;
  1415. }
  1416. // copied from zend_operators.c and beautified
  1417. ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
  1418. {
  1419. zval op1_copy, op2_copy;
  1420. int use_copy1, use_copy2;
  1421. zend_make_printable_zval(op1, &op1_copy, &use_copy1);
  1422. zend_make_printable_zval(op2, &op2_copy, &use_copy2);
  1423. if (use_copy1) op1 = &op1_copy;
  1424. if (use_copy2) op2 = &op2_copy;
  1425. result->value.lval = strcoll(op1->value.str.val, op2->value.str.val);
  1426. result->type = IS_LONG;
  1427. if (use_copy1) zval_dtor(op1);
  1428. if (use_copy2) zval_dtor(op2);
  1429. return SUCCESS;
  1430. }
  1431. // copied from zend_operators.c and beautified
  1432. ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
  1433. {
  1434. zval op1_copy, op2_copy;
  1435. op1_copy = *op1;
  1436. zval_copy_ctor(&op1_copy);
  1437. op2_copy = *op2;
  1438. zval_copy_ctor(&op2_copy);
  1439. convert_to_double(&op1_copy);
  1440. convert_to_double(&op2_copy);
  1441. result->value.lval = ZEND_NORMALIZE_BOOL(op1_copy.value.dval - op2_copy.value.dval);
  1442. result->type = IS_LONG;
  1443. return SUCCESS;
  1444. }
  1445. // copied from zend_operators.c and beautified
  1446. ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
  1447. {
  1448. zval op1_copy, op2_copy;
  1449. if ((op1->type == IS_NULL && op2->type == IS_STRING) ||
  1450. (op2->type == IS_NULL && op1->type == IS_STRING))
  1451. {
  1452. if (op1->type == IS_NULL)
  1453. {
  1454. result->type = IS_LONG;
  1455. result->value.lval = zend_binary_strcmp("", 0, op2->value.str.val, op2->value.str.len);
  1456. return SUCCESS;
  1457. }
  1458. else
  1459. {
  1460. result->type = IS_LONG;
  1461. result->value.lval = zend_binary_strcmp(op1->value.str.val, op1->value.str.len, "", 0);
  1462. return SUCCESS;
  1463. }
  1464. }
  1465. if (op1->type == IS_STRING && op2->type == IS_STRING)
  1466. {
  1467. zendi_smart_strcmp(result, op1, op2);
  1468. return SUCCESS;
  1469. }
  1470. if (op1->type == IS_BOOL || op2->type == IS_BOOL ||
  1471. op1->type == IS_NULL || op2->type == IS_NULL)
  1472. {
  1473. zendi_convert_to_boolean(op1, op1_copy, result);
  1474. zendi_convert_to_boolean(op2, op2_copy, result);
  1475. result->type = IS_LONG;
  1476. result->value.lval = ZEND_NORMALIZE_BOOL(op1->value.lval - op2->value.lval);
  1477. return SUCCESS;
  1478. }
  1479. zendi_convert_scalar_to_number(op1, op1_copy, result);
  1480. zendi_convert_scalar_to_number(op2, op2_copy, result);
  1481. if (op1->type == IS_LONG && op2->type == IS_LONG) {
  1482. result->type = IS_LONG;
  1483. result->value.lval = op1->value.lval > op2->value.lval ? 1 : (op1->value.lval < op2->value.lval ? -1 : 0);
  1484. return SUCCESS;
  1485. }
  1486. if ((op1->type == IS_DOUBLE || op1->type == IS_LONG) &&
  1487. (op2->type == IS_DOUBLE || op2->type == IS_LONG))
  1488. {
  1489. result->value.dval = (op1->type == IS_LONG ? (double) op1->value.lval : op1->value.dval) -
  1490. (op2->type == IS_LONG ? (double) op2->value.lval : op2->value.dval);
  1491. result->value.lval = ZEND_NORMALIZE_BOOL(result->value.dval);
  1492. result->type = IS_LONG;
  1493. return SUCCESS;
  1494. }
  1495. if (op1->type == IS_ARRAY && op2->type == IS_ARRAY)
  1496. {
  1497. zend_compare_arrays(result, op1, op2 TSRMLS_CC);
  1498. return SUCCESS;
  1499. }
  1500. if (op1->type == IS_OBJECT && op2->type == IS_OBJECT)
  1501. {
  1502. zend_compare_objects(result, op1, op2 TSRMLS_CC);
  1503. return SUCCESS;
  1504. }
  1505. if (op1->type == IS_ARRAY)
  1506. {
  1507. result->value.lval = 1;
  1508. result->type = IS_LONG;
  1509. return SUCCESS;
  1510. }
  1511. if (op2->type == IS_ARRAY)
  1512. {
  1513. result->value.lval = -1;
  1514. result->type = IS_LONG;
  1515. return SUCCESS;
  1516. }
  1517. if (op1->type == IS_OBJECT)
  1518. {
  1519. result->value.lval = 1;
  1520. result->type = IS_LONG;
  1521. return SUCCESS;
  1522. }
  1523. if (op2->type == IS_OBJECT)
  1524. {
  1525. result->value.lval = -1;
  1526. result->type = IS_LONG;
  1527. return SUCCESS;
  1528. }
  1529. ZVAL_BOOL(result, 0);
  1530. return FAILURE;
  1531. }
  1532. // copied from zend_operators.c and beautified
  1533. ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_copy)
  1534. {
  1535. if (expr->type == IS_STRING)
  1536. {
  1537. *use_copy = 0;
  1538. return;
  1539. }
  1540. switch (expr->type)
  1541. {
  1542. case IS_NULL:
  1543. expr_copy->value.str.len = 0;
  1544. expr_copy->value.str.val = empty_string;
  1545. break;
  1546. case IS_BOOL:
  1547. if (expr->value.lval)
  1548. {
  1549. expr_copy->value.str.len = 1;
  1550. expr_copy->value.str.val = estrndup("1", 1);
  1551. }
  1552. else
  1553. {
  1554. expr_copy->value.str.len = 0;
  1555. expr_copy->value.str.val = empty_string;
  1556. }
  1557. break;
  1558. case IS_RESOURCE:
  1559. expr_copy->value.str.val = (char *)emalloc(sizeof("Resource id #") -1 + MAX_LENGTH_OF_LONG);
  1560. expr_copy->value.str.len = sprintf(expr_copy->value.str.val, "Resource id #%ld", expr->value.lval);
  1561. break;
  1562. case IS_ARRAY:
  1563. expr_copy->value.str.len = sizeof("Array") - 1;
  1564. expr_copy->value.str.val = estrndup("Array", expr_copy->value.str.len);
  1565. break;
  1566. case IS_OBJECT:
  1567. expr_copy->value.str.len = sizeof("Object") - 1;
  1568. expr_copy->value.str.val = estrndup("Object", expr_copy->value.str.len);
  1569. break;
  1570. case IS_DOUBLE:
  1571. *expr_copy = *expr;
  1572. zval_copy_ctor(expr_copy);
  1573. zend_locale_sprintf_double(expr_copy ZEND_FILE_LINE_CC);
  1574. break;
  1575. default:
  1576. *expr_copy = *expr;
  1577. zval_copy_ctor(expr_copy);
  1578. convert_to_string(expr_copy);
  1579. break;
  1580. }
  1581. expr_copy->type = IS_STRING;
  1582. *use_copy = 1;
  1583. }
  1584. // copied from zend_operators.c and beautified
  1585. #ifdef PHP4TS
  1586. ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC)
  1587. {
  1588. double dval = op->value.dval;
  1589. TSRMLS_FETCH();
  1590. op->value.str.val = (char *)emalloc_rel(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1);
  1591. sprintf(op->value.str.val, "%.*G", (int)EG(precision), dval);
  1592. op->value.str.len = strlen(op->value.str.val);
  1593. if (EG(float_separator)[0] != '.')
  1594. {
  1595. char *p = op->value.str.val;
  1596. if ((p = strchr(p, '.'))) *p = EG(float_separator)[0];
  1597. }
  1598. }
  1599. #elif defined(PHP5TS)
  1600. ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC)
  1601. {
  1602. TSRMLS_FETCH();
  1603. op->value.str.len = zend_spprintf(&op->value.str.val, 0, "%.*G", (int) EG(precision), (double)op->value.dval);
  1604. }
  1605. #endif
  1606. // copied from strlcpy.c and slightly modified
  1607. /*
  1608. * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
  1609. * All rights reserved.
  1610. *
  1611. * Redistribution and use in source and binary forms, with or without
  1612. * modification, are permitted provided that the following conditions
  1613. * are met:
  1614. * 1. Redistributions of source code must retain the above copyright
  1615. * notice, this list of conditions and the following disclaimer.
  1616. * 2. Redistributions in binary form must reproduce the above copyright
  1617. * notice, this list of conditions and the following disclaimer in the
  1618. * documentation and/or other materials provided with the distribution.
  1619. * 3. The name of the author may not be used to endorse or promote products
  1620. * derived from this software without specific prior written permission.
  1621. *
  1622. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
  1623. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  1624. * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  1625. * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  1626. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  1627. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  1628. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  1629. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  1630. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  1631. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  1632. */
  1633. /*
  1634. * Copy src to string dst of size siz. At most siz-1 characters
  1635. * will be copied. Always NUL terminates (unless siz == 0).
  1636. * Returns strlen(src); if retval >= siz, truncation occurred.
  1637. */
  1638. ZEND_API size_t php_strlcpy(char *dst, const char *src, size_t siz)
  1639. {
  1640. register char *d = dst;
  1641. register const char *s = src;
  1642. register size_t n = siz;
  1643. /* Copy as many bytes as will fit */
  1644. if (n != 0 && --n != 0) {
  1645. do {
  1646. if ((*d++ = *s++) == 0)
  1647. break;
  1648. } while (--n != 0);
  1649. }
  1650. /* Not enough room in dst, add NUL and traverse rest of src */
  1651. if (n == 0) {
  1652. if (siz != 0)
  1653. *d = '\0'; /* NUL-terminate dst */
  1654. while (*s++)
  1655. ;
  1656. }
  1657. return(s - src - 1); /* count does not include NUL */
  1658. }
  1659. // copied from zend_operators.c and beautified
  1660. ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
  1661. {
  1662. zval op1_copy, op2_copy;
  1663. if (op1->type == IS_STRING && op2->type == IS_STRING)
  1664. {
  1665. zval *longer, *shorter;
  1666. char *result_str;
  1667. int i, result_len;
  1668. if (op1->value.str.len >= op2->value.str.len)
  1669. {
  1670. longer = op1;
  1671. shorter = op2;
  1672. }
  1673. else
  1674. {
  1675. longer = op2;
  1676. shorter = op1;
  1677. }
  1678. result->type = IS_STRING;
  1679. result_len = shorter->value.str.len;
  1680. result_str = estrndup(shorter->value.str.val, shorter->value.str.len);
  1681. for (i = 0; i < shorter->value.str.len; i++)
  1682. {
  1683. result_str[i] &= longer->value.str.val[i];
  1684. }
  1685. if (result == op1)
  1686. {
  1687. STR_FREE(result->value.str.val);
  1688. }
  1689. result->value.str.val = result_str;
  1690. result->value.str.len = result_len;
  1691. return SUCCESS;
  1692. }
  1693. zendi_convert_to_long(op1, op1_copy, result);
  1694. zendi_convert_to_long(op2, op2_copy, result);
  1695. result->type = IS_LONG;
  1696. result->value.lval = op1->value.lval & op2->value.lval;
  1697. return SUCCESS;
  1698. }
  1699. // copied from zend_operators.c and beautified
  1700. ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC)
  1701. {
  1702. zval op1_copy = *op1;
  1703. op1 = &op1_copy;
  1704. if (op1->type == IS_DOUBLE)
  1705. {
  1706. op1->value.lval = (long)op1->value.dval;
  1707. op1->type = IS_LONG;
  1708. }
  1709. if (op1->type == IS_LONG)
  1710. {
  1711. result->value.lval = ~op1->value.lval;
  1712. result->type = IS_LONG;
  1713. return SUCCESS;
  1714. }
  1715. if (op1->type == IS_STRING)
  1716. {
  1717. int i;
  1718. result->type = IS_STRING;
  1719. result->value.str.val = estrndup(op1->value.str.val, op1->value.str.len);
  1720. result->value.str.len = op1->value.str.len;
  1721. for (i = 0; i < op1->value.str.len; i++)
  1722. {
  1723. result->value.str.val[i] = ~op1->value.str.val[i];
  1724. }
  1725. return SUCCESS;
  1726. }
  1727. zend_error(E_ERROR, "Unsupported operand types");
  1728. return FAILURE; /* unknown datatype */
  1729. }
  1730. // copied from zend_operators.c and beautified
  1731. ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
  1732. {
  1733. zval op1_copy, op2_copy;
  1734. if (op1->type == IS_STRING && op2->type == IS_STRING)
  1735. {
  1736. zval *longer, *shorter;
  1737. char *result_str;
  1738. int i, result_len;
  1739. if (op1->value.str.len >= op2->value.str.len)
  1740. {
  1741. longer = op1;
  1742. shorter = op2;
  1743. }

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