PageRenderTime 73ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/xdebug_var.c

http://github.com/derickr/xdebug
C | 2912 lines | 2781 code | 90 blank | 41 comment | 193 complexity | 60df2dfa2e3b85949f700adcfd32b3f7 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Xdebug |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2002-2016 Derick Rethans |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 1.0 of the Xdebug license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available at through the world-wide-web at |
  10. | http://xdebug.derickrethans.nl/license.php |
  11. | If you did not receive a copy of the Xdebug license and are unable |
  12. | to obtain it through the world-wide-web, please send a note to |
  13. | xdebug@derickrethans.nl so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Derick Rethans <derick@xdebug.org> |
  16. +----------------------------------------------------------------------+
  17. */
  18. #include "php.h"
  19. #include "ext/standard/php_string.h"
  20. #include "ext/standard/url.h"
  21. #include "zend.h"
  22. #include "zend_extensions.h"
  23. #if PHP_VERSION_ID >= 70000
  24. # include "ext/standard/php_smart_string.h"
  25. # include "zend_smart_str.h"
  26. #else
  27. # include "ext/standard/php_smart_str.h"
  28. #endif
  29. #include "php_xdebug.h"
  30. #include "xdebug_compat.h"
  31. #include "xdebug_private.h"
  32. #include "xdebug_mm.h"
  33. #include "xdebug_var.h"
  34. #include "xdebug_xml.h"
  35. /* Set correct int format to use */
  36. #if PHP_VERSION_ID >= 70000
  37. # include "Zend/zend_long.h"
  38. # if SIZEOF_ZEND_LONG == 4
  39. # define XDEBUG_INT_FMT "%ld"
  40. # else
  41. # define XDEBUG_INT_FMT "%lld"
  42. # endif
  43. #else
  44. # define XDEBUG_INT_FMT "%ld"
  45. #endif
  46. ZEND_EXTERN_MODULE_GLOBALS(xdebug)
  47. HashTable *xdebug_objdebug_pp(zval **zval_pp, int *is_tmp TSRMLS_DC)
  48. {
  49. zval dzval = **zval_pp;
  50. HashTable *tmp;
  51. if (!XG(in_debug_info) && Z_OBJ_HANDLER(dzval, get_debug_info)) {
  52. zend_bool old_trace = XG(do_trace);
  53. #if PHP_VERSION_ID >= 70000
  54. zend_object *orig_exception;
  55. #else
  56. zval *orig_exception;
  57. #endif
  58. XG(do_trace) = 0;
  59. XG(in_debug_info) = 1;
  60. orig_exception = EG(exception);
  61. EG(exception) = NULL;
  62. tmp = Z_OBJ_HANDLER(dzval, get_debug_info)(&dzval, is_tmp TSRMLS_CC);
  63. XG(in_debug_info) = 0;
  64. XG(do_trace) = old_trace;
  65. EG(exception) = orig_exception;
  66. return tmp;
  67. } else {
  68. *is_tmp = 0;
  69. if (Z_OBJ_HANDLER(dzval, get_properties)) {
  70. return Z_OBJPROP(dzval);
  71. }
  72. }
  73. return NULL;
  74. }
  75. char* xdebug_error_type_simple(int type)
  76. {
  77. switch (type) {
  78. case E_ERROR:
  79. case E_CORE_ERROR:
  80. case E_COMPILE_ERROR:
  81. case E_USER_ERROR:
  82. return xdstrdup("fatal-error");
  83. break;
  84. case E_RECOVERABLE_ERROR:
  85. return xdstrdup("catchable-fatal-error");
  86. break;
  87. case E_WARNING:
  88. case E_CORE_WARNING:
  89. case E_COMPILE_WARNING:
  90. case E_USER_WARNING:
  91. return xdstrdup("warning");
  92. break;
  93. case E_PARSE:
  94. return xdstrdup("parse-error");
  95. break;
  96. case E_NOTICE:
  97. case E_USER_NOTICE:
  98. return xdstrdup("notice");
  99. break;
  100. case E_STRICT:
  101. return xdstrdup("strict-standards");
  102. break;
  103. case E_DEPRECATED:
  104. case E_USER_DEPRECATED:
  105. return xdstrdup("deprecated");
  106. break;
  107. case 0:
  108. return xdstrdup("xdebug");
  109. break;
  110. default:
  111. return xdstrdup("unknown-error");
  112. break;
  113. }
  114. }
  115. char* xdebug_error_type(int type)
  116. {
  117. switch (type) {
  118. case E_ERROR:
  119. case E_CORE_ERROR:
  120. case E_COMPILE_ERROR:
  121. case E_USER_ERROR:
  122. return xdstrdup("Fatal error");
  123. break;
  124. case E_RECOVERABLE_ERROR:
  125. return xdstrdup("Catchable fatal error");
  126. break;
  127. case E_WARNING:
  128. case E_CORE_WARNING:
  129. case E_COMPILE_WARNING:
  130. case E_USER_WARNING:
  131. return xdstrdup("Warning");
  132. break;
  133. case E_PARSE:
  134. return xdstrdup("Parse error");
  135. break;
  136. case E_NOTICE:
  137. case E_USER_NOTICE:
  138. return xdstrdup("Notice");
  139. break;
  140. case E_STRICT:
  141. return xdstrdup("Strict standards");
  142. break;
  143. case E_DEPRECATED:
  144. case E_USER_DEPRECATED:
  145. return xdstrdup("Deprecated");
  146. break;
  147. case 0:
  148. return xdstrdup("Xdebug");
  149. break;
  150. default:
  151. return xdstrdup("Unknown error");
  152. break;
  153. }
  154. }
  155. /*************************************************************************************************************************************/
  156. #if PHP_VERSION_ID >= 70000
  157. # define T(offset) (*(union _temp_variable *)((char*)zdata->current_execute_data->Ts + offset))
  158. #elif PHP_VERSION_ID >= 50500
  159. # define T(offset) (*EX_TMP_VAR(zdata, offset))
  160. #else
  161. # define T(offset) (*(temp_variable *)((char*)zdata->Ts + offset))
  162. #endif
  163. #if PHP_VERSION_ID >= 70000
  164. zval *xdebug_get_zval(zend_execute_data *zdata, int node_type, const znode_op *node, int *is_var)
  165. {
  166. zend_free_op should_free;
  167. return zend_get_zval_ptr(node_type, node, zdata, &should_free, BP_VAR_IS);
  168. }
  169. #else
  170. zval *xdebug_get_zval(zend_execute_data *zdata, int node_type, const znode_op *node, int *is_var)
  171. {
  172. switch (node_type) {
  173. case IS_CONST:
  174. #if PHP_VERSION_ID >= 50300
  175. return node->zv;
  176. #else
  177. return &node->u.constant;
  178. #endif
  179. break;
  180. case IS_TMP_VAR:
  181. *is_var = 1;
  182. return &T(node->var).tmp_var;
  183. break;
  184. case IS_VAR:
  185. *is_var = 1;
  186. if (T(node->var).var.ptr) {
  187. return T(node->var).var.ptr;
  188. }
  189. break;
  190. case IS_CV: {
  191. zval **tmp;
  192. tmp = zend_get_compiled_variable_value(zdata, node->constant);
  193. if (tmp) {
  194. return *tmp;
  195. }
  196. break;
  197. }
  198. case IS_UNUSED:
  199. fprintf(stderr, "\nIS_UNUSED\n");
  200. break;
  201. default:
  202. fprintf(stderr, "\ndefault %d\n", node_type);
  203. break;
  204. }
  205. *is_var = 1;
  206. return NULL;
  207. }
  208. #endif
  209. /*****************************************************************************
  210. ** PHP Variable related utility functions
  211. */
  212. /*****************************************************************************
  213. ** Data returning functions
  214. */
  215. #define XF_ST_ROOT 0
  216. #define XF_ST_ARRAY_INDEX_NUM 1
  217. #define XF_ST_ARRAY_INDEX_ASSOC 2
  218. #define XF_ST_OBJ_PROPERTY 3
  219. #define XF_ST_STATIC_ROOT 4
  220. #define XF_ST_STATIC_PROPERTY 5
  221. inline static HashTable *fetch_ht_from_zval(zval *z TSRMLS_DC)
  222. {
  223. #if PHP_VERSION_ID >= 70000
  224. if (Z_TYPE_P(z) == IS_REFERENCE) {
  225. z = &z->value.ref->val;
  226. }
  227. #endif
  228. switch (Z_TYPE_P(z)) {
  229. case IS_ARRAY:
  230. return Z_ARRVAL_P(z);
  231. break;
  232. case IS_OBJECT:
  233. return Z_OBJPROP_P(z);
  234. break;
  235. }
  236. return NULL;
  237. }
  238. #if PHP_VERSION_ID >= 70000
  239. inline static char *fetch_classname_from_zval(zval *z, int *length, zend_class_entry **ce TSRMLS_DC)
  240. {
  241. zend_string *class_name;
  242. if (Z_TYPE_P(z) != IS_OBJECT) {
  243. return NULL;
  244. }
  245. class_name = Z_OBJ_HANDLER_P(z, get_class_name)(Z_OBJ_P(z));
  246. *ce = Z_OBJCE_P(z);
  247. *length = class_name->len;
  248. return estrdup(class_name->val);
  249. }
  250. #else
  251. inline static char *fetch_classname_from_zval(zval *z, int *length, zend_class_entry **ce TSRMLS_DC)
  252. {
  253. char *name;
  254. SIZETorZUINT name_len;
  255. zend_class_entry *tmp_ce;
  256. if (Z_TYPE_P(z) != IS_OBJECT) {
  257. return NULL;
  258. }
  259. tmp_ce = zend_get_class_entry(z TSRMLS_CC);
  260. if (Z_OBJ_HT_P(z)->get_class_name == NULL ||
  261. Z_OBJ_HT_P(z)->get_class_name(z, (const char **) &name, &name_len, 0 TSRMLS_CC) != SUCCESS) {
  262. if (!tmp_ce) {
  263. return NULL;
  264. }
  265. *length = tmp_ce->name_length;
  266. *ce = tmp_ce;
  267. return estrdup(tmp_ce->name);
  268. } else {
  269. *ce = tmp_ce;
  270. }
  271. *length = name_len;
  272. return name;
  273. }
  274. #endif
  275. static char* prepare_search_key(char *name, unsigned int *name_length, char *prefix, int prefix_length)
  276. {
  277. char *element;
  278. int extra_length = 0;
  279. if (prefix_length) {
  280. if (prefix[0] == '*') {
  281. extra_length = 3;
  282. } else {
  283. extra_length = 2 + prefix_length;
  284. }
  285. }
  286. element = malloc(*name_length + 1 + extra_length);
  287. memset(element, 0, *name_length + 1 + extra_length);
  288. if (extra_length) {
  289. memcpy(element + 1, prefix, extra_length - 2);
  290. }
  291. memcpy(element + extra_length, name, *name_length);
  292. *name_length += extra_length;
  293. return element;
  294. }
  295. static zval *get_arrayobject_storage(zval *parent TSRMLS_DC)
  296. {
  297. int is_temp;
  298. HashTable *properties = Z_OBJDEBUG_P(parent, is_temp);
  299. #if PHP_VERSION_ID >= 70000
  300. zval *tmp = NULL;
  301. if ((tmp = zend_hash_str_find(properties, "\0ArrayObject\0storage", sizeof("*ArrayObject*storage") - 1)) != NULL) {
  302. return tmp;
  303. #else
  304. zval **tmp = NULL;
  305. if (zend_hash_find(properties, "\0ArrayObject\0storage", sizeof("*ArrayObject*storage"), (void **) &tmp) == SUCCESS) {
  306. return *tmp;
  307. #endif
  308. }
  309. return NULL;
  310. }
  311. static zval *get_splobjectstorage_storage(zval *parent TSRMLS_DC)
  312. {
  313. int is_temp;
  314. HashTable *properties = Z_OBJDEBUG_P(parent, is_temp);
  315. #if PHP_VERSION_ID >= 70000
  316. zval *tmp = NULL;
  317. if ((tmp = zend_hash_str_find(properties, "\0SplObjectStorage\0storage", sizeof("*SplObjectStorage*storage") - 1)) != NULL) {
  318. return tmp;
  319. #else
  320. zval **tmp = NULL;
  321. if (zend_hash_find(properties, "\0SplObjectStorage\0storage", sizeof("*SplObjectStorage*storage"), (void **) &tmp) == SUCCESS) {
  322. return *tmp;
  323. #endif
  324. }
  325. return NULL;
  326. }
  327. static zval *get_arrayiterator_storage(zval *parent TSRMLS_DC)
  328. {
  329. int is_temp;
  330. HashTable *properties = Z_OBJDEBUG_P(parent, is_temp);
  331. #if PHP_VERSION_ID >= 70000
  332. zval *tmp = NULL;
  333. if ((tmp = zend_hash_str_find(properties, "\0ArrayIterator\0storage", sizeof("*ArrayIterator*storage") - 1)) != NULL) {
  334. return tmp;
  335. #else
  336. zval **tmp = NULL;
  337. if (zend_hash_find(properties, "\0ArrayIterator\0storage", sizeof("*ArrayIterator*storage"), (void **) &tmp) == SUCCESS) {
  338. return *tmp;
  339. #endif
  340. }
  341. return NULL;
  342. }
  343. static zval* fetch_zval_from_symbol_table(zval *parent, char* name, unsigned int name_length, int type, char* ccn, int ccnl, zend_class_entry *cce TSRMLS_DC)
  344. {
  345. HashTable *ht = NULL;
  346. zval *retval_p = NULL;
  347. #if PHP_VERSION_ID < 70000
  348. zval **retval_pp = NULL;
  349. #endif
  350. char *element = NULL;
  351. unsigned int element_length = name_length;
  352. zend_property_info *zpp;
  353. if (parent) {
  354. ht = fetch_ht_from_zval(parent TSRMLS_CC);
  355. }
  356. switch (type) {
  357. case XF_ST_STATIC_ROOT:
  358. case XF_ST_STATIC_PROPERTY:
  359. /* First we try a public,private,protected property */
  360. element = prepare_search_key(name, &element_length, "", 0);
  361. #if PHP_VERSION_ID >= 70000
  362. if (cce && &cce->properties_info && ((zpp = zend_hash_str_find_ptr(&cce->properties_info, element, element_length)) != NULL) && cce->static_members_table) {
  363. retval_p = &cce->static_members_table[zpp->offset];
  364. #else
  365. if (cce && &cce->properties_info && zend_hash_find(&cce->properties_info, element, element_length + 1, (void **) &zpp) == SUCCESS) {
  366. retval_p = cce->static_members_table[zpp->offset];
  367. #endif
  368. goto cleanup;
  369. }
  370. element_length = name_length;
  371. /* Then we try to see whether the first char is * and use the part between * and * as class name for the private property */
  372. if (name[0] == '*') {
  373. char *secondStar;
  374. secondStar = strstr(name + 1, "*");
  375. if (secondStar) {
  376. free(element);
  377. element_length = name_length - (secondStar + 1 - name);
  378. element = prepare_search_key(secondStar + 1, &element_length, "", 0);
  379. #if PHP_VERSION_ID >= 70000
  380. if (cce && &cce->properties_info && ((zpp = zend_hash_str_find_ptr(&cce->properties_info, element, element_length)) != NULL)) {
  381. retval_p = &cce->static_members_table[zpp->offset];
  382. #else
  383. if (cce && &cce->properties_info && zend_hash_find(&cce->properties_info, element, element_length + 1, (void **) &zpp) == SUCCESS) {
  384. retval_p = cce->static_members_table[zpp->offset];
  385. #endif
  386. goto cleanup;
  387. }
  388. }
  389. }
  390. break;
  391. case XF_ST_ROOT:
  392. /* Check for compiled vars */
  393. element = prepare_search_key(name, &element_length, "", 0);
  394. #if PHP_VERSION_ID >= 70000
  395. if (XG(active_execute_data) && XG(active_execute_data)->func) {
  396. #else
  397. if (XG(active_execute_data) && XG(active_execute_data)->op_array) {
  398. #endif
  399. int i = 0;
  400. #if PHP_VERSION_ID >= 70000
  401. hashULONG hash_value = zend_inline_hash_func(element, element_length);
  402. zend_op_array *opa = &XG(active_execute_data)->func->op_array;
  403. #else
  404. hashULONG hash_value = zend_inline_hash_func(element, element_length + 1);
  405. zend_op_array *opa = XG(active_execute_data)->op_array;
  406. #endif
  407. zval **CV;
  408. while (i < opa->last_var) {
  409. #if PHP_VERSION_ID >= 70000
  410. if (ZSTR_H(opa->vars[i]) == hash_value &&
  411. ZSTR_LEN(opa->vars[i]) == element_length &&
  412. strncmp(STR_NAME_VAL(opa->vars[i]), element, element_length) == 0)
  413. #else
  414. if (opa->vars[i].hash_value == hash_value &&
  415. opa->vars[i].name_len == (int) element_length &&
  416. strcmp(STR_NAME_VAL(opa->vars[i].name), element) == 0)
  417. #endif
  418. {
  419. #if PHP_VERSION_ID >= 70000
  420. zval *CV_z = ZEND_CALL_VAR_NUM(XG(active_execute_data), i);
  421. CV = &CV_z;
  422. #elif PHP_VERSION_ID >= 50500
  423. CV = (*EX_CV_NUM(XG(active_execute_data), i));
  424. #else
  425. CV = XG(active_execute_data)->CVs[i];
  426. #endif
  427. if (CV) {
  428. retval_p = *CV;
  429. goto cleanup;
  430. }
  431. }
  432. i++;
  433. }
  434. }
  435. free(element);
  436. ht = XG(active_symbol_table);
  437. /* break intentionally missing */
  438. case XF_ST_ARRAY_INDEX_ASSOC:
  439. element = prepare_search_key(name, &name_length, "", 0);
  440. /* Handle "this" in a different way */
  441. if (type == XF_ST_ROOT && strcmp("this", element) == 0) {
  442. if (XG(This)) {
  443. retval_p = XG(This);
  444. } else {
  445. retval_p = NULL;
  446. }
  447. goto cleanup;
  448. }
  449. #if PHP_VERSION_ID >= 70000
  450. if (ht && ((retval_p = zend_hash_str_find(ht, element, name_length)) != NULL)) {
  451. #else
  452. if (ht && zend_hash_find(ht, element, name_length + 1, (void **) &retval_pp) == SUCCESS) {
  453. retval_p = *retval_pp;
  454. #endif
  455. goto cleanup;
  456. }
  457. break;
  458. case XF_ST_ARRAY_INDEX_NUM:
  459. element = prepare_search_key(name, &name_length, "", 0);
  460. #if PHP_VERSION_ID >= 70000
  461. if (ht && ((retval_p = zend_hash_index_find(ht, strtoull(element, NULL, 10))) != NULL)) {
  462. #else
  463. if (ht && zend_hash_index_find(ht, strtoul(element, NULL, 10), (void **) &retval_pp) == SUCCESS) {
  464. retval_p = *retval_pp;
  465. #endif
  466. goto cleanup;
  467. }
  468. break;
  469. case XF_ST_OBJ_PROPERTY:
  470. /* First we try an object handler */
  471. if (cce) {
  472. zval *tmp_val;
  473. #if PHP_VERSION_ID >= 70000
  474. zval dummy;
  475. tmp_val = zend_read_property(cce, parent, name, name_length, 0, &dummy);
  476. if (tmp_val && tmp_val != &EG(uninitialized_zval)) {
  477. #else
  478. tmp_val = zend_read_property(cce, parent, name, name_length, 0 TSRMLS_CC);
  479. if (tmp_val && tmp_val != EG(uninitialized_zval_ptr)) {
  480. #endif
  481. retval_p = tmp_val;
  482. goto cleanup;
  483. }
  484. if (EG(exception)) {
  485. zend_clear_exception(TSRMLS_C);
  486. }
  487. }
  488. /* Then we try a public property */
  489. element = prepare_search_key(name, &element_length, "", 0);
  490. #if PHP_VERSION_ID >= 70000
  491. if (ht && ((retval_p = zend_symtable_str_find(ht, element, element_length)) != NULL)) {
  492. #else
  493. if (ht && zend_symtable_find(ht, element, element_length + 1, (void **) &retval_pp) == SUCCESS) {
  494. retval_p = *retval_pp;
  495. #endif
  496. goto cleanup;
  497. }
  498. element_length = name_length;
  499. /* Then we try it again as protected property */
  500. free(element);
  501. element = prepare_search_key(name, &element_length, "*", 1);
  502. #if PHP_VERSION_ID >= 70000
  503. if (ht && ((retval_p = zend_hash_str_find(ht, element, element_length)) != NULL)) {
  504. #else
  505. if (ht && zend_hash_find(ht, element, element_length + 1, (void **) &retval_pp) == SUCCESS) {
  506. retval_p = *retval_pp;
  507. #endif
  508. goto cleanup;
  509. }
  510. element_length = name_length;
  511. /* Then we try it again as private property */
  512. free(element);
  513. element = prepare_search_key(name, &element_length, ccn, ccnl);
  514. #if PHP_VERSION_ID >= 70000
  515. if (ht && ((retval_p = zend_hash_str_find(ht, element, element_length)) != NULL)) {
  516. #else
  517. if (ht && zend_hash_find(ht, element, element_length + 1, (void **) &retval_pp) == SUCCESS) {
  518. retval_p = *retval_pp;
  519. #endif
  520. goto cleanup;
  521. }
  522. element_length = name_length;
  523. /* All right, time for a mega hack. It's SplObjectStorage access time! */
  524. if (strncmp(ccn, "SplObjectStorage", ccnl) == 0 && strncmp(name, "storage", name_length) == 0) {
  525. element = NULL;
  526. if ((retval_p = get_splobjectstorage_storage(parent TSRMLS_CC)) != NULL) {
  527. if (retval_p) {
  528. goto cleanup;
  529. }
  530. }
  531. }
  532. /* Then we try to see whether the first char is * and use the part between * and * as class name for the private property */
  533. if (name[0] == '*') {
  534. char *secondStar;
  535. secondStar = strstr(name + 1, "*");
  536. if (secondStar) {
  537. free(element);
  538. element_length = name_length - (secondStar + 1 - name);
  539. /* All right, time for a mega hack. It's ArrayObject access time! */
  540. if (strncmp(name + 1, "ArrayObject", secondStar - name - 1) == 0 && strncmp(secondStar + 1, "storage", element_length) == 0) {
  541. element = NULL;
  542. if ((retval_p = get_arrayobject_storage(parent TSRMLS_CC)) != NULL) {
  543. if (retval_p) {
  544. goto cleanup;
  545. }
  546. }
  547. }
  548. /* All right, time for a mega hack. It's ArrayIterator access time! */
  549. if (strncmp(name + 1, "ArrayIterator", secondStar - name - 1) == 0 && strncmp(secondStar + 1, "storage", element_length) == 0) {
  550. element = NULL;
  551. if ((retval_p = get_arrayiterator_storage(parent TSRMLS_CC)) != NULL) {
  552. if (retval_p) {
  553. goto cleanup;
  554. }
  555. }
  556. }
  557. /* The normal one */
  558. element = prepare_search_key(secondStar + 1, &element_length, name + 1, secondStar - name - 1);
  559. #if PHP_VERSION_ID >= 70000
  560. if (ht && ((retval_p = zend_hash_str_find(ht, element, element_length)) != NULL)) {
  561. #else
  562. if (ht && zend_hash_find(ht, element, element_length + 1, (void **) &retval_pp) == SUCCESS) {
  563. retval_p = *retval_pp;
  564. #endif
  565. goto cleanup;
  566. }
  567. }
  568. }
  569. break;
  570. }
  571. cleanup:
  572. if (element) {
  573. free(element);
  574. }
  575. return retval_p;
  576. }
  577. zval* xdebug_get_php_symbol(char* name TSRMLS_DC)
  578. {
  579. int found = -1;
  580. int state = 0;
  581. char **p = &name;
  582. char *keyword = NULL, *keyword_end = NULL;
  583. int type = XF_ST_ROOT;
  584. zval *retval = NULL;
  585. char *current_classname = NULL;
  586. zend_class_entry *current_ce = NULL;
  587. int cc_length = 0;
  588. char quotechar = 0;
  589. do {
  590. if (*p[0] == '\0') {
  591. found = 0;
  592. } else {
  593. switch (state) {
  594. case 0:
  595. if (*p[0] == '$') {
  596. keyword = *p + 1;
  597. break;
  598. }
  599. if (*p[0] == ':') { /* special tricks */
  600. keyword = *p;
  601. state = 7;
  602. break;
  603. }
  604. keyword = *p;
  605. state = 1;
  606. /* break intentionally missing */
  607. case 1:
  608. if (*p[0] == '[') {
  609. keyword_end = *p;
  610. if (keyword) {
  611. retval = fetch_zval_from_symbol_table(retval, keyword, keyword_end - keyword, type, current_classname, cc_length, current_ce TSRMLS_CC);
  612. if (current_classname) {
  613. efree(current_classname);
  614. }
  615. current_classname = NULL;
  616. cc_length = 0;
  617. current_ce = NULL;
  618. keyword = NULL;
  619. }
  620. state = 3;
  621. } else if (*p[0] == '-') {
  622. keyword_end = *p;
  623. if (keyword) {
  624. retval = fetch_zval_from_symbol_table(retval, keyword, keyword_end - keyword, type, current_classname, cc_length, current_ce TSRMLS_CC);
  625. if (current_classname) {
  626. efree(current_classname);
  627. }
  628. current_classname = NULL;
  629. cc_length = 0;
  630. current_ce = NULL;
  631. if (retval) {
  632. current_classname = fetch_classname_from_zval(retval, &cc_length, &current_ce TSRMLS_CC);
  633. }
  634. keyword = NULL;
  635. }
  636. state = 2;
  637. type = XF_ST_OBJ_PROPERTY;
  638. } else if (*p[0] == ':') {
  639. keyword_end = *p;
  640. if (keyword) {
  641. retval = fetch_zval_from_symbol_table(retval, keyword, keyword_end - keyword, type, current_classname, cc_length, current_ce TSRMLS_CC);
  642. if (current_classname) {
  643. efree(current_classname);
  644. }
  645. current_classname = NULL;
  646. cc_length = 0;
  647. if (retval) {
  648. current_classname = fetch_classname_from_zval(retval, &cc_length, &current_ce TSRMLS_CC);
  649. }
  650. keyword = NULL;
  651. }
  652. state = 8;
  653. type = XF_ST_STATIC_PROPERTY;
  654. }
  655. break;
  656. case 2:
  657. if (*p[0] != '>') {
  658. keyword = *p;
  659. state = 1;
  660. }
  661. break;
  662. case 8:
  663. if (*p[0] != ':') {
  664. keyword = *p;
  665. state = 1;
  666. }
  667. break;
  668. case 3: /* Parsing in [...] */
  669. /* Associative arrays */
  670. if (*p[0] == '\'' || *p[0] == '"') {
  671. state = 4;
  672. keyword = *p + 1;
  673. quotechar = *p[0];
  674. type = XF_ST_ARRAY_INDEX_ASSOC;
  675. }
  676. /* Numerical index */
  677. if (*p[0] >= '0' && *p[0] <= '9') {
  678. cc_length = 0;
  679. state = 6;
  680. keyword = *p;
  681. type = XF_ST_ARRAY_INDEX_NUM;
  682. }
  683. /* Numerical index starting with a - */
  684. if (*p[0] == '-') {
  685. state = 9;
  686. keyword = *p;
  687. }
  688. break;
  689. case 9:
  690. /* Numerical index starting with a - */
  691. if (*p[0] >= '0' && *p[0] <= '9') {
  692. state = 6;
  693. type = XF_ST_ARRAY_INDEX_NUM;
  694. }
  695. break;
  696. case 4:
  697. if (*p[0] == quotechar) {
  698. quotechar = 0;
  699. state = 5;
  700. keyword_end = *p;
  701. retval = fetch_zval_from_symbol_table(retval, keyword, keyword_end - keyword, type, current_classname, cc_length, current_ce TSRMLS_CC);
  702. if (current_classname) {
  703. efree(current_classname);
  704. }
  705. current_classname = NULL;
  706. cc_length = 0;
  707. if (retval) {
  708. current_classname = fetch_classname_from_zval(retval, &cc_length, &current_ce TSRMLS_CC);
  709. }
  710. keyword = NULL;
  711. }
  712. break;
  713. case 5:
  714. if (*p[0] == ']') {
  715. state = 1;
  716. }
  717. break;
  718. case 6:
  719. if (*p[0] == ']') {
  720. state = 1;
  721. keyword_end = *p;
  722. retval = fetch_zval_from_symbol_table(retval, keyword, keyword_end - keyword, type, current_classname, cc_length, current_ce TSRMLS_CC);
  723. if (current_classname) {
  724. efree(current_classname);
  725. }
  726. current_classname = NULL;
  727. cc_length = 0;
  728. if (retval) {
  729. current_classname = fetch_classname_from_zval(retval, &cc_length, &current_ce TSRMLS_CC);
  730. }
  731. keyword = NULL;
  732. }
  733. break;
  734. case 7: /* special cases, started with a ":" */
  735. if (*p[0] == ':') {
  736. state = 1;
  737. keyword_end = *p;
  738. if (strncmp(keyword, "::", 2) == 0 && XG(active_fse)->function.class) { /* static class properties */
  739. zend_class_entry *ce = xdebug_fetch_class(XG(active_fse)->function.class, strlen(XG(active_fse)->function.class), ZEND_FETCH_CLASS_SELF TSRMLS_CC);
  740. current_classname = estrdup(STR_NAME_VAL(ce->name));
  741. cc_length = strlen(STR_NAME_VAL(ce->name));
  742. current_ce = ce;
  743. keyword = *p + 1;
  744. type = XF_ST_STATIC_ROOT;
  745. } else {
  746. keyword = NULL;
  747. }
  748. }
  749. break;
  750. }
  751. (*p)++;
  752. }
  753. } while (found < 0);
  754. if (keyword != NULL) {
  755. retval = fetch_zval_from_symbol_table(retval, keyword, *p - keyword, type, current_classname, cc_length, current_ce TSRMLS_CC);
  756. }
  757. if (current_classname) {
  758. efree(current_classname);
  759. }
  760. return retval;
  761. }
  762. char* xdebug_get_property_info(char *mangled_property, int mangled_len, char **property_name, char **class_name)
  763. {
  764. const char *prop_name, *cls_name;
  765. #if PHP_VERSION_ID >= 70000
  766. zend_string *i_mangled = zend_string_init(mangled_property, mangled_len - 1, 0);
  767. zend_unmangle_property_name(i_mangled, &cls_name, &prop_name);
  768. #else
  769. zend_unmangle_property_name(mangled_property, mangled_len, &cls_name, &prop_name);
  770. #endif
  771. *property_name = (char *) xdstrdup(prop_name);
  772. *class_name = cls_name ? xdstrdup(cls_name) : NULL;
  773. #if PHP_VERSION_ID >= 70000
  774. zend_string_release(i_mangled);
  775. #endif
  776. if (*class_name) {
  777. if (*class_name[0] == '*') {
  778. return "protected";
  779. } else {
  780. return "private";
  781. }
  782. } else {
  783. return "public";
  784. }
  785. }
  786. #define XDEBUG_MAX_INT 2147483647
  787. xdebug_var_export_options* xdebug_var_export_options_from_ini(TSRMLS_D)
  788. {
  789. xdebug_var_export_options *options;
  790. options = xdmalloc(sizeof(xdebug_var_export_options));
  791. options->max_children = XG(display_max_children);
  792. options->max_data = XG(display_max_data);
  793. options->max_depth = XG(display_max_depth);
  794. options->show_hidden = 0;
  795. options->show_location = XG(overload_var_dump) > 1;
  796. if (options->max_children == -1 || options->max_children > XDEBUG_MAX_INT) {
  797. options->max_children = XDEBUG_MAX_INT;
  798. } else if (options->max_children < 1) {
  799. options->max_children = 0;
  800. }
  801. if (options->max_data == -1 || options->max_data > XDEBUG_MAX_INT) {
  802. options->max_data = XDEBUG_MAX_INT;
  803. } else if (options->max_data < 1) {
  804. options->max_data = 0;
  805. }
  806. if (options->max_depth == -1 || options->max_depth > 1023) {
  807. options->max_depth = 1023;
  808. } else if (options->max_depth < 1) {
  809. options->max_depth = 0;
  810. }
  811. options->runtime = (xdebug_var_runtime_page*) xdmalloc((options->max_depth + 1) * sizeof(xdebug_var_runtime_page));
  812. options->no_decoration = 0;
  813. return options;
  814. }
  815. xdebug_var_export_options xdebug_var_nolimit_options = { XDEBUG_MAX_INT, XDEBUG_MAX_INT, 1023, 1, 0, NULL, 0 };
  816. xdebug_var_export_options* xdebug_var_get_nolimit_options(TSRMLS_D)
  817. {
  818. return &xdebug_var_nolimit_options;
  819. }
  820. /*****************************************************************************
  821. ** Normal variable printing routines
  822. */
  823. #if PHP_VERSION_ID >= 70000
  824. static int xdebug_array_element_export(zval *zv_nptr, zend_ulong index, zend_string *hash_key, int level, xdebug_str *str, int debug_zval, xdebug_var_export_options *options)
  825. {
  826. zval **zv = &zv_nptr;
  827. #else
  828. static int xdebug_array_element_export(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
  829. {
  830. int level = va_arg(args, int);
  831. xdebug_str *str = va_arg(args, struct xdebug_str*);
  832. int debug_zval = va_arg(args, int);
  833. xdebug_var_export_options *options = va_arg(args, xdebug_var_export_options*);
  834. #endif
  835. if (options->runtime[level].current_element_nr >= options->runtime[level].start_element_nr &&
  836. options->runtime[level].current_element_nr < options->runtime[level].end_element_nr)
  837. {
  838. if (HASH_KEY_IS_NUMERIC(hash_key)) { /* numeric key */
  839. xdebug_str_add(str, xdebug_sprintf("%ld => ", HASH_APPLY_NUMERIC(hash_key)), 1);
  840. } else { /* string key */
  841. SIZETorINT newlen = 0;
  842. char *tmp, *tmp2;
  843. tmp = xdebug_str_to_str((char*) HASH_APPLY_KEY_VAL(hash_key), HASH_APPLY_KEY_LEN(hash_key), "'", 1, "\\'", 2, &newlen);
  844. tmp2 = xdebug_str_to_str(tmp, newlen - 1, "\0", 1, "\\0", 2, &newlen);
  845. if (tmp) {
  846. efree(tmp);
  847. }
  848. xdebug_str_addl(str, "'", 1, 0);
  849. if (tmp2) {
  850. xdebug_str_addl(str, tmp2, newlen, 0);
  851. efree(tmp2);
  852. }
  853. xdebug_str_add(str, "' => ", 0);
  854. }
  855. xdebug_var_export(zv, str, level + 2, debug_zval, options TSRMLS_CC);
  856. xdebug_str_addl(str, ", ", 2, 0);
  857. }
  858. if (options->runtime[level].current_element_nr == options->runtime[level].end_element_nr) {
  859. xdebug_str_addl(str, "..., ", 5, 0);
  860. }
  861. options->runtime[level].current_element_nr++;
  862. return 0;
  863. }
  864. #if PHP_VERSION_ID >= 70000
  865. static int xdebug_object_element_export(zval *zv_nptr, zend_ulong index, zend_string *hash_key, int level, xdebug_str *str, int debug_zval, xdebug_var_export_options *options, char *class_name)
  866. {
  867. zval **zv = &zv_nptr;
  868. #else
  869. static int xdebug_object_element_export(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
  870. {
  871. int level = va_arg(args, int);
  872. xdebug_str *str = va_arg(args, struct xdebug_str*);
  873. int debug_zval = va_arg(args, int);
  874. xdebug_var_export_options *options = va_arg(args, xdebug_var_export_options*);
  875. char *class_name = va_arg(args, char*);
  876. #endif
  877. if (options->runtime[level].current_element_nr >= options->runtime[level].start_element_nr &&
  878. options->runtime[level].current_element_nr < options->runtime[level].end_element_nr)
  879. {
  880. if (!HASH_KEY_IS_NUMERIC(hash_key)) {
  881. char *prop_name, *modifier, *prop_class_name;
  882. modifier = xdebug_get_property_info((char*) HASH_APPLY_KEY_VAL(hash_key), HASH_APPLY_KEY_LEN(hash_key), &prop_name, &prop_class_name);
  883. if (strcmp(modifier, "private") != 0 || strcmp(class_name, prop_class_name) == 0) {
  884. xdebug_str_add(str, xdebug_sprintf("%s $%s = ", modifier, prop_name), 1);
  885. } else {
  886. xdebug_str_add(str, xdebug_sprintf("%s ${%s}:%s = ", modifier, prop_class_name, prop_name), 1);
  887. }
  888. xdfree(prop_name);
  889. xdfree(prop_class_name);
  890. } else {
  891. xdebug_str_add(str, xdebug_sprintf("public $%d = ", HASH_APPLY_NUMERIC(hash_key)), 1);
  892. }
  893. xdebug_var_export(zv, str, level + 2, debug_zval, options TSRMLS_CC);
  894. xdebug_str_addl(str, "; ", 2, 0);
  895. }
  896. if (options->runtime[level].current_element_nr == options->runtime[level].end_element_nr) {
  897. xdebug_str_addl(str, "...; ", 5, 0);
  898. }
  899. options->runtime[level].current_element_nr++;
  900. return 0;
  901. }
  902. void xdebug_var_export(zval **struc, xdebug_str *str, int level, int debug_zval, xdebug_var_export_options *options TSRMLS_DC)
  903. {
  904. HashTable *myht;
  905. char* tmp_str;
  906. int is_temp;
  907. #if PHP_VERSION_ID >= 70000
  908. zend_ulong num;
  909. zend_string *key;
  910. zval *val;
  911. zval *tmpz;
  912. #endif
  913. if (!struc || !(*struc)) {
  914. return;
  915. }
  916. #if PHP_VERSION_ID >= 70000
  917. if (debug_zval) {
  918. if (Z_TYPE_P(*struc) >= IS_STRING && Z_TYPE_P(*struc) != IS_INDIRECT) {
  919. xdebug_str_add(str, xdebug_sprintf("(refcount=%d, is_ref=%d)=", (*struc)->value.counted->gc.refcount, Z_TYPE_P(*struc) == IS_REFERENCE), 1);
  920. } else {
  921. xdebug_str_add(str, "(refcount=0, is_ref=0)=", 0);
  922. }
  923. }
  924. if (Z_TYPE_P(*struc) == IS_REFERENCE) {
  925. tmpz = &((*struc)->value.ref->val);
  926. struc = &tmpz;
  927. }
  928. #else
  929. if (debug_zval) {
  930. xdebug_str_add(str, xdebug_sprintf("(refcount=%d, is_ref=%d)=", (*struc)->refcount__gc, (*struc)->is_ref__gc), 1);
  931. }
  932. #endif
  933. switch (Z_TYPE_P(*struc)) {
  934. #if PHP_VERSION_ID >= 70000
  935. case IS_TRUE:
  936. case IS_FALSE:
  937. xdebug_str_add(str, xdebug_sprintf("%s", Z_TYPE_P(*struc) == IS_TRUE ? "TRUE" : "FALSE"), 1);
  938. break;
  939. #else
  940. case IS_BOOL:
  941. xdebug_str_add(str, xdebug_sprintf("%s", Z_LVAL_P(*struc) ? "TRUE" : "FALSE"), 1);
  942. break;
  943. #endif
  944. case IS_NULL:
  945. xdebug_str_addl(str, "NULL", 4, 0);
  946. break;
  947. case IS_LONG:
  948. xdebug_str_add(str, xdebug_sprintf(XDEBUG_INT_FMT, Z_LVAL_P(*struc)), 1);
  949. break;
  950. case IS_DOUBLE:
  951. xdebug_str_add(str, xdebug_sprintf("%.*G", (int) EG(precision), Z_DVAL_P(*struc)), 1);
  952. break;
  953. case IS_STRING: {
  954. #if PHP_VERSION_ID >= 70000
  955. zend_string *i_string = zend_string_init(Z_STRVAL_P(*struc), Z_STRLEN_P(*struc), 0);
  956. zend_string *tmp_zstr;
  957. tmp_zstr = php_addcslashes(i_string, 0, "'\\\0..\37", 7);
  958. tmp_str = estrndup(tmp_zstr->val, tmp_zstr->len);
  959. zend_string_release(tmp_zstr);
  960. zend_string_release(i_string);
  961. #else
  962. int tmp_len;
  963. tmp_str = php_addcslashes(Z_STRVAL_P(*struc), Z_STRLEN_P(*struc), &tmp_len, 0, "'\\\0..\37", 7 TSRMLS_CC);
  964. #endif
  965. if (options->no_decoration) {
  966. xdebug_str_add(str, tmp_str, 0);
  967. } else if ((size_t) Z_STRLEN_P(*struc) <= (size_t) options->max_data) {
  968. xdebug_str_add(str, xdebug_sprintf("'%s'", tmp_str), 1);
  969. } else {
  970. xdebug_str_addl(str, "'", 1, 0);
  971. xdebug_str_addl(str, xdebug_sprintf("%s", tmp_str), options->max_data, 1);
  972. xdebug_str_addl(str, "...'", 4, 0);
  973. }
  974. efree(tmp_str);
  975. } break;
  976. case IS_ARRAY:
  977. myht = Z_ARRVAL_P(*struc);
  978. if (XDEBUG_APPLY_COUNT(myht) < 1) {
  979. xdebug_str_addl(str, "array (", 7, 0);
  980. if (level <= options->max_depth) {
  981. options->runtime[level].current_element_nr = 0;
  982. options->runtime[level].start_element_nr = 0;
  983. options->runtime[level].end_element_nr = options->max_children;
  984. #if PHP_VERSION_ID >= 70000
  985. ZEND_HASH_INC_APPLY_COUNT(myht);
  986. ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, val) {
  987. xdebug_array_element_export(val, num, key, level, str, debug_zval, options);
  988. } ZEND_HASH_FOREACH_END();
  989. ZEND_HASH_DEC_APPLY_COUNT(myht);
  990. #else
  991. zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) xdebug_array_element_export, 4, level, str, debug_zval, options);
  992. #endif
  993. /* Remove the ", " at the end of the string */
  994. if (myht->nNumOfElements > 0) {
  995. xdebug_str_chop(str, 2);
  996. }
  997. } else {
  998. xdebug_str_addl(str, "...", 3, 0);
  999. }
  1000. xdebug_str_addl(str, ")", 1, 0);
  1001. } else {
  1002. xdebug_str_addl(str, "...", 3, 0);
  1003. }
  1004. break;
  1005. case IS_OBJECT:
  1006. myht = xdebug_objdebug_pp(struc, &is_temp TSRMLS_CC);
  1007. if (XDEBUG_APPLY_COUNT(myht) < 1) {
  1008. char *class_name = (char*) STR_NAME_VAL(Z_OBJCE_P(*struc)->name);
  1009. xdebug_str_add(str, xdebug_sprintf("class %s { ", class_name), 1);
  1010. if (level <= options->max_depth) {
  1011. options->runtime[level].current_element_nr = 0;
  1012. options->runtime[level].start_element_nr = 0;
  1013. options->runtime[level].end_element_nr = options->max_children;
  1014. #if PHP_VERSION_ID >= 70000
  1015. ZEND_HASH_INC_APPLY_COUNT(myht);
  1016. ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, val) {
  1017. xdebug_object_element_export(val, num, key, level, str, debug_zval, options, class_name);
  1018. } ZEND_HASH_FOREACH_END();
  1019. ZEND_HASH_DEC_APPLY_COUNT(myht);
  1020. #else
  1021. zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) xdebug_object_element_export, 5, level, str, debug_zval, options, class_name);
  1022. #endif
  1023. /* Remove the ", " at the end of the string */
  1024. if (myht->nNumOfElements > 0) {
  1025. xdebug_str_chop(str, 2);
  1026. }
  1027. } else {
  1028. xdebug_str_addl(str, "...", 3, 0);
  1029. }
  1030. xdebug_str_addl(str, " }", 2, 0);
  1031. } else {
  1032. xdebug_str_addl(str, "...", 3, 0);
  1033. }
  1034. if (is_temp) {
  1035. zend_hash_destroy(myht);
  1036. efree(myht);
  1037. }
  1038. break;
  1039. case IS_RESOURCE: {
  1040. char *type_name;
  1041. #if PHP_VERSION_ID >= 70000
  1042. type_name = (char *) zend_rsrc_list_get_rsrc_type(Z_RES_P(*struc) TSRMLS_CC);
  1043. xdebug_str_add(str, xdebug_sprintf("resource(%ld) of type (%s)", Z_RES_P(*struc)->handle, type_name ? type_name : "Unknown"), 1);
  1044. #else
  1045. type_name = (char *) zend_rsrc_list_get_rsrc_type(Z_LVAL_P(*struc) TSRMLS_CC);
  1046. xdebug_str_add(str, xdebug_sprintf("resource(%ld) of type (%s)", Z_LVAL_P(*struc), type_name ? type_name : "Unknown"), 1);
  1047. #endif
  1048. break;
  1049. }
  1050. #if PHP_VERSION_ID >= 70000
  1051. case IS_UNDEF:
  1052. xdebug_str_addl(str, "*uninitialized*", sizeof("*uninitialized*") - 1, 0);
  1053. break;
  1054. #endif
  1055. default:
  1056. xdebug_str_addl(str, "NFC", 3, 0);
  1057. break;
  1058. }
  1059. }
  1060. char* xdebug_get_zval_value(zval *val, int debug_zval, xdebug_var_export_options *options)
  1061. {
  1062. xdebug_str str = XDEBUG_STR_INITIALIZER;
  1063. int default_options = 0;
  1064. TSRMLS_FETCH();
  1065. if (!options) {
  1066. options = xdebug_var_export_options_from_ini(TSRMLS_C);
  1067. default_options = 1;
  1068. }
  1069. xdebug_var_export(&val, (xdebug_str*) &str, 1, debug_zval, options TSRMLS_CC);
  1070. if (default_options) {
  1071. xdfree(options->runtime);
  1072. xdfree(options);
  1073. }
  1074. return str.d;
  1075. }
  1076. static void xdebug_var_synopsis(zval **struc, xdebug_str *str, int level, int debug_zval, xdebug_var_export_options *options TSRMLS_DC)
  1077. {
  1078. HashTable *myht;
  1079. #if PHP_VERSION_ID >= 70000
  1080. zval *tmpz;
  1081. #endif
  1082. if (!struc || !(*struc)) {
  1083. return;
  1084. }
  1085. #if PHP_VERSION_ID >= 70000
  1086. if (debug_zval) {
  1087. if (Z_TYPE_P(*struc) >= IS_STRING && Z_TYPE_P(*struc) != IS_INDIRECT) {
  1088. xdebug_str_add(str, xdebug_sprintf("(refcount=%d, is_ref=%d)=", (*struc)->value.counted->gc.refcount, Z_TYPE_P(*struc) == IS_REFERENCE), 1);
  1089. } else {
  1090. xdebug_str_add(str, "(refcount=0, is_ref=0)=", 0);
  1091. }
  1092. }
  1093. if (Z_TYPE_P(*struc) == IS_REFERENCE) {
  1094. tmpz = &((*struc)->value.ref->val);
  1095. struc = &tmpz;
  1096. }
  1097. #else
  1098. if (debug_zval) {
  1099. xdebug_str_add(str, xdebug_sprintf("(refcount=%d, is_ref=%d)=", (*struc)->refcount__gc, (*struc)->is_ref__gc), 1);
  1100. }
  1101. #endif
  1102. switch (Z_TYPE_P(*struc)) {
  1103. #if PHP_VERSION_ID >= 70000
  1104. case IS_TRUE:
  1105. xdebug_str_addl(str, "true", 4, 0);
  1106. break;
  1107. case IS_FALSE:
  1108. xdebug_str_addl(str, "false", 5, 0);
  1109. break;
  1110. #else
  1111. case IS_BOOL:
  1112. xdebug_str_addl(str, "bool", 4, 0);
  1113. break;
  1114. #endif
  1115. case IS_NULL:
  1116. xdebug_str_addl(str, "null", 4, 0);
  1117. break;
  1118. case IS_LONG:
  1119. xdebug_str_addl(str, "long", 4, 0);
  1120. break;
  1121. case IS_DOUBLE:
  1122. xdebug_str_addl(str, "double", 6, 0);
  1123. break;
  1124. case IS_STRING:
  1125. xdebug_str_add(str, xdebug_sprintf("string(%d)", Z_STRLEN_P(*struc)), 1);
  1126. break;
  1127. case IS_ARRAY:
  1128. myht = Z_ARRVAL_P(*struc);
  1129. xdebug_str_add(str, xdebug_sprintf("array(%d)", myht->nNumOfElements), 1);
  1130. break;
  1131. case IS_OBJECT: {
  1132. xdebug_str_add(str, xdebug_sprintf("class %s", STR_NAME_VAL(Z_OBJCE_P(*struc)->name)), 1);
  1133. break;
  1134. }
  1135. case IS_RESOURCE: {
  1136. char *type_name;
  1137. #if PHP_VERSION_ID >= 70000
  1138. type_name = (char *) zend_rsrc_list_get_rsrc_type(Z_RES_P(*struc) TSRMLS_CC);
  1139. xdebug_str_add(str, xdebug_sprintf("resource(%ld) of type (%s)", Z_RES_P(*struc)->handle, type_name ? type_name : "Unknown"), 1);
  1140. #else
  1141. type_name = (char *) zend_rsrc_list_get_rsrc_type(Z_LVAL_P(*struc) TSRMLS_CC);
  1142. xdebug_str_add(str, xdebug_sprintf("resource(%ld) of type (%s)", Z_LVAL_P(*struc), type_name ? type_name : "Unknown"), 1);
  1143. #endif
  1144. break;
  1145. }
  1146. #if PHP_VERSION_ID >= 70000
  1147. case IS_UNDEF:
  1148. xdebug_str_addl(str, "*uninitialized*", sizeof("*uninitialized*") - 1, 0);
  1149. break;
  1150. #endif
  1151. default:
  1152. xdebug_str_addl(str, "NFC", 3, 0);
  1153. break;
  1154. }
  1155. }
  1156. char* xdebug_get_zval_synopsis(zval *val, int debug_zval, xdebug_var_export_options *options)
  1157. {
  1158. xdebug_str str = XDEBUG_STR_INITIALIZER;
  1159. int default_options = 0;
  1160. TSRMLS_FETCH();
  1161. if (!options) {
  1162. options = xdebug_var_export_options_from_ini(TSRMLS_C);
  1163. default_options = 1;
  1164. }
  1165. xdebug_var_synopsis(&val, (xdebug_str*) &str, 1, debug_zval, options TSRMLS_CC);
  1166. if (default_options) {
  1167. xdfree(options->runtime);
  1168. xdfree(options);
  1169. }
  1170. return str.d;
  1171. }
  1172. /*****************************************************************************
  1173. ** Plain text/ANSI coloured variable printing routines
  1174. */
  1175. #define ANSI_COLOR_POINTER (mode == 1 ? "" : "")
  1176. #define ANSI_COLOR_BOOL (mode == 1 ? "" : "")
  1177. #define ANSI_COLOR_LONG (mode == 1 ? "" : "")
  1178. #define ANSI_COLOR_NULL (mode == 1 ? "" : "")
  1179. #define ANSI_COLOR_DOUBLE (mode == 1 ? "" : "")
  1180. #define ANSI_COLOR_STRING (mode == 1 ? "" : "")
  1181. #define ANSI_COLOR_EMPTY (mode == 1 ? "" : "")
  1182. #define ANSI_COLOR_ARRAY (mode == 1 ? "" : "")
  1183. #define ANSI_COLOR_OBJECT (mode == 1 ? "" : "")
  1184. #define ANSI_COLOR_RESOURCE (mode == 1 ? "" : "")
  1185. #define ANSI_COLOR_MODIFIER (mode == 1 ? "" : "")
  1186. #define ANSI_COLOR_RESET (mode == 1 ? "" : "")
  1187. #define ANSI_COLOR_BOLD (mode == 1 ? "" : "")
  1188. #define ANSI_COLOR_BOLD_OFF (mode == 1 ? "" : "")
  1189. #if PHP_VERSION_ID >= 70000
  1190. static int xdebug_array_element_export_text_ansi(zval *zv_nptr, zend_ulong index, zend_string *hash_key, int level, int mode, xdebug_str *str, int debug_zval, xdebug_var_export_options *options)
  1191. {
  1192. zval **zv = &zv_nptr;
  1193. #else
  1194. static int xdebug_array_element_export_text_ansi(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
  1195. {
  1196. int level = va_arg(args, int);
  1197. int mode = va_arg(args, int);
  1198. xdebug_str *str = va_arg(args, struct xdebug_str*);
  1199. int debug_zval = va_arg(args, int);
  1200. xdebug_var_export_options *options = va_arg(args, xdebug_var_export_options*);
  1201. #endif
  1202. if (options->runtime[level].current_element_nr >= options->runtime[level].start_element_nr &&
  1203. options->runtime[level].current_element_nr < options->runtime[level].end_element_nr)
  1204. {
  1205. xdebug_str_add(str, xdebug_sprintf("%*s", (level * 2), ""), 1);
  1206. if (HASH_KEY_IS_NUMERIC(hash_key)) { /* numeric key */
  1207. xdebug_str_add(str, xdebug_sprintf("[%ld] %s=>%s\n", HASH_APPLY_NUMERIC(hash_key), ANSI_COLOR_POINTER, ANSI_COLOR_RESET), 1);
  1208. } else { /* string key */
  1209. SIZETorINT newlen = 0;
  1210. char *tmp, *tmp2;
  1211. tmp = xdebug_str_to_str((char*) HASH_APPLY_KEY_VAL(hash_key), HASH_APPLY_KEY_LEN(hash_key), "'", 1, "\\'", 2, &newlen);
  1212. tmp2 = xdebug_str_to_str(tmp, newlen - 1, "\0", 1, "\\0", 2, &newlen);
  1213. if (tmp) {
  1214. efree(tmp);
  1215. }
  1216. xdebug_str_addl(str, "'", 1, 0);
  1217. if (tmp2) {
  1218. xdebug_str_addl(str, tmp2, newlen, 0);
  1219. efree(tmp2);
  1220. }
  1221. xdebug_str_add(str, "' =>\n", 0);
  1222. }
  1223. xdebug_var_export_text_ansi(zv, str, mode, level + 1, debug_zval, options TSRMLS_CC);
  1224. }
  1225. if (options->runtime[level].current_element_nr == options->runtime[level].end_element_nr) {
  1226. xdebug_str_add(str, xdebug_sprintf("\n%*s(more elements)...\n", (level * 2), ""), 1);
  1227. }
  1228. options->runtime[level].current_element_nr++;
  1229. return 0;
  1230. }
  1231. #if PHP_VERSION_ID >= 70000
  1232. static int xdebug_object_element_export_text_ansi(zval *zv_nptr, zend_ulong index, zend_string *hash_key, int level, int mode, xdebug_str *str, int debug_zval, xdebug_var_export_options *options)
  1233. {
  1234. zval **zv = &zv_nptr;
  1235. #else
  1236. static int xdebug_object_element_export_text_ansi(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
  1237. {
  1238. int level = va_arg(args, int);
  1239. int mode = va_arg(args, int);
  1240. xdebug_str *str = va_arg(args, struct xdebug_str*);
  1241. int debug_zval = va_arg(args, int);
  1242. xdebug_var_export_options *options = va_arg(args, xdebug_var_export_options*);
  1243. #endif
  1244. if (options->runtime[level].current_element_nr >= options->runtime[level].start_element_nr &&
  1245. options->runtime[level].current_element_nr < options->runtime[level].end_element_nr)
  1246. {
  1247. xdebug_str_add(str, xdebug_sprintf("%*s", (level * 2), ""), 1);
  1248. if (!HASH_KEY_IS_NUMERIC(hash_key)) {
  1249. char *prop_name, *class_name, *modifier;
  1250. modifier = xdebug_get_property_info((char*) HASH_APPLY_KEY_VAL(hash_key), HASH_APPLY_KEY_LEN(hash_key), &prop_name, &class_name);
  1251. xdebug_str_add(str, xdebug_sprintf("%s%s%s%s%s $%s %s=>%s\n",
  1252. ANSI_COLOR_MODIFIER, ANSI_COLOR_BOLD, modifier, ANSI_COLOR_BOLD_OFF, ANSI_COLOR_RESET,
  1253. prop_name, ANSI_COLOR_POINTER, ANSI_COLOR_RESET), 1);
  1254. xdfree(prop_name);
  1255. xdfree(class_name);
  1256. } else {
  1257. xdebug_str_add(str, xdebug_sprintf("%s%spublic%s%s ${%d} %s=>%s\n",
  1258. ANSI_COLOR_MODIFIER, ANSI_COLOR_BOLD, ANSI_COLOR_BOLD_OFF, ANSI_COLOR_RESET,
  1259. HASH_APPLY_NUMERIC(hash_key), ANSI_COLOR_POINTER, ANSI_COLOR_RESET), 1);
  1260. }
  1261. xdebug_var_export_text_ansi(zv, str, mode, level + 1, debug_zval, options TSRMLS_CC);
  1262. }
  1263. if (options->runtime[level].current_element_nr == options->runtime[level].end_element_nr) {
  1264. xdebug_str_add(str, xdebug_sprintf("\n%*s(more elements)...\n", (level * 2), ""), 1);
  1265. }
  1266. options->runtime[level].current_element_nr++;
  1267. return 0;
  1268. }
  1269. void xdebug_var_export_text_ansi(zval **struc, xdebug_str *str, int mode, int level, int debug_zval, xdebug_var_export_options *options TSRMLS_DC)
  1270. {
  1271. HashTable *myht;
  1272. char* tmp_str;
  1273. int tmp_len;
  1274. int is_temp;
  1275. #if PHP_VERSION_ID >= 70000
  1276. zend_ulong num;
  1277. zend_string *key;
  1278. zval *val;
  1279. zval *tmpz;
  1280. #endif
  1281. if (!struc || !(*struc)) {
  1282. return;
  1283. }
  1284. xdebug_str_add(str, xdebug_sprintf("%*s", (level * 2) - 2, ""), 1);
  1285. #if PHP_VERSION_ID >= 70000
  1286. if (debug_zval) {
  1287. if (Z_TYPE_P(*struc) >= IS_STRING && Z_TYPE_P(*struc) != IS_INDIRECT) {
  1288. xdebug_str_add(str, xdebug_sprintf("(refcount=%d, is_ref=%d)=", (*struc)->value.counted->gc.refcount, Z_TYPE_P(*struc) == IS_REFERENCE), 1);
  1289. } else {
  1290. xdebug_str_add(str, "(refcount=0, is_ref=0)=", 0);
  1291. }
  1292. }
  1293. if (Z_TYPE_P(*struc) == IS_REFERENCE) {
  1294. tmpz = &((*struc)->value.ref->val);
  1295. struc = &tmpz;
  1296. }
  1297. #else
  1298. if (debug_zval) {
  1299. xdebug_str_add(str, xdebug_sprintf("(refcount=%d, is_ref=%d)=", (*struc)->refcount__gc, (*struc)->is_ref__gc), 1);
  1300. }
  1301. #endif
  1302. switch (Z_TYPE_P(*struc)) {
  1303. #if PHP_VERSION_ID >= 70000
  1304. case IS_TRUE:
  1305. case IS_FALSE:
  1306. xdebug_str_add(str, xdebug_sprintf("%sbool%s(%s%s%s)", ANSI_COLOR_BOLD, ANSI_COLOR_BOLD_OFF, ANSI_COLOR_BOOL, Z_TYPE_P(*struc) == IS_TRUE ? "true" : "false", ANSI_COLOR_RESET), 1);
  1307. break;
  1308. #else
  1309. case IS_BOOL:
  1310. xdebug_str_add(str, xdebug_sprintf("%sbool%s(%s%s%s)", ANSI_COLOR_BOLD, ANSI_COLOR_BOLD_OFF, ANSI_COLOR_BOOL, Z_LVAL_P(*struc) ? "true" : "false", ANSI_COLOR_RESET), 1);
  1311. break;
  1312. #endif
  1313. case IS_NULL:
  1314. xdebug_str_add(str, xdebug_sprintf("%s%sNULL%s%s", ANSI_COLOR_BOLD, ANSI_COLOR_NULL, ANSI_COLOR_RESET, ANSI_COLOR_BOLD_OFF), 1);
  1315. break;
  1316. case IS_LONG:
  1317. xdebug_str_add(str, xdebug_sprintf("%sint%s(%s" XDEBUG_INT_FMT "%s)", ANSI_COLOR_BOLD, ANSI_COLOR_BOLD_OFF, ANSI_COLOR_LONG, Z_LVAL_P(*struc), ANSI_COLOR_RESET), 1);
  1318. break;
  1319. case IS_DOUBLE:
  1320. xdebug_str_add(str, xdebug_sprintf("%sdouble%s(%s%.*G%s)", ANSI_COLOR_BOLD, ANSI_COLOR_BOLD_OFF, ANSI_COLOR_DOUBLE, (int) EG(precision), Z_DVAL_P(*struc), ANSI_COLOR_RESET), 1);
  1321. break;
  1322. case IS_STRING: {
  1323. char *pattern = (mode == 1) ? "'\\\0..\37" : "\0";
  1324. size_t pattern_len = (mode == 1) ? 7 : 1;
  1325. #if PHP_VERSION_ID >= 70000
  1326. zend_string *i_string = zend_string_init(Z_STRVAL_P(*struc), Z_STRLEN_P(*struc), 0);
  1327. zend_string *tmp_zstr;
  1328. tmp_zstr = php_addcslashes(i_string, 0, pattern, pattern_len);
  1329. tmp_str = estrndup(tmp_zstr->val, tmp_zstr->len);
  1330. tmp_len = tmp_zstr->len;
  1331. zend_string_release(tmp_zstr);
  1332. zend_string_release(i_string);
  1333. #else
  1334. tmp_str = php_addcslashes(Z_STRVAL_P(*struc), Z_STRLEN_P(*struc), &tmp_len, 0, pattern, pattern_len TSRMLS_CC);
  1335. #endif
  1336. if (options->no_decoration) {
  1337. xdebug_str_addl(str, tmp_str, tmp_len, 0);
  1338. } else if ((size_t) Z_STRLEN_P(*struc) <= (size_t) options->max_data) {
  1339. xdebug_str_add(str, xdebug_sprintf("%sstring%s(%s%ld%s) \"%s%s%s\"",
  1340. ANSI_COLOR_BOLD, ANSI_COLOR_BOLD_OFF,
  1341. ANSI_COLOR_LONG, Z_STRLEN_P(*struc), ANSI_COLOR_RESET,
  1342. ANSI_COLOR_STRING, tmp_str, ANSI_COLOR_RESET), 1);
  1343. } else {
  1344. xdebug_str_add(str, xdebug_sprintf("%sstring%s(%s%ld%s) \"%s",
  1345. ANSI_COLOR_BOLD, ANSI_COLOR_BOLD_OFF,
  1346. ANSI_COLOR_LONG, Z_STRLEN_P(*struc), ANSI_COLOR_RESET, ANSI_COLOR_STRING), 1);
  1347. xdebug_str_addl(str, tmp_str, options->max_data, 0);
  1348. xdebug_str_add(str, xdebug_sprintf("%s\"...", ANSI_COLOR_RESET), 1);
  1349. }
  1350. efree(tmp_str);
  1351. } break;
  1352. case IS_ARRAY:
  1353. myht = Z_ARRVAL_P(*struc);
  1354. if (XDEBUG_APPLY_COUNT(myht) < 1) {
  1355. xdebug_str_add(str, xdebug_sprintf("%sarray%s(%s%d%s) {\n", ANSI_COLOR_BOLD, ANSI_COLOR_BOLD_OFF, ANSI_COLOR_LONG, myht->nNumOfElements, ANSI_COLOR_RESET), 1);
  1356. if (level <= options->max_depth) {
  1357. options->runtime[level].current_element_nr = 0;
  1358. options->runtime[level].start_element_nr = 0;
  1359. options->runtime[level].end_element_nr = options->max_children;
  1360. #if PHP_VERSION_ID >= 70000
  1361. ZEND_HASH_INC_APPLY_COUNT(myht);
  1362. ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, val) {
  1363. xdebug_array_element_export_text_ansi(val, num, key, level, mode, str, debug_zval, options);
  1364. } ZEND_HASH_FOREACH_END();
  1365. ZEND_HASH_DEC_APPLY_COUNT(myht);
  1366. #else
  1367. zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) xdebug_array_element_export_text_ansi, 5, level, mode, str, debug_zval, options);
  1368. #endif
  1369. } else {
  1370. xdebug_str_add(str, xdebug_sprintf("%*s...\n", (level * 2), ""), 1);
  1371. }
  1372. xdebug_str_add(str, xdebug_sprintf("%*s}", (level * 2) - 2 , ""), 1);
  1373. } else {
  1374. xdebug_str_add(str, xdebug_sprintf("&%sarray%s", ANSI_COLOR_BOLD, ANSI_COLOR_BOLD_OFF), 1);
  1375. }
  1376. break;
  1377. case IS_OBJECT:
  1378. myht = xdebug_objdebug_pp(struc, &is_temp TSRMLS_CC);
  1379. if (myht && XDEBUG_APPLY_COUNT(myht) < 1) {
  1380. xdebug_str_add(str, xdebug_sprintf("%sclass%s %s%s%s#%d (%s%d%s) {\n",
  1381. ANSI_COLOR_BOLD, ANSI_COLOR_BOLD_OFF,
  1382. ANSI_COLOR_OBJECT, STR_NAME_VAL(Z_OBJCE_P(*struc)->name), ANSI_COLOR_RESET,
  1383. Z_OBJ_HANDLE_P(*struc),
  1384. ANSI_COLOR_LONG, myht->nNumOfElements, ANSI_COLOR_RESET), 1);
  1385. if (level <= options->max_depth) {
  1386. options->runtime[level].current_element_nr = 0;
  1387. options->runtime[level].start_element_nr = 0;
  1388. options->runtime[level].end_element_nr = options->max_children;
  1389. #if PHP_VERSION_ID >= 70000
  1390. ZEND_HASH_INC_APPLY_COUNT(myht);
  1391. ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, val) {
  1392. xdebug_object_element_export_text_ansi(val, num, key, level, mode, str, debug_zval, options);
  1393. } ZEND_HASH_FOREACH_END();
  1394. ZEND_HASH_DEC_APPLY_COUNT(myht);
  1395. #else
  1396. zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) xdebug_object_element_export_text_ansi, 5, level, mode, str, debug_zval, options);
  1397. #endif
  1398. } else {
  1399. xdebug_str_add(str, xdebug_sprintf("%*s...\n", (level * 2), ""), 1);
  1400. }
  1401. xdebug_str_add(str, xdebug_sprintf("%*s}", (level * 2) - 2, ""), 1);
  1402. } else {
  1403. xdebug_str_add(str, xdebug_sprintf("%*s...\n", (level * 2), ""), 1);
  1404. }
  1405. if (is_temp) {
  1406. zend_hash_destroy(myht);
  1407. efree(myht);
  1408. }
  1409. break;
  1410. case IS_RESOURCE: {
  1411. char *type_name;
  1412. #if PHP_VERSION_ID >= 70000
  1413. type_name = (char *) zend_rsrc_list_get_rsrc_type(Z_RES_P(*struc) TSRMLS_CC);
  1414. xdebug_str_add(str, xdebug_sprintf("%sresource%s(%s%ld%s) of type (%s)",
  1415. ANSI_COLOR_BOLD, ANSI_COLOR_BOLD_OFF,
  1416. ANSI_COLOR_RESOURCE, Z_RES_P(*struc)->handle, ANSI_COLOR_RESET, type_name ? type_name : "Unknown"), 1);
  1417. #else
  1418. type_name = (char *) zend_rsrc_list_get_rsrc_type(Z_LVAL_P(*struc) TSRMLS_CC);
  1419. xdebug_str_add(str, xdebug_sprintf("%sresource%s(%s%ld%s) of type (%s)",
  1420. ANSI_COLOR_BOLD, ANSI_COLOR_BOLD_OFF,
  1421. ANSI_COLOR_RESOURCE, Z_LVAL_P(*struc), ANSI_COLOR_RESET, type_name ? type_name : "Unknown"), 1);
  1422. #endif
  1423. break;
  1424. }
  1425. #if PHP_VERSION_ID >= 70000
  1426. case IS_UNDEF:
  1427. xdebug_str_add(str, xdebug_sprintf("%s*uninitialized*%s", ANSI_COLOR_NULL, ANSI_COLOR_RESET), 0);
  1428. break;
  1429. #endif
  1430. default:
  1431. xdebug_str_add(str, xdebug_sprintf("%sNFC%s", ANSI_COLOR_NULL, ANSI_COLOR_RESET), 0);
  1432. break;
  1433. }
  1434. xdebug_str_addl(str, "\n", 1, 0);
  1435. }
  1436. char* xdebug_get_zval_value_text_ansi(zval *val, int mode, int debug_zval, xdebug_var_export_options *options TSRMLS_DC)
  1437. {
  1438. xdebug_str str = XDEBUG_STR_INITIALIZER;
  1439. int default_options = 0;
  1440. if (!options) {
  1441. options = xdebug_var_export_options_from_ini(TSRMLS_C);
  1442. default_options = 1;
  1443. }
  1444. if (options->show_location && !debug_zval) {
  1445. xdebug_str_add(&str, xdebug_sprintf("%s%s%s:%s%d%s:\n", ANSI_COLOR_BOLD, zend_get_executed_filename(TSRMLS_C), ANSI_COLOR_BOLD_OFF, ANSI_COLOR_BOLD, zend_get_executed_lineno(TSRMLS_C), ANSI_COLOR_BOLD_OFF), 1);
  1446. }
  1447. xdebug_var_export_text_ansi(&val, (xdebug_str*) &str, mode, 1, debug_zval, options TSRMLS_CC);
  1448. if (default_options) {
  1449. xdfree(options->runtime);
  1450. xdfree(options);
  1451. }
  1452. return str.d;
  1453. }
  1454. static void xdebug_var_synopsis_text_ansi(zval **struc, xdebug_str *str, int mode, int level, int debug_zval, xdebug_var_export_options *options TSRMLS_DC)
  1455. {
  1456. HashTable *myht;
  1457. #if PHP_VERSION_ID >= 70000
  1458. zval *tmpz;
  1459. #endif
  1460. if (!struc || !(*struc)) {
  1461. return;
  1462. }
  1463. #if PHP_VERSION_ID >= 70000
  1464. if (debug_zval) {
  1465. if (Z_TYPE_P(*struc) >= IS_STRING && Z_TYPE_P(*struc) != IS_INDIRECT) {
  1466. xdebug_str_add(str, xdebug_sprintf("(refcount=%d, is_ref=%d)=", (*struc)->value.counted->gc.refcount, Z_TYPE_P(*struc) == IS_REFERENCE), 1);
  1467. } else {
  1468. xdebug_str_add(str, "(refcount=0, is_ref=0)=", 0);
  1469. }
  1470. }
  1471. if (Z_TYPE_P(*struc) == IS_REFERENCE) {
  1472. tmpz = &((*struc)->value.ref->val);
  1473. struc = &tmpz;
  1474. }
  1475. #else
  1476. if (debug_zval) {
  1477. xdebug_str_add(str, xdebug_sprintf("(refcount=%d, is_ref=%d)=", (*struc)->refcount__gc, (*struc)->is_ref__gc), 1);
  1478. }
  1479. #endif
  1480. switch (Z_TYPE_P(*struc)) {
  1481. #if PHP_VERSION_ID >= 70000
  1482. case IS_TRUE:
  1483. xdebug_str_add(str, xdebug_sprintf("%strue%s", ANSI_COLOR_BOLD, ANSI_COLOR_BOLD_OFF), 1);
  1484. break;
  1485. case IS_FALSE:
  1486. xdebug_str_add(str, xdebug_sprintf("%sfalse%s", ANSI_COLOR_BOLD, ANSI_COLOR_BOLD_OFF), 1);
  1487. break;
  1488. #else
  1489. case IS_BOOL:
  1490. xdebug_str_add(str, xdebug_sprintf("%sbool%s", ANSI_COLOR_BOLD, ANSI_COLOR_BOLD_OFF), 1);
  1491. break;
  1492. #endif
  1493. case IS_NULL:
  1494. xdebug_str_add(str, xdebug_sprintf("%snull%s", ANSI_COLOR_BOLD, ANSI_COLOR_BOLD_OFF), 1);
  1495. break;
  1496. case IS_LONG:
  1497. xdebug_str_add(str, xdebug_sprintf("%sint%s", ANSI_COLOR_BOLD, ANSI_COLOR_BOLD_OFF), 1);
  1498. break;
  1499. case IS_DOUBLE:
  1500. xdebug_str_add(str, xdebug_sprintf("%sdouble%s", ANSI_COLOR_BOLD, ANSI_COLOR_BOLD_OFF), 1);
  1501. break;
  1502. case IS_STRING:
  1503. xdebug_str_add(str, xdebug_sprintf("%sstring%s(%s%d%s)", ANSI_COLOR_BOLD, ANSI_COLOR_BOLD_OFF, ANSI_COLOR_LONG, Z_STRLEN_P(*struc), ANSI_COLOR_RESET), 1);
  1504. break;
  1505. case IS_ARRAY:
  1506. myht = Z_ARRVAL_P(*struc);
  1507. xdebug_str_add(str, xdebug_sprintf("array(%s%d%s)", ANSI_COLOR_LONG, myht->nNumOfElements, ANSI_COLOR_RESET), 1);
  1508. break;
  1509. case IS_OBJECT: {
  1510. xdebug_str_add(str, xdebug_sprintf("class %s", STR_NAME_VAL(Z_OBJCE_P(*struc)->name)), 1);
  1511. break;
  1512. }
  1513. case IS_RESOURCE: {
  1514. char *type_name;
  1515. #if PHP_VERSION_ID >= 70000
  1516. type_name = (char *) zend_rsrc_list_get_rsrc_type(Z_RES_P(*struc) TSRMLS_CC);
  1517. xdebug_str_add(str, xdebug_sprintf("resource(%s%ld%s) of type (%s)", ANSI_COLOR_LONG, Z_RES_P(*struc)->handle, ANSI_COLOR_RESET, type_name ? type_name : "Unknown"), 1);
  1518. #else
  1519. type_name = (char *) zend_rsrc_list_get_rsrc_type(Z_LVAL_P(*struc) TSRMLS_CC);
  1520. xdebug_str_add(str, xdebug_sprintf("resource(%s%ld%s) of type (%s)", ANSI_COLOR_LONG, Z_LVAL_P(*struc), ANSI_COLOR_RESET, type_name ? type_name : "Unknown"), 1);
  1521. #endif
  1522. break;
  1523. }
  1524. #if PHP_VERSION_ID >= 70000
  1525. case IS_UNDEF:
  1526. xdebug_str_add(str, xdebug_sprintf("%s*uninitialized*%s", ANSI_COLOR_NULL, ANSI_COLOR_RESET), 0);
  1527. break;
  1528. #endif
  1529. default:
  1530. xdebug_str_add(str, xdebug_sprintf("%sNFC%s", ANSI_COLOR_NULL, ANSI_COLOR_RESET), 0);
  1531. break;
  1532. }
  1533. }
  1534. char* xdebug_get_zval_synopsis_text_ansi(zval *val, int mode, int debug_zval, xdebug_var_export_options *options TSRMLS_DC)
  1535. {
  1536. xdebug_str str = XDEBUG_STR_INITIALIZER;
  1537. int default_options = 0;
  1538. if (!options) {
  1539. options = xdebug_var_export_options_from_ini(TSRMLS_C);
  1540. default_options = 1;
  1541. }
  1542. if (options->show_location && !debug_zval) {
  1543. xdebug_str_add(&str, xdebug_sprintf("%s%s: %d%s\n", ANSI_COLOR_BOLD, zend_get_executed_filename(TSRMLS_C), zend_get_executed_lineno(TSRMLS_C), ANSI_COLOR_BOLD_OFF), 1);
  1544. }
  1545. xdebug_var_synopsis_text_ansi(&val, (xdebug_str*) &str, mode, 1, debug_zval, options TSRMLS_CC);
  1546. if (default_options) {
  1547. xdfree(options->runtime);
  1548. xdfree(options);
  1549. }
  1550. return str.d;
  1551. }
  1552. /*****************************************************************************
  1553. ** XML node printing routines
  1554. */
  1555. #define XDEBUG_OBJECT_ITEM_TYPE_PROPERTY 1
  1556. #define XDEBUG_OBJECT_ITEM_TYPE_STATIC_PROPERTY 2
  1557. typedef struct
  1558. {
  1559. char type;
  1560. char *name;
  1561. int name_len;
  1562. ulong index;
  1563. zval *zv;
  1564. } xdebug_object_item;
  1565. #if PHP_VERSION_ID >= 70000
  1566. static int object_item_add_to_merged_hash(zval *zv_nptr, zend_ulong index, zend_string *hash_key, HashTable *merged, int object_type)
  1567. {
  1568. zval **zv = &zv_nptr;
  1569. #else
  1570. static int object_item_add_to_merged_hash(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
  1571. {
  1572. HashTable *merged = va_arg(args, HashTable*);
  1573. int object_type = va_arg(args, int);
  1574. #endif
  1575. xdebug_object_item *item;
  1576. item = xdcalloc(1, sizeof(xdebug_object_item));
  1577. item->type = object_type;
  1578. item->zv = *zv;
  1579. #if PHP_VERSION_ID >= 70000
  1580. if (hash_key) {
  1581. item->name = (char*) HASH_APPLY_KEY_VAL(hash_key);
  1582. item->name_len = HASH_APPLY_KEY_LEN(hash_key) - 1;
  1583. item->index = hash_key->h;
  1584. } else {
  1585. item->name = xdebug_sprintf("%ld", index);
  1586. item->name_len = strlen(item->name);
  1587. }
  1588. #else
  1589. item->name = (char*) HASH_APPLY_KEY_VAL(hash_key);
  1590. item->name_len = HASH_APPLY_KEY_LEN(hash_key);
  1591. item->index = hash_key->h;
  1592. #endif
  1593. #if PHP_VERSION_ID >= 70000
  1594. zend_hash_next_index_insert_ptr(merged, item);
  1595. #else
  1596. zend_hash_next_index_insert(merged, &item, sizeof(xdebug_object_item*), NULL);
  1597. #endif
  1598. return 0;
  1599. }
  1600. #if PHP_VERSION_ID >= 50400
  1601. # if PHP_VERSION_ID >= 70000
  1602. static int object_item_add_zend_prop_to_merged_hash(zend_property_info *zpp, HashTable *merged, int object_type, zend_class_entry *ce)
  1603. {
  1604. # else
  1605. static int object_item_add_zend_prop_to_merged_hash(zend_property_info *zpp TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
  1606. {
  1607. HashTable *merged = va_arg(args, HashTable*);
  1608. int object_type = va_arg(args, int);
  1609. zend_class_entry *ce = va_arg(args, zend_class_entry*);
  1610. # endif
  1611. xdebug_object_item *item;
  1612. if ((zpp->flags & ZEND_ACC_STATIC) == 0) {
  1613. return 0;
  1614. }
  1615. item = xdmalloc(sizeof(xdebug_object_item));
  1616. item->type = object_type;
  1617. #if ZTS
  1618. # if PHP_VERSION_ID >= 70000
  1619. if (ce->type == 1) {
  1620. item->zv = &CG(static_members_table)[(zend_intptr_t) ce->static_members_table][zpp->offset];
  1621. } else {
  1622. item->zv = &ce->static_members_table[zpp->offset];
  1623. }
  1624. # else
  1625. if (ce->type == 1) {
  1626. item->zv = CG(static_members_table)[(zend_intptr_t) ce->static_members_table][zpp->offset];
  1627. } else {
  1628. item->zv = ce->static_members_table[zpp->offset];
  1629. }
  1630. # endif
  1631. #else
  1632. # if PHP_VERSION_ID >= 70000
  1633. item->zv = &ce->static_members_table[zpp->offset];
  1634. # else
  1635. item->zv = ce->static_members_table[zpp->offset];
  1636. # endif
  1637. #endif
  1638. item->name = (char*) STR_NAME_VAL(zpp->name);
  1639. item->name_len = STR_NAME_LEN(zpp->name);
  1640. #if PHP_VERSION_ID >= 70000
  1641. zend_hash_next_index_insert_ptr(merged, item);
  1642. #else
  1643. zend_hash_next_index_insert(merged, &item, sizeof(xdebug_object_item*), NULL);
  1644. #endif
  1645. return 0;
  1646. }
  1647. #endif
  1648. #if PHP_VERSION_ID >= 70000
  1649. static int xdebug_array_element_export_xml_node(zval *zv_nptr, zend_ulong index, zend_string *hash_key, int level, xdebug_xml_node *parent, char *parent_name, xdebug_var_export_options *options)
  1650. {
  1651. zval **zv = &zv_nptr;
  1652. #else
  1653. static int xdebug_array_element_export_xml_node(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
  1654. {
  1655. int level = va_arg(args, int);
  1656. xdebug_xml_node *parent = va_arg(args, xdebug_xml_node*);
  1657. char *parent_name = va_arg(args, char *);
  1658. xdebug_var_export_options *options = va_arg(args, xdebug_var_export_options*);
  1659. #endif
  1660. xdebug_xml_node *node;
  1661. char *name = NULL;
  1662. int name_len = 0;
  1663. xdebug_str full_name = XDEBUG_STR_INITIALIZER;
  1664. if (options->runtime[level].current_element_nr >= options->runtime[level].start_element_nr &&
  1665. options->runtime[level].current_element_nr < options->runtime[level].end_element_nr)
  1666. {
  1667. node = xdebug_xml_node_init("property");
  1668. if (!HASH_KEY_IS_NUMERIC(hash_key)) { /* string key */
  1669. name = xdstrndup(HASH_APPLY_KEY_VAL(hash_key), HASH_APPLY_KEY_LEN(hash_key));
  1670. name_len = HASH_APPLY_KEY_LEN(hash_key) - 1;
  1671. if (parent_name) {
  1672. xdebug_str_add(&full_name, parent_name, 0);
  1673. xdebug_str_addl(&full_name, "['", 2, 0);
  1674. xdebug_str_addl(&full_name, name, name_len, 0);
  1675. xdebug_str_addl(&full_name, "']", 2, 0);
  1676. }
  1677. } else {
  1678. name = xdebug_sprintf("%ld", HASH_APPLY_NUMERIC(hash_key));
  1679. name_len = strlen(name);
  1680. if (parent_name) {
  1681. xdebug_str_add(&full_name, xdebug_sprintf("%s[%s]", parent_name, name), 1);
  1682. }
  1683. }
  1684. xdebug_xml_add_attribute_exl(node, "name", 4, name, name_len, 0, 1);
  1685. if (full_name.l) {
  1686. xdebug_xml_add_attribute_exl(node, "fullname", 8, full_name.d, full_name.l, 0, 1);
  1687. }
  1688. xdebug_xml_add_child(parent, node);
  1689. xdebug_var_export_xml_node(zv, full_name.d, node, options, level + 1 TSRMLS_CC);
  1690. }
  1691. options->runtime[level].current_element_nr++;
  1692. return 0;
  1693. }
  1694. #if PHP_VERSION_ID >= 70000
  1695. static int xdebug_object_element_export_xml_node(xdebug_object_item *item_nptr, zend_ulong index, zend_string *hash_key, int level, xdebug_xml_node *parent, char *parent_name, xdebug_var_export_options *options, char *class_name)
  1696. {
  1697. xdebug_object_item **item = &item_nptr;
  1698. #else
  1699. static int xdebug_object_element_export_xml_node(xdebug_object_item **item TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
  1700. {
  1701. int level = va_arg(args, int);
  1702. xdebug_xml_node *parent = va_arg(args, xdebug_xml_node*);
  1703. char *parent_name = va_arg(args, char *);
  1704. xdebug_var_export_options *options = va_arg(args, xdebug_var_export_options*);
  1705. char *class_name = va_arg(args, char *);
  1706. #endif
  1707. xdebug_xml_node *node;
  1708. char *full_name = NULL;
  1709. if (options->runtime[level].current_element_nr >= options->runtime[level].start_element_nr &&
  1710. options->runtime[level].current_element_nr < options->runtime[level].end_element_nr)
  1711. {
  1712. char *modifier;
  1713. node = xdebug_xml_node_init("property");
  1714. if ((*item)->name_len != 0) {
  1715. char *prop_name, *prop_class_name;
  1716. #if PHP_VERSION_ID >= 70000
  1717. modifier = xdebug_get_property_info((*item)->name, (*item)->name_len + 1, &prop_name, &prop_class_name);
  1718. #else
  1719. modifier = xdebug_get_property_info((*item)->name, (*item)->name_len + 1, &prop_name, &prop_class_name);
  1720. #endif
  1721. if (strcmp(modifier, "private") != 0 || strcmp(class_name, prop_class_name) == 0) {
  1722. xdebug_xml_add_attribute_ex(node, "name", xdstrdup(prop_name), 0, 1);
  1723. } else {
  1724. xdebug_xml_add_attribute_ex(node, "name", xdebug_sprintf("*%s*%s", prop_class_name, prop_name), 0, 1);
  1725. }
  1726. if (parent_name) {
  1727. if (strcmp(modifier, "private") != 0 || strcmp(class_name, prop_class_name) == 0) {
  1728. full_name = xdebug_sprintf("%s%s%s", parent_name, (*item)->type == XDEBUG_OBJECT_ITEM_TYPE_STATIC_PROPERTY ? "::" : "->", prop_name);
  1729. } else {
  1730. full_name = xdebug_sprintf("%s%s*%s*%s", parent_name, (*item)->type == XDEBUG_OBJECT_ITEM_TYPE_STATIC_PROPERTY ? "::" : "->", prop_class_name, prop_name);
  1731. }
  1732. xdebug_xml_add_attribute_ex(node, "fullname", full_name, 0, 1);
  1733. }
  1734. xdfree(prop_name);
  1735. xdfree(prop_class_name);
  1736. } else { /* Numerical property name */
  1737. modifier = "public";
  1738. xdebug_xml_add_attribute_ex(node, "name", xdebug_sprintf("%ld", (*item)->index), 0, 1);
  1739. if (parent_name) {
  1740. full_name = xdebug_sprintf("%s%s%ld", parent_name, (*item)->type == XDEBUG_OBJECT_ITEM_TYPE_STATIC_PROPERTY ? "::" : "->", (*item)->index);
  1741. xdebug_xml_add_attribute_ex(node, "fullname", full_name, 0, 1);
  1742. }
  1743. }
  1744. xdebug_xml_add_attribute_ex(node, "facet", xdebug_sprintf("%s%s", (*item)->type == XDEBUG_OBJECT_ITEM_TYPE_STATIC_PROPERTY ? "static " : "", modifier), 0, 1);
  1745. xdebug_xml_add_child(parent, node);
  1746. xdebug_var_export_xml_node(&((*item)->zv), full_name, node, options, level + 1 TSRMLS_CC);
  1747. }
  1748. options->runtime[level].current_element_nr++;
  1749. return 0;
  1750. }
  1751. static char *prepare_variable_name(char *name)
  1752. {
  1753. char *tmp_name;
  1754. tmp_name = xdebug_sprintf("%s%s", (name[0] == '$' || name[0] == ':') ? "" : "$", name);
  1755. if (tmp_name[strlen(tmp_name) - 2] == ':' && tmp_name[strlen(tmp_name) - 1] == ':') {
  1756. tmp_name[strlen(tmp_name) - 2] = '\0';
  1757. }
  1758. return tmp_name;
  1759. }
  1760. void xdebug_attach_uninitialized_var(xdebug_xml_node *node, char *name)
  1761. {
  1762. xdebug_xml_node *contents = NULL;
  1763. char *tmp_name;
  1764. contents = xdebug_xml_node_init("property");
  1765. tmp_name = prepare_variable_name(name);
  1766. xdebug_xml_add_attribute_ex(contents, "name", xdstrdup(tmp_name), 0, 1);
  1767. xdebug_xml_add_attribute_ex(contents, "fullname", xdstrdup(tmp_name), 0, 1);
  1768. xdfree(tmp_name);
  1769. xdebug_xml_add_attribute(contents, "type", "uninitialized");
  1770. xdebug_xml_add_child(node, contents);
  1771. }
  1772. #if PHP_VERSION_ID >= 70000
  1773. void xdebug_attach_property_with_contents(zend_property_info *prop_info, xdebug_xml_node *node, xdebug_var_export_options *options, zend_class_entry *class_entry, char *class_name, int *children_count)
  1774. {
  1775. #else
  1776. void xdebug_attach_property_with_contents(zend_property_info *prop_info TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
  1777. {
  1778. xdebug_xml_node *node = va_arg(args, xdebug_xml_node *);
  1779. xdebug_var_export_options *options = va_arg(args, xdebug_var_export_options *);
  1780. zend_class_entry *class_entry = va_arg(args, zend_class_entry *);
  1781. char *class_name = va_arg(args, char *);
  1782. int *children_count = va_arg(args, int *);
  1783. #endif
  1784. char *modifier;
  1785. xdebug_xml_node *contents = NULL;
  1786. char *prop_name, *prop_class_name;
  1787. if ((prop_info->flags & ZEND_ACC_STATIC) == 0) {
  1788. return;
  1789. }
  1790. (*children_count)++;
  1791. #if PHP_VERSION_ID >= 70000
  1792. modifier = xdebug_get_property_info(STR_NAME_VAL(prop_info->name), STR_NAME_LEN(prop_info->name) + 1, &prop_name, &prop_class_name);
  1793. #else
  1794. modifier = xdebug_get_property_info((char *) prop_info->name, prop_info->name_length, &prop_name, &prop_class_name);
  1795. #endif
  1796. if (strcmp(modifier, "private") != 0 || strcmp(class_name, prop_class_name) == 0) {
  1797. #if PHP_VERSION_ID >= 70000
  1798. contents = xdebug_get_zval_value_xml_node_ex(prop_name, &class_entry->static_members_table[prop_info->offset], XDEBUG_VAR_TYPE_STATIC, options TSRMLS_CC);
  1799. #else
  1800. contents = xdebug_get_zval_value_xml_node_ex(prop_name, class_entry->static_members_table[prop_info->offset], XDEBUG_VAR_TYPE_STATIC, options TSRMLS_CC);
  1801. #endif
  1802. } else{
  1803. char *priv_name = xdebug_sprintf("*%s*%s", prop_class_name, prop_name);
  1804. #if PHP_VERSION_ID >= 70000
  1805. contents = xdebug_get_zval_value_xml_node_ex(priv_name, &class_entry->static_members_table[prop_info->offset], XDEBUG_VAR_TYPE_STATIC, options TSRMLS_CC);
  1806. #else
  1807. contents = xdebug_get_zval_value_xml_node_ex(priv_name, class_entry->static_members_table[prop_info->offset], XDEBUG_VAR_TYPE_STATIC, options TSRMLS_CC);
  1808. #endif
  1809. xdfree(priv_name);
  1810. }
  1811. xdfree(prop_name);
  1812. xdfree(prop_class_name);
  1813. if (contents) {
  1814. xdebug_xml_add_attribute_ex(contents, "facet", xdebug_sprintf("static %s", modifier), 0, 1);
  1815. xdebug_xml_add_child(node, contents);
  1816. } else {
  1817. xdebug_attach_uninitialized_var(node, (char *) prop_info->name);
  1818. }
  1819. }
  1820. void xdebug_attach_static_vars(xdebug_xml_node *node, xdebug_var_export_options *options, zend_class_entry *ce TSRMLS_DC)
  1821. {
  1822. HashTable *static_members = &ce->properties_info;
  1823. int children = 0;
  1824. xdebug_xml_node *static_container;
  1825. #if PHP_VERSION_ID >= 70000
  1826. zend_property_info *zpi;
  1827. #endif
  1828. static_container = xdebug_xml_node_init("property");
  1829. xdebug_xml_add_attribute(static_container, "name", "::");
  1830. xdebug_xml_add_attribute(static_container, "fullname", "::");
  1831. xdebug_xml_add_attribute(static_container, "type", "object");
  1832. xdebug_xml_add_attribute_ex(static_container, "classname", xdstrdup(STR_NAME_VAL(ce->name)), 0, 1);
  1833. #if PHP_VERSION_ID >= 70000
  1834. ZEND_HASH_INC_APPLY_COUNT(static_members);
  1835. ZEND_HASH_FOREACH_PTR(static_members, zpi) {
  1836. xdebug_attach_property_with_contents(zpi, static_container, options, ce, STR_NAME_VAL(ce->name), &children);
  1837. } ZEND_HASH_FOREACH_END();
  1838. ZEND_HASH_DEC_APPLY_COUNT(static_members);
  1839. #else
  1840. zend_hash_apply_with_arguments(static_members TSRMLS_CC, (apply_func_args_t) xdebug_attach_property_with_contents, 5, static_container, options, ce, ce->name, &children);
  1841. #endif
  1842. xdebug_xml_add_attribute(static_container, "children", children > 0 ? "1" : "0");
  1843. xdebug_xml_add_attribute_ex(static_container, "numchildren", xdebug_sprintf("%d", children), 0, 1);
  1844. xdebug_xml_add_child(node, static_container);
  1845. }
  1846. void xdebug_var_export_xml_node(zval **struc, char *name, xdebug_xml_node *node, xdebug_var_export_options *options, int level TSRMLS_DC)
  1847. {
  1848. HashTable *myht;
  1849. char *class_name;
  1850. SIZETorINT class_name_len;
  1851. #if PHP_VERSION_ID >= 70000
  1852. zend_ulong num;
  1853. zend_string *key;
  1854. zval *z_val;
  1855. xdebug_object_item *xoi_val;
  1856. zval *tmpz;
  1857. if (Z_TYPE_P(*struc) == IS_INDIRECT) {
  1858. tmpz = ((*struc)->value.zv);
  1859. struc = &tmpz;
  1860. }
  1861. if (Z_TYPE_P(*struc) == IS_REFERENCE) {
  1862. tmpz = &((*struc)->value.ref->val);
  1863. struc = &tmpz;
  1864. }
  1865. #endif
  1866. switch (Z_TYPE_P(*struc)) {
  1867. #if PHP_VERSION_ID >= 70000
  1868. case IS_TRUE:
  1869. case IS_FALSE:
  1870. xdebug_xml_add_attribute(node, "type", "bool");
  1871. xdebug_xml_add_text(node, xdebug_sprintf("%d", Z_TYPE_P(*struc) == IS_TRUE ? 1 : 0));
  1872. break;
  1873. #else
  1874. case IS_BOOL:
  1875. xdebug_xml_add_attribute(node, "type", "bool");
  1876. xdebug_xml_add_text(node, xdebug_sprintf("%d", Z_LVAL_P(*struc)));
  1877. break;
  1878. #endif
  1879. case IS_NULL:
  1880. xdebug_xml_add_attribute(node, "type", "null");
  1881. break;
  1882. case IS_LONG:
  1883. xdebug_xml_add_attribute(node, "type", "int");
  1884. xdebug_xml_add_text(node, xdebug_sprintf(XDEBUG_INT_FMT, Z_LVAL_P(*struc)));
  1885. break;
  1886. case IS_DOUBLE:
  1887. xdebug_xml_add_attribute(node, "type", "float");
  1888. xdebug_xml_add_text(node, xdebug_sprintf("%.*G", (int) EG(precision), Z_DVAL_P(*struc)));
  1889. break;
  1890. case IS_STRING:
  1891. xdebug_xml_add_attribute(node, "type", "string");
  1892. if (options->max_data == 0 || (size_t) Z_STRLEN_P(*struc) <= (size_t) options->max_data) {
  1893. xdebug_xml_add_text_encodel(node, xdstrndup(Z_STRVAL_P(*struc), Z_STRLEN_P(*struc)), Z_STRLEN_P(*struc));
  1894. } else {
  1895. xdebug_xml_add_text_encodel(node, xdstrndup(Z_STRVAL_P(*struc), options->max_data), options->max_data);
  1896. }
  1897. xdebug_xml_add_attribute_ex(node, "size", xdebug_sprintf("%d", Z_STRLEN_P(*struc)), 0, 1);
  1898. break;
  1899. case IS_ARRAY:
  1900. myht = Z_ARRVAL_P(*struc);
  1901. xdebug_xml_add_attribute(node, "type", "array");
  1902. xdebug_xml_add_attribute(node, "children", myht->nNumOfElements > 0?"1":"0");
  1903. if (XDEBUG_APPLY_COUNT(myht) < 1) {
  1904. xdebug_xml_add_attribute_ex(node, "numchildren", xdebug_sprintf("%d", myht->nNumOfElements), 0, 1);
  1905. if (level < options->max_depth) {
  1906. xdebug_xml_add_attribute_ex(node, "page", xdebug_sprintf("%d", options->runtime[level].page), 0, 1);
  1907. xdebug_xml_add_attribute_ex(node, "pagesize", xdebug_sprintf("%d", options->max_children), 0, 1);
  1908. options->runtime[level].current_element_nr = 0;
  1909. if (level == 0) {
  1910. options->runtime[level].start_element_nr = options->max_children * options->runtime[level].page;
  1911. options->runtime[level].end_element_nr = options->max_children * (options->runtime[level].page + 1);
  1912. } else {
  1913. options->runtime[level].start_element_nr = 0;
  1914. options->runtime[level].end_element_nr = options->max_children;
  1915. }
  1916. #if PHP_VERSION_ID >= 70000
  1917. ZEND_HASH_INC_APPLY_COUNT(myht);
  1918. ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, z_val) {
  1919. xdebug_array_element_export_xml_node(z_val, num, key, level, node, name, options);
  1920. } ZEND_HASH_FOREACH_END();
  1921. ZEND_HASH_DEC_APPLY_COUNT(myht);
  1922. #else
  1923. zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) xdebug_array_element_export_xml_node, 4, level, node, name, options);
  1924. #endif
  1925. }
  1926. } else {
  1927. xdebug_xml_add_attribute(node, "recursive", "1");
  1928. }
  1929. break;
  1930. case IS_OBJECT: {
  1931. HashTable *merged_hash;
  1932. zend_class_entry *ce;
  1933. int is_temp;
  1934. #if PHP_VERSION_ID >= 70000
  1935. zend_property_info *zpi_val;
  1936. #endif
  1937. ALLOC_HASHTABLE(merged_hash);
  1938. zend_hash_init(merged_hash, 128, NULL, NULL, 0);
  1939. class_name = (char*) STR_NAME_VAL(Z_OBJCE_P(*struc)->name);
  1940. class_name_len = STR_NAME_LEN(Z_OBJCE_P(*struc)->name);
  1941. ce = xdebug_fetch_class(class_name, class_name_len, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
  1942. /* Adding static properties */
  1943. if (&ce->properties_info) {
  1944. #if PHP_VERSION_ID >= 70000
  1945. ZEND_HASH_INC_APPLY_COUNT(&ce->properties_info);
  1946. ZEND_HASH_FOREACH_PTR(&ce->properties_info, zpi_val) {
  1947. object_item_add_zend_prop_to_merged_hash(zpi_val, merged_hash, (int) XDEBUG_OBJECT_ITEM_TYPE_STATIC_PROPERTY, ce);
  1948. } ZEND_HASH_FOREACH_END();
  1949. ZEND_HASH_DEC_APPLY_COUNT(&ce->properties_info);
  1950. #else
  1951. zend_hash_apply_with_arguments(&ce->properties_info TSRMLS_CC, (apply_func_args_t) object_item_add_zend_prop_to_merged_hash, 3, merged_hash, (int) XDEBUG_OBJECT_ITEM_TYPE_STATIC_PROPERTY, ce);
  1952. #endif
  1953. }
  1954. /* Adding normal properties */
  1955. myht = xdebug_objdebug_pp(struc, &is_temp TSRMLS_CC);
  1956. if (myht) {
  1957. #if PHP_VERSION_ID >= 70000
  1958. zval *tmp_val;
  1959. ZEND_HASH_INC_APPLY_COUNT(myht);
  1960. ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, tmp_val) {
  1961. object_item_add_to_merged_hash(tmp_val, num, key, merged_hash, (int) XDEBUG_OBJECT_ITEM_TYPE_PROPERTY);
  1962. } ZEND_HASH_FOREACH_END();
  1963. ZEND_HASH_DEC_APPLY_COUNT(myht);
  1964. #else
  1965. zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) object_item_add_to_merged_hash, 2, merged_hash, (int) XDEBUG_OBJECT_ITEM_TYPE_PROPERTY);
  1966. #endif
  1967. }
  1968. xdebug_xml_add_attribute(node, "type", "object");
  1969. xdebug_xml_add_attribute_ex(node, "classname", xdstrdup(class_name), 0, 1);
  1970. xdebug_xml_add_attribute(node, "children", merged_hash->nNumOfElements ? "1" : "0");
  1971. if (XDEBUG_APPLY_COUNT(merged_hash) < 1) {
  1972. xdebug_xml_add_attribute_ex(node, "numchildren", xdebug_sprintf("%d", zend_hash_num_elements(merged_hash)), 0, 1);
  1973. if (level < options->max_depth) {
  1974. xdebug_xml_add_attribute_ex(node, "page", xdebug_sprintf("%d", options->runtime[level].page), 0, 1);
  1975. xdebug_xml_add_attribute_ex(node, "pagesize", xdebug_sprintf("%d", options->max_children), 0, 1);
  1976. options->runtime[level].current_element_nr = 0;
  1977. if (level == 0) {
  1978. options->runtime[level].start_element_nr = options->max_children * options->runtime[level].page;
  1979. options->runtime[level].end_element_nr = options->max_children * (options->runtime[level].page + 1);
  1980. } else {
  1981. options->runtime[level].start_element_nr = 0;
  1982. options->runtime[level].end_element_nr = options->max_children;
  1983. }
  1984. #if PHP_VERSION_ID >= 70000
  1985. ZEND_HASH_INC_APPLY_COUNT(merged_hash);
  1986. ZEND_HASH_FOREACH_KEY_PTR(merged_hash, num, key, xoi_val) {
  1987. xdebug_object_element_export_xml_node(xoi_val, num, key, level, node, name, options, class_name);
  1988. } ZEND_HASH_FOREACH_END();
  1989. ZEND_HASH_DEC_APPLY_COUNT(merged_hash);
  1990. #else
  1991. zend_hash_apply_with_arguments(merged_hash TSRMLS_CC, (apply_func_args_t) xdebug_object_element_export_xml_node, 5, level, node, name, options, class_name);
  1992. #endif
  1993. }
  1994. }
  1995. zend_hash_destroy(merged_hash);
  1996. FREE_HASHTABLE(merged_hash);
  1997. break;
  1998. }
  1999. case IS_RESOURCE: {
  2000. char *type_name;
  2001. xdebug_xml_add_attribute(node, "type", "resource");
  2002. #if PHP_VERSION_ID >= 70000
  2003. type_name = (char *) zend_rsrc_list_get_rsrc_type(Z_RES_P(*struc) TSRMLS_CC);
  2004. xdebug_xml_add_text(node, xdebug_sprintf("resource id='%ld' type='%s'", Z_RES_P(*struc)->handle, type_name ? type_name : "Unknown"));
  2005. #else
  2006. type_name = (char *) zend_rsrc_list_get_rsrc_type(Z_LVAL_P(*struc) TSRMLS_CC);
  2007. xdebug_xml_add_text(node, xdebug_sprintf("resource id='%ld' type='%s'", Z_LVAL_P(*struc), type_name ? type_name : "Unknown"));
  2008. #endif
  2009. break;
  2010. }
  2011. #if PHP_VERSION_ID >= 70000
  2012. case IS_UNDEF:
  2013. xdebug_xml_add_attribute(node, "type", "uninitialized");
  2014. break;
  2015. #endif
  2016. default:
  2017. xdebug_xml_add_attribute(node, "type", "null");
  2018. break;
  2019. }
  2020. }
  2021. xdebug_xml_node* xdebug_get_zval_value_xml_node_ex(char *name, zval *val, int var_type, xdebug_var_export_options *options TSRMLS_DC)
  2022. {
  2023. xdebug_xml_node *node;
  2024. char *short_name = NULL;
  2025. char *full_name = NULL;
  2026. node = xdebug_xml_node_init("property");
  2027. if (name) {
  2028. switch (var_type) {
  2029. case XDEBUG_VAR_TYPE_NORMAL: {
  2030. char *tmp_name;
  2031. tmp_name = prepare_variable_name(name);
  2032. short_name = xdstrdup(tmp_name);
  2033. full_name = xdstrdup(tmp_name);
  2034. xdfree(tmp_name);
  2035. } break;
  2036. case XDEBUG_VAR_TYPE_STATIC:
  2037. short_name = xdebug_sprintf("::%s", name);
  2038. full_name = xdebug_sprintf("::%s", name);
  2039. break;
  2040. case XDEBUG_VAR_TYPE_CONSTANT:
  2041. short_name = xdstrdup(name);
  2042. full_name = xdstrdup(name);
  2043. break;
  2044. }
  2045. xdebug_xml_add_attribute_ex(node, "name", short_name, 0, 1);
  2046. xdebug_xml_add_attribute_ex(node, "fullname", full_name, 0, 1);
  2047. }
  2048. xdebug_var_export_xml_node(&val, full_name, node, options, 0 TSRMLS_CC);
  2049. return node;
  2050. }
  2051. /*****************************************************************************
  2052. ** Fancy variable printing routines
  2053. */
  2054. #define COLOR_POINTER "#888a85"
  2055. #define COLOR_BOOL "#75507b"
  2056. #define COLOR_LONG "#4e9a06"
  2057. #define COLOR_NULL "#3465a4"
  2058. #define COLOR_DOUBLE "#f57900"
  2059. #define COLOR_STRING "#cc0000"
  2060. #define COLOR_EMPTY "#888a85"
  2061. #define COLOR_ARRAY "#ce5c00"
  2062. #define COLOR_OBJECT "#8f5902"
  2063. #define COLOR_RESOURCE "#2e3436"
  2064. #if PHP_VERSION_ID >= 70000
  2065. static int xdebug_array_element_export_fancy(zval *zv_nptr, zend_ulong index, zend_string *hash_key, int level, xdebug_str *str, int debug_zval, xdebug_var_export_options *options)
  2066. {
  2067. zval **zv = &zv_nptr;
  2068. #else
  2069. static int xdebug_array_element_export_fancy(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
  2070. {
  2071. int level = va_arg(args, int);
  2072. xdebug_str *str = va_arg(args, struct xdebug_str*);
  2073. int debug_zval = va_arg(args, int);
  2074. xdebug_var_export_options *options = va_arg(args, xdebug_var_export_options*);
  2075. #endif
  2076. size_t newlen;
  2077. char *tmp_str;
  2078. if (options->runtime[level].current_element_nr >= options->runtime[level].start_element_nr &&
  2079. options->runtime[level].current_element_nr < options->runtime[level].end_element_nr)
  2080. {
  2081. xdebug_str_add(str, xdebug_sprintf("%*s", (level * 4) - 2, ""), 1);
  2082. if (HASH_KEY_IS_NUMERIC(hash_key)) { /* numeric key */
  2083. xdebug_str_add(str, xdebug_sprintf("%ld <font color='%s'>=&gt;</font> ", HASH_APPLY_NUMERIC(hash_key), COLOR_POINTER), 1);
  2084. } else { /* string key */
  2085. xdebug_str_addl(str, "'", 1, 0);
  2086. tmp_str = xdebug_xmlize((char*) HASH_APPLY_KEY_VAL(hash_key), HASH_APPLY_KEY_LEN(hash_key) - 1, &newlen);
  2087. xdebug_str_addl(str, tmp_str, newlen, 0);
  2088. efree(tmp_str);
  2089. xdebug_str_add(str, xdebug_sprintf("' <font color='%s'>=&gt;</font> ", COLOR_POINTER), 1);
  2090. }
  2091. xdebug_var_export_fancy(zv, str, level + 1, debug_zval, options TSRMLS_CC);
  2092. }
  2093. if (options->runtime[level].current_element_nr == options->runtime[level].end_element_nr) {
  2094. xdebug_str_add(str, xdebug_sprintf("%*s", (level * 4) - 2, ""), 1);
  2095. xdebug_str_addl(str, "<i>more elements...</i>\n", 24, 0);
  2096. }
  2097. options->runtime[level].current_element_nr++;
  2098. return 0;
  2099. }
  2100. #if PHP_VERSION_ID >= 70000
  2101. static int xdebug_object_element_export_fancy(zval *zv_nptr, zend_ulong index, zend_string *hash_key, int level, xdebug_str *str, int debug_zval, xdebug_var_export_options *options, char *class_name)
  2102. {
  2103. zval **zv = &zv_nptr;
  2104. #else
  2105. static int xdebug_object_element_export_fancy(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
  2106. {
  2107. int level = va_arg(args, int);
  2108. xdebug_str *str = va_arg(args, struct xdebug_str*);
  2109. int debug_zval = va_arg(args, int);
  2110. xdebug_var_export_options *options = va_arg(args, xdebug_var_export_options*);
  2111. char *class_name = va_arg(args, char*);
  2112. #endif
  2113. if (options->runtime[level].current_element_nr >= options->runtime[level].start_element_nr &&
  2114. options->runtime[level].current_element_nr < options->runtime[level].end_element_nr)
  2115. {
  2116. xdebug_str_add(str, xdebug_sprintf("%*s", (level * 4) - 2, ""), 1);
  2117. if (!HASH_KEY_IS_NUMERIC(hash_key)) {
  2118. char *prop_name, *modifier, *prop_class_name;
  2119. modifier = xdebug_get_property_info((char*) HASH_APPLY_KEY_VAL(hash_key), HASH_APPLY_KEY_LEN(hash_key), &prop_name, &prop_class_name);
  2120. if (strcmp(modifier, "private") != 0 || strcmp(class_name, prop_class_name) == 0) {
  2121. xdebug_str_add(str, xdebug_sprintf("<i>%s</i> '%s' <font color='%s'>=&gt;</font> ", modifier, prop_name, COLOR_POINTER), 1);
  2122. } else {
  2123. xdebug_str_add(str, xdebug_sprintf("<i>%s</i> '%s' <small>(%s)</small> <font color='%s'>=&gt;</font> ", modifier, prop_name, prop_class_name, COLOR_POINTER), 1);
  2124. }
  2125. xdfree(prop_name);
  2126. xdfree(prop_class_name);
  2127. } else {
  2128. xdebug_str_add(str, xdebug_sprintf("<i>public</i> %d <font color='%s'>=&gt;</font> ", HASH_APPLY_NUMERIC(hash_key), COLOR_POINTER), 1);
  2129. }
  2130. xdebug_var_export_fancy(zv, str, level + 1, debug_zval, options TSRMLS_CC);
  2131. }
  2132. if (options->runtime[level].current_element_nr == options->runtime[level].end_element_nr) {
  2133. xdebug_str_add(str, xdebug_sprintf("%*s", (level * 4) - 2, ""), 1);
  2134. xdebug_str_addl(str, "<i>more elements...</i>\n", 24, 0);
  2135. }
  2136. options->runtime[level].current_element_nr++;
  2137. return 0;
  2138. }
  2139. void xdebug_var_export_fancy(zval **struc, xdebug_str *str, int level, int debug_zval, xdebug_var_export_options *options TSRMLS_DC)
  2140. {
  2141. HashTable *myht;
  2142. char* tmp_str;
  2143. size_t newlen;
  2144. int is_temp;
  2145. #if PHP_VERSION_ID >= 70000
  2146. zend_ulong num;
  2147. zend_string *key;
  2148. zval *val;
  2149. zval *tmpz;
  2150. #endif
  2151. #if PHP_VERSION_ID >= 70000
  2152. if (debug_zval) {
  2153. if (Z_TYPE_P(*struc) >= IS_STRING && Z_TYPE_P(*struc) != IS_INDIRECT) {
  2154. xdebug_str_add(str, xdebug_sprintf("<i>(refcount=%d, is_ref=%d)</i>", (*struc)->value.counted->gc.refcount, Z_TYPE_P(*struc) == IS_REFERENCE), 1);
  2155. } else {
  2156. xdebug_str_add(str, "<i>(refcount=0, is_ref=0)</i>", 0);
  2157. }
  2158. }
  2159. if (Z_TYPE_P(*struc) == IS_REFERENCE) {
  2160. tmpz = &((*struc)->value.ref->val);
  2161. struc = &tmpz;
  2162. }
  2163. #else
  2164. if (debug_zval) {
  2165. xdebug_str_add(str, xdebug_sprintf("<i>(refcount=%d, is_ref=%d)</i>,", (*struc)->refcount__gc, (*struc)->is_ref__gc), 1);
  2166. }
  2167. #endif
  2168. switch (Z_TYPE_P(*struc)) {
  2169. #if PHP_VERSION_ID >= 70000
  2170. case IS_TRUE:
  2171. case IS_FALSE:
  2172. xdebug_str_add(str, xdebug_sprintf("<small>boolean</small> <font color='%s'>%s</font>", COLOR_BOOL, Z_TYPE_P(*struc) == IS_TRUE ? "true" : "false"), 1);
  2173. break;
  2174. #else
  2175. case IS_BOOL:
  2176. xdebug_str_add(str, xdebug_sprintf("<small>boolean</small> <font color='%s'>%s</font>", COLOR_BOOL, Z_LVAL_P(*struc) ? "true" : "false"), 1);
  2177. break;
  2178. #endif
  2179. case IS_NULL:
  2180. xdebug_str_add(str, xdebug_sprintf("<font color='%s'>null</font>", COLOR_NULL), 1);
  2181. break;
  2182. case IS_LONG:
  2183. xdebug_str_add(str, xdebug_sprintf("<small>int</small> <font color='%s'>" XDEBUG_INT_FMT "</font>", COLOR_LONG, Z_LVAL_P(*struc)), 1);
  2184. break;
  2185. case IS_DOUBLE:
  2186. xdebug_str_add(str, xdebug_sprintf("<small>float</small> <font color='%s'>%.*G</font>", COLOR_DOUBLE, (int) EG(precision), Z_DVAL_P(*struc)), 1);
  2187. break;
  2188. case IS_STRING:
  2189. xdebug_str_add(str, xdebug_sprintf("<small>string</small> <font color='%s'>'", COLOR_STRING), 1);
  2190. if ((size_t) Z_STRLEN_P(*struc) > (size_t) options->max_data) {
  2191. tmp_str = xdebug_xmlize(Z_STRVAL_P(*struc), options->max_data, &newlen);
  2192. xdebug_str_addl(str, tmp_str, newlen, 0);
  2193. efree(tmp_str);
  2194. xdebug_str_addl(str, "'...</font>", 11, 0);
  2195. } else {
  2196. tmp_str = xdebug_xmlize(Z_STRVAL_P(*struc), Z_STRLEN_P(*struc), &newlen);
  2197. xdebug_str_addl(str, tmp_str, newlen, 0);
  2198. efree(tmp_str);
  2199. xdebug_str_addl(str, "'</font>", 8, 0);
  2200. }
  2201. xdebug_str_add(str, xdebug_sprintf(" <i>(length=%d)</i>", Z_STRLEN_P(*struc)), 1);
  2202. break;
  2203. case IS_ARRAY:
  2204. myht = Z_ARRVAL_P(*struc);
  2205. xdebug_str_add(str, xdebug_sprintf("\n%*s", (level - 1) * 4, ""), 1);
  2206. if (XDEBUG_APPLY_COUNT(myht) < 1) {
  2207. xdebug_str_add(str, xdebug_sprintf("<b>array</b> <i>(size=%d)</i>\n", myht->nNumOfElements), 1);
  2208. if (level <= options->max_depth) {
  2209. if (myht->nNumOfElements) {
  2210. options->runtime[level].current_element_nr = 0;
  2211. options->runtime[level].start_element_nr = 0;
  2212. options->runtime[level].end_element_nr = options->max_children;
  2213. #if PHP_VERSION_ID >= 70000
  2214. ZEND_HASH_INC_APPLY_COUNT(myht);
  2215. ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, val) {
  2216. xdebug_array_element_export_fancy(val, num, key, level, str, debug_zval, options);
  2217. } ZEND_HASH_FOREACH_END();
  2218. ZEND_HASH_DEC_APPLY_COUNT(myht);
  2219. #else
  2220. zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) xdebug_array_element_export_fancy, 4, level, str, debug_zval, options);
  2221. #endif
  2222. } else {
  2223. xdebug_str_add(str, xdebug_sprintf("%*s", (level * 4) - 2, ""), 1);
  2224. xdebug_str_add(str, xdebug_sprintf("<i><font color='%s'>empty</font></i>\n", COLOR_EMPTY), 1);
  2225. }
  2226. } else {
  2227. xdebug_str_add(str, xdebug_sprintf("%*s...\n", (level * 4) - 2, ""), 1);
  2228. }
  2229. } else {
  2230. xdebug_str_addl(str, "<i>&amp;</i><b>array</b>\n", 21, 0);
  2231. }
  2232. break;
  2233. case IS_OBJECT:
  2234. myht = xdebug_objdebug_pp(struc, &is_temp TSRMLS_CC);
  2235. xdebug_str_add(str, xdebug_sprintf("\n%*s", (level - 1) * 4, ""), 1);
  2236. if (XDEBUG_APPLY_COUNT(myht) < 1) {
  2237. char *class_name = (char*) STR_NAME_VAL(Z_OBJCE_P(*struc)->name);
  2238. xdebug_str_add(str, xdebug_sprintf("<b>object</b>(<i>%s</i>)", class_name), 1);
  2239. xdebug_str_add(str, xdebug_sprintf("[<i>%d</i>]\n", Z_OBJ_HANDLE_P(*struc)), 1);
  2240. if (level <= options->max_depth) {
  2241. options->runtime[level].current_element_nr = 0;
  2242. options->runtime[level].start_element_nr = 0;
  2243. options->runtime[level].end_element_nr = options->max_children;
  2244. #if PHP_VERSION_ID >= 70000
  2245. ZEND_HASH_INC_APPLY_COUNT(myht);
  2246. ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, val) {
  2247. xdebug_object_element_export_fancy(val, num, key, level, str, debug_zval, options, class_name);
  2248. } ZEND_HASH_FOREACH_END();
  2249. ZEND_HASH_DEC_APPLY_COUNT(myht);
  2250. #else
  2251. zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) xdebug_object_element_export_fancy, 5, level, str, debug_zval, options, class_name);
  2252. #endif
  2253. } else {
  2254. xdebug_str_add(str, xdebug_sprintf("%*s...\n", (level * 4) - 2, ""), 1);
  2255. }
  2256. } else {
  2257. xdebug_str_add(str, xdebug_sprintf("<i>&amp;</i><b>object</b>(<i>%s</i>)", STR_NAME_VAL(Z_OBJCE_P(*struc)->name)), 1);
  2258. xdebug_str_add(str, xdebug_sprintf("[<i>%d</i>]\n", Z_OBJ_HANDLE_P(*struc)), 1);
  2259. }
  2260. if (is_temp) {
  2261. zend_hash_destroy(myht);
  2262. efree(myht);
  2263. }
  2264. break;
  2265. case IS_RESOURCE: {
  2266. char *type_name;
  2267. #if PHP_VERSION_ID >= 70000
  2268. type_name = (char *) zend_rsrc_list_get_rsrc_type(Z_RES_P(*struc) TSRMLS_CC);
  2269. xdebug_str_add(str, xdebug_sprintf("<b>resource</b>(<i>%ld</i><font color='%s'>,</font> <i>%s</i>)", Z_RES_P(*struc)->handle, COLOR_RESOURCE, type_name ? type_name : "Unknown"), 1);
  2270. #else
  2271. type_name = (char *) zend_rsrc_list_get_rsrc_type(Z_LVAL_P(*struc) TSRMLS_CC);
  2272. xdebug_str_add(str, xdebug_sprintf("<b>resource</b>(<i>%ld</i><font color='%s'>,</font> <i>%s</i>)", Z_LVAL_P(*struc), COLOR_RESOURCE, type_name ? type_name : "Unknown"), 1);
  2273. #endif
  2274. break;
  2275. }
  2276. #if PHP_VERSION_ID >= 70000
  2277. case IS_UNDEF:
  2278. xdebug_str_add(str, xdebug_sprintf("<font color='%s'>*uninitialized*</font>", COLOR_NULL), 0);
  2279. break;
  2280. #endif
  2281. default:
  2282. xdebug_str_add(str, xdebug_sprintf("<font color='%s'>NFC</font>", COLOR_NULL), 0);
  2283. break;
  2284. }
  2285. if (Z_TYPE_P(*struc) != IS_ARRAY && Z_TYPE_P(*struc) != IS_OBJECT) {
  2286. xdebug_str_addl(str, "\n", 1, 0);
  2287. }
  2288. }
  2289. char* xdebug_get_zval_value_fancy(char *name, zval *val, int *len, int debug_zval, xdebug_var_export_options *options TSRMLS_DC)
  2290. {
  2291. xdebug_str str = XDEBUG_STR_INITIALIZER;
  2292. int default_options = 0;
  2293. if (!options) {
  2294. options = xdebug_var_export_options_from_ini(TSRMLS_C);
  2295. default_options = 1;
  2296. }
  2297. xdebug_str_addl(&str, "<pre class='xdebug-var-dump' dir='ltr'>", 39, 0);
  2298. if (options->show_location && !debug_zval) {
  2299. if (strlen(XG(file_link_format)) > 0) {
  2300. char *file_link;
  2301. xdebug_format_file_link(&file_link, zend_get_executed_filename(TSRMLS_C), zend_get_executed_lineno(TSRMLS_C) TSRMLS_CC);
  2302. xdebug_str_add(&str, xdebug_sprintf("\n<small><a href='%s'>%s:%d</a>:</small>", file_link, zend_get_executed_filename(TSRMLS_C), zend_get_executed_lineno(TSRMLS_C)), 1);
  2303. xdfree(file_link);
  2304. } else {
  2305. xdebug_str_add(&str, xdebug_sprintf("\n<small>%s:%d:</small>", zend_get_executed_filename(TSRMLS_C), zend_get_executed_lineno(TSRMLS_C)), 1);
  2306. }
  2307. }
  2308. xdebug_var_export_fancy(&val, (xdebug_str*) &str, 1, debug_zval, options TSRMLS_CC);
  2309. xdebug_str_addl(&str, "</pre>", 6, 0);
  2310. if (default_options) {
  2311. xdfree(options->runtime);
  2312. xdfree(options);
  2313. }
  2314. *len = str.l;
  2315. return str.d;
  2316. }
  2317. char* xdebug_get_zval_value_serialized(zval *val, int debug_zval, xdebug_var_export_options *options TSRMLS_DC)
  2318. {
  2319. #if PHP_VERSION_ID >= 70000
  2320. zend_object *orig_exception = EG(exception);
  2321. #endif
  2322. php_serialize_data_t var_hash;
  2323. smart_str buf = {0};
  2324. if (!val) {
  2325. return NULL;
  2326. }
  2327. PHP_VAR_SERIALIZE_INIT(var_hash);
  2328. XG(in_var_serialisation) = 1;
  2329. #if PHP_VERSION_ID >= 70000
  2330. EG(exception) = NULL;
  2331. php_var_serialize(&buf, val, &var_hash TSRMLS_CC);
  2332. orig_exception = EG(exception) = orig_exception;
  2333. #else
  2334. php_var_serialize(&buf, &val, &var_hash TSRMLS_CC);
  2335. #endif
  2336. XG(in_var_serialisation) = 0;
  2337. PHP_VAR_SERIALIZE_DESTROY(var_hash);
  2338. #if PHP_VERSION_ID >= 70000
  2339. if (buf.a) {
  2340. #else
  2341. if (buf.c) {
  2342. #endif
  2343. int new_len;
  2344. char *tmp_base64, *tmp_ret;
  2345. /* now we need to base64 it */
  2346. #if PHP_VERSION_ID >= 70000
  2347. tmp_base64 = (char*) xdebug_base64_encode((unsigned char*) buf.s->val, buf.s->len, &new_len);
  2348. #else
  2349. tmp_base64 = (char*) xdebug_base64_encode((unsigned char*) buf.c, buf.len, &new_len);
  2350. #endif
  2351. /* we need a malloc'ed and not an emalloc'ed string */
  2352. tmp_ret = xdstrdup(tmp_base64);
  2353. efree(tmp_base64);
  2354. smart_str_free(&buf);
  2355. return tmp_ret;
  2356. } else {
  2357. return NULL;
  2358. }
  2359. }
  2360. static void xdebug_var_synopsis_fancy(zval **struc, xdebug_str *str, int level, int debug_zval, xdebug_var_export_options *options TSRMLS_DC)
  2361. {
  2362. HashTable *myht;
  2363. #if PHP_VERSION_ID >= 70000
  2364. zval *tmpz;
  2365. if (debug_zval) {
  2366. if (Z_TYPE_P(*struc) >= IS_STRING && Z_TYPE_P(*struc) != IS_INDIRECT) {
  2367. xdebug_str_add(str, xdebug_sprintf("<i>(refcount=%d, is_ref=%d)</i>", (*struc)->value.counted->gc.refcount, Z_TYPE_P(*struc) == IS_REFERENCE), 1);
  2368. } else {
  2369. xdebug_str_add(str, "<i>(refcount=0, is_ref=0)</i>", 0);
  2370. }
  2371. }
  2372. if (Z_TYPE_P(*struc) == IS_REFERENCE) {
  2373. tmpz = &((*struc)->value.ref->val);
  2374. struc = &tmpz;
  2375. }
  2376. #else
  2377. if (debug_zval) {
  2378. xdebug_str_add(str, xdebug_sprintf("<i>(refcount=%d, is_ref=%d)</i>,", (*struc)->refcount__gc, (*struc)->is_ref__gc), 1);
  2379. }
  2380. #endif
  2381. switch (Z_TYPE_P(*struc)) {
  2382. #if PHP_VERSION_ID >= 70000
  2383. case IS_TRUE:
  2384. case IS_FALSE:
  2385. xdebug_str_add(str, xdebug_sprintf("<font color='%s'>%s</font>", COLOR_BOOL, Z_TYPE_P(*struc) == IS_TRUE ? "true" : "false"), 1);
  2386. break;
  2387. #else
  2388. case IS_BOOL:
  2389. xdebug_str_add(str, xdebug_sprintf("<font color='%s'>bool</font>", COLOR_BOOL), 1);
  2390. break;
  2391. #endif
  2392. case IS_NULL:
  2393. xdebug_str_add(str, xdebug_sprintf("<font color='%s'>null</font>", COLOR_NULL), 1);
  2394. break;
  2395. case IS_LONG:
  2396. xdebug_str_add(str, xdebug_sprintf("<font color='%s'>long</font>", COLOR_LONG), 1);
  2397. break;
  2398. case IS_DOUBLE:
  2399. xdebug_str_add(str, xdebug_sprintf("<font color='%s'>double</font>", COLOR_DOUBLE), 1);
  2400. break;
  2401. case IS_STRING:
  2402. xdebug_str_add(str, xdebug_sprintf("<font color='%s'>string(%d)</font>", COLOR_STRING, Z_STRLEN_P(*struc)), 1);
  2403. break;
  2404. case IS_ARRAY:
  2405. myht = Z_ARRVAL_P(*struc);
  2406. xdebug_str_add(str, xdebug_sprintf("<font color='%s'>array(%d)</font>", COLOR_ARRAY, myht->nNumOfElements), 1);
  2407. break;
  2408. case IS_OBJECT:
  2409. xdebug_str_add(str, xdebug_sprintf("<font color='%s'>object(%s)", COLOR_OBJECT, STR_NAME_VAL(Z_OBJCE_P(*struc)->name)), 1);
  2410. xdebug_str_add(str, xdebug_sprintf("[%d]", Z_OBJ_HANDLE_P(*struc)), 1);
  2411. xdebug_str_addl(str, "</font>", 7, 0);
  2412. break;
  2413. case IS_RESOURCE: {
  2414. char *type_name;
  2415. #if PHP_VERSION_ID >= 70000
  2416. type_name = (char *) zend_rsrc_list_get_rsrc_type(Z_RES_P(*struc) TSRMLS_CC);
  2417. xdebug_str_add(str, xdebug_sprintf("<font color='%s'>resource(%ld, %s)</font>", COLOR_RESOURCE, Z_RES_P(*struc)->handle, type_name ? type_name : "Unknown"), 1);
  2418. #else
  2419. type_name = (char *) zend_rsrc_list_get_rsrc_type(Z_LVAL_P(*struc) TSRMLS_CC);
  2420. xdebug_str_add(str, xdebug_sprintf("<font color='%s'>resource(%ld, %s)</font>", COLOR_RESOURCE, Z_LVAL_P(*struc), type_name ? type_name : "Unknown"), 1);
  2421. #endif
  2422. break;
  2423. }
  2424. #if PHP_VERSION_ID >= 70000
  2425. case IS_UNDEF:
  2426. xdebug_str_add(str, xdebug_sprintf("<font color='%s'>*uninitialized*</font>", COLOR_NULL), 0);
  2427. break;
  2428. #endif
  2429. default:
  2430. xdebug_str_add(str, xdebug_sprintf("<font color='%s'>NFC</font>", COLOR_NULL), 0);
  2431. break;
  2432. }
  2433. }
  2434. char* xdebug_get_zval_synopsis_fancy(char *name, zval *val, int *len, int debug_zval, xdebug_var_export_options *options TSRMLS_DC)
  2435. {
  2436. xdebug_str str = XDEBUG_STR_INITIALIZER;
  2437. int default_options = 0;
  2438. if (!options) {
  2439. options = xdebug_var_export_options_from_ini(TSRMLS_C);
  2440. default_options = 1;
  2441. }
  2442. xdebug_var_synopsis_fancy(&val, (xdebug_str*) &str, 1, debug_zval, options TSRMLS_CC);
  2443. if (default_options) {
  2444. xdfree(options->runtime);
  2445. xdfree(options);
  2446. }
  2447. *len = str.l;
  2448. return str.d;
  2449. }
  2450. /*****************************************************************************
  2451. ** XML encoding function
  2452. */
  2453. char* xdebug_xmlize(char *string, SIZETorINT len, size_t *newlen)
  2454. {
  2455. if (len) {
  2456. char *tmp;
  2457. char *tmp2;
  2458. tmp = xdebug_str_to_str(string, len, "&", 1, "&amp;", 5, &len);
  2459. tmp2 = xdebug_str_to_str(tmp, len, ">", 1, "&gt;", 4, &len);
  2460. efree(tmp);
  2461. tmp = xdebug_str_to_str(tmp2, len, "<", 1, "&lt;", 4, &len);
  2462. efree(tmp2);
  2463. tmp2 = xdebug_str_to_str(tmp, len, "\"", 1, "&quot;", 6, &len);
  2464. efree(tmp);
  2465. tmp = xdebug_str_to_str(tmp2, len, "'", 1, "&#39;", 5, &len);
  2466. efree(tmp2);
  2467. tmp2 = xdebug_str_to_str(tmp, len, "\n", 1, "&#10;", 5, &len);
  2468. efree(tmp);
  2469. tmp = xdebug_str_to_str(tmp2, len, "\r", 1, "&#13;", 5, &len);
  2470. efree(tmp2);
  2471. tmp2 = xdebug_str_to_str(tmp, len, "\0", 1, "&#0;", 4, (SIZETorINT*) newlen);
  2472. efree(tmp);
  2473. return tmp2;
  2474. } else {
  2475. *newlen = len;
  2476. return estrdup(string);
  2477. }
  2478. }
  2479. /*****************************************************************************
  2480. ** Function name printing function
  2481. */
  2482. static char* xdebug_create_doc_link(xdebug_func f TSRMLS_DC)
  2483. {
  2484. char *tmp_target = NULL, *p, *retval;
  2485. switch (f.type) {
  2486. case XFUNC_NORMAL: {
  2487. tmp_target = xdebug_sprintf("function.%s", f.function);
  2488. break;
  2489. }
  2490. case XFUNC_STATIC_MEMBER:
  2491. case XFUNC_MEMBER: {
  2492. if (strcmp(f.function, "__construct") == 0) {
  2493. tmp_target = xdebug_sprintf("%s.construct", f.class);
  2494. } else {
  2495. tmp_target = xdebug_sprintf("%s.%s", f.class, f.function);
  2496. }
  2497. break;
  2498. }
  2499. }
  2500. while ((p = strchr(tmp_target, '_')) != NULL) {
  2501. *p = '-';
  2502. }
  2503. retval = xdebug_sprintf("<a href='%s%s%s' target='_new'>%s</a>\n",
  2504. (PG(docref_root) && PG(docref_root)[0]) ? PG(docref_root) : "http://www.php.net/",
  2505. tmp_target, PG(docref_ext), f.function);
  2506. xdfree(tmp_target);
  2507. return retval;
  2508. }
  2509. char* xdebug_show_fname(xdebug_func f, int html, int flags TSRMLS_DC)
  2510. {
  2511. switch (f.type) {
  2512. case XFUNC_NORMAL: {
  2513. if (PG(html_errors) && html && f.internal) {
  2514. return xdebug_create_doc_link(f TSRMLS_CC);
  2515. } else {
  2516. return xdstrdup(f.function);
  2517. }
  2518. break;
  2519. }
  2520. case XFUNC_STATIC_MEMBER:
  2521. case XFUNC_MEMBER: {
  2522. if (PG(html_errors) && html && f.internal) {
  2523. return xdebug_create_doc_link(f TSRMLS_CC);
  2524. } else {
  2525. return xdebug_sprintf("%s%s%s",
  2526. f.class ? f.class : "?",
  2527. f.type == XFUNC_STATIC_MEMBER ? "::" : "->",
  2528. f.function ? f.function : "?"
  2529. );
  2530. }
  2531. break;
  2532. }
  2533. case XFUNC_EVAL:
  2534. return xdstrdup("eval");
  2535. break;
  2536. case XFUNC_INCLUDE:
  2537. return xdstrdup("include");
  2538. break;
  2539. case XFUNC_INCLUDE_ONCE:
  2540. return xdstrdup("include_once");
  2541. break;
  2542. case XFUNC_REQUIRE:
  2543. return xdstrdup("require");
  2544. break;
  2545. case XFUNC_REQUIRE_ONCE:
  2546. return xdstrdup("require_once");
  2547. break;
  2548. case XFUNC_ZEND_PASS:
  2549. return xdstrdup("{zend_pass}");
  2550. break;
  2551. default:
  2552. return xdstrdup("{unknown}");
  2553. }
  2554. }