| 473 | | /* MINIT/MSHUTDOWN */ |
| 474 | | int xc_coverager_module_init(int module_number TSRMLS_DC) /* {{{ */ |
| | 480 | /* user api */ |
| | 481 | /* {{{ proto array xcache_coverager_decode(string data) |
| | 482 | * decode specified data which is saved by auto dumper to array |
| | 483 | */ |
| | 484 | PHP_FUNCTION(xcache_coverager_decode) |
| | 485 | { |
| | 486 | char *str; |
| | 487 | int len; |
| | 488 | long *p; |
| | 489 | |
| | 490 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len) == FAILURE) { |
| | 491 | return; |
| | 492 | } |
| | 493 | |
| | 494 | array_init(return_value); |
| | 495 | |
| | 496 | p = (long*) str; |
| | 497 | len -= sizeof(long); |
| | 498 | if (len < 0) { |
| | 499 | return; |
| | 500 | } |
| | 501 | if (*p++ != PCOV_HEADER_MAGIC) { |
| | 502 | TRACE("%s", "wrong magic in xcache_coverager_decode"); |
| | 503 | return; |
| | 504 | } |
| | 505 | |
| | 506 | for (; len >= (int) sizeof(long) * 2; len -= sizeof(long) * 2, p += 2) { |
| | 507 | add_index_long(return_value, p[0], p[1] < 0 ? 0 : p[1]); |
| | 508 | } |
| | 509 | } |
| | 510 | /* }}} */ |
| | 511 | /* {{{ proto void xcache_coverager_start([bool clean = true]) |
| | 512 | * starts coverager data collecting |
| | 513 | */ |
| | 514 | PHP_FUNCTION(xcache_coverager_start) |
| | 515 | { |
| | 516 | zend_bool clean = 1; |
| | 517 | |
| | 518 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &clean) == FAILURE) { |
| | 519 | return; |
| | 520 | } |
| | 521 | |
| | 522 | if (clean) { |
| | 523 | xc_coverager_clean(TSRMLS_C); |
| | 524 | } |
| | 525 | |
| | 526 | if (XG(coverager)) { |
| | 527 | xc_coverager_enable(TSRMLS_C); |
| | 528 | } |
| | 529 | else { |
| | 530 | php_error(E_WARNING, "You can only start coverager after you set 'xcache.coverager' to 'On' in ini"); |
| | 531 | } |
| | 532 | } |
| | 533 | /* }}} */ |
| | 534 | /* {{{ proto void xcache_coverager_stop([bool clean = false]) |
| | 535 | * stop coverager data collecting |
| | 536 | */ |
| | 537 | PHP_FUNCTION(xcache_coverager_stop) |
| | 538 | { |
| | 539 | zend_bool clean = 0; |
| | 540 | |
| | 541 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &clean) == FAILURE) { |
| | 542 | return; |
| | 543 | } |
| | 544 | |
| | 545 | xc_coverager_disable(TSRMLS_C); |
| | 546 | if (clean) { |
| | 547 | xc_coverager_clean(TSRMLS_C); |
| | 548 | } |
| | 549 | } |
| | 550 | /* }}} */ |
| | 551 | /* {{{ proto array xcache_coverager_get([bool clean = false]) |
| | 552 | * get coverager data collected |
| | 553 | */ |
| | 554 | PHP_FUNCTION(xcache_coverager_get) |
| | 555 | { |
| | 556 | zend_bool clean = 0; |
| | 557 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &clean) == FAILURE) { |
| | 558 | return; |
| | 559 | } |
| | 560 | |
| | 561 | xc_coverager_dump(return_value TSRMLS_CC); |
| | 562 | if (clean) { |
| | 563 | xc_coverager_clean(TSRMLS_C); |
| | 564 | } |
| | 565 | } |
| | 566 | /* }}} */ |
| | 567 | static zend_function_entry xcache_coverager_functions[] = /* {{{ */ |
| | 568 | { |
| | 569 | PHP_FE(xcache_coverager_decode, NULL) |
| | 570 | PHP_FE(xcache_coverager_start, NULL) |
| | 571 | PHP_FE(xcache_coverager_stop, NULL) |
| | 572 | PHP_FE(xcache_coverager_get, NULL) |
| | 573 | PHP_FE_END |
| | 574 | }; |
| | 575 | /* }}} */ |
| | 576 | |
| | 577 | static int xc_zend_startup(zend_extension *extension) /* {{{ */ |
| | 578 | { |
| | 579 | return SUCCESS; |
| | 580 | } |
| | 581 | /* }}} */ |
| | 582 | static void xc_zend_shutdown(zend_extension *extension) /* {{{ */ |
| | 583 | { |
| | 584 | /* empty */ |
| | 585 | } |
| | 586 | /* }}} */ |
| | 587 | static void xc_statement_handler(zend_op_array *op_array) /* {{{ */ |
| | 588 | { |
| | 589 | #ifdef HAVE_XCACHE_COVERAGER |
| | 590 | xc_coverager_handle_ext_stmt(op_array, ZEND_EXT_STMT); |
| | 591 | #endif |
| | 592 | } |
| | 593 | /* }}} */ |
| | 594 | static void xc_fcall_begin_handler(zend_op_array *op_array) /* {{{ */ |
| | 595 | { |
| | 596 | #if 0 |
| | 597 | xc_coverager_handle_ext_stmt(op_array, ZEND_EXT_FCALL_BEGIN); |
| | 598 | #endif |
| | 599 | } |
| | 600 | /* }}} */ |
| | 601 | static void xc_fcall_end_handler(zend_op_array *op_array) /* {{{ */ |
| | 602 | { |
| | 603 | #if 0 |
| | 604 | xc_coverager_handle_ext_stmt(op_array, ZEND_EXT_FCALL_END); |
| | 605 | #endif |
| | 606 | } |
| | 607 | /* }}} */ |
| | 608 | /* {{{ zend extension definition structure */ |
| | 609 | static zend_extension xc_coverager_zend_extension_entry = { |
| | 610 | XCACHE_NAME " Coverager", |
| | 611 | XCACHE_VERSION, |
| | 612 | XCACHE_AUTHOR, |
| | 613 | XCACHE_URL, |
| | 614 | XCACHE_COPYRIGHT, |
| | 615 | xc_zend_startup, |
| | 616 | xc_zend_shutdown, |
| | 617 | NULL, /* activate_func_t */ |
| | 618 | NULL, /* deactivate_func_t */ |
| | 619 | NULL, /* message_handler_func_t */ |
| | 620 | NULL, /* statement_handler_func_t */ |
| | 621 | xc_statement_handler, |
| | 622 | xc_fcall_begin_handler, |
| | 623 | xc_fcall_end_handler, |
| | 624 | NULL, /* op_array_ctor_func_t */ |
| | 625 | NULL, /* op_array_dtor_func_t */ |
| | 626 | STANDARD_ZEND_EXTENSION_PROPERTIES |
| | 627 | }; |
| | 628 | /* }}} */ |
| | 629 | /* {{{ PHP_INI */ |
| | 630 | PHP_INI_BEGIN() |
| | 631 | STD_PHP_INI_BOOLEAN("xcache.coverager" , "0", PHP_INI_ALL, OnUpdateBool, coverager, zend_xcache_globals, xcache_globals) |
| | 632 | PHP_INI_ENTRY1 ("xcache.coveragedump_directory", "", PHP_INI_SYSTEM, xcache_OnUpdateDummy, NULL) |
| | 633 | PHP_INI_END() |
| | 634 | /* }}} */ |
| | 635 | static PHP_MINFO_FUNCTION(xcache_coverager) /* {{{ */ |
| | 636 | { |
| | 637 | char *covdumpdir; |
| | 638 | |
| | 639 | php_info_print_table_start(); |
| | 640 | php_info_print_table_row(2, "XCache Coverager Version", XCACHE_VERSION); |
| | 641 | if (cfg_get_string("xcache.coveragedump_directory", &covdumpdir) != SUCCESS || !covdumpdir[0]) { |
| | 642 | covdumpdir = NULL; |
| | 643 | } |
| | 644 | php_info_print_table_row(2, "Coverage Auto Dumper", XG(coverager) && covdumpdir ? "enabled" : "disabled"); |
| | 645 | php_info_print_table_end(); |
| | 646 | |
| | 647 | DISPLAY_INI_ENTRIES(); |
| | 648 | } |
| | 649 | /* }}} */ |
| | 650 | static PHP_MINIT_FUNCTION(xcache_coverager) /* {{{ */ |
| 506 | | } |
| 507 | | /* }}} */ |
| 508 | | |
| 509 | | /* user api */ |
| 510 | | /* {{{ proto array xcache_coverager_decode(string data) |
| 511 | | * decode specified data which is saved by auto dumper to array |
| 512 | | */ |
| 513 | | PHP_FUNCTION(xcache_coverager_decode) |
| 514 | | { |
| 515 | | char *str; |
| 516 | | int len; |
| 517 | | long *p; |
| 518 | | |
| 519 | | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len) == FAILURE) { |
| 520 | | return; |
| 521 | | } |
| 522 | | |
| 523 | | array_init(return_value); |
| 524 | | |
| 525 | | p = (long*) str; |
| 526 | | len -= sizeof(long); |
| 527 | | if (len < 0) { |
| 528 | | return; |
| 529 | | } |
| 530 | | if (*p++ != PCOV_HEADER_MAGIC) { |
| 531 | | TRACE("%s", "wrong magic in xcache_coverager_decode"); |
| 532 | | return; |
| 533 | | } |
| 534 | | |
| 535 | | for (; len >= (int) sizeof(long) * 2; len -= sizeof(long) * 2, p += 2) { |
| 536 | | add_index_long(return_value, p[0], p[1] < 0 ? 0 : p[1]); |
| 537 | | } |
| 538 | | } |
| 539 | | /* }}} */ |
| 540 | | /* {{{ proto void xcache_coverager_start([bool clean = true]) |
| 541 | | * starts coverager data collecting |
| 542 | | */ |
| 543 | | PHP_FUNCTION(xcache_coverager_start) |
| 544 | | { |
| 545 | | zend_bool clean = 1; |
| 546 | | |
| 547 | | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &clean) == FAILURE) { |
| 548 | | return; |
| 549 | | } |
| 550 | | |
| 551 | | if (clean) { |
| 552 | | xc_coverager_clean(TSRMLS_C); |
| 553 | | } |
| 554 | | |
| 555 | | if (XG(coverager)) { |
| 556 | | xc_coverager_enable(TSRMLS_C); |
| 557 | | } |
| 558 | | else { |
| 559 | | php_error(E_WARNING, "You can only start coverager after you set 'xcache.coverager' to 'On' in ini"); |
| 560 | | } |
| 561 | | } |
| 562 | | /* }}} */ |
| 563 | | /* {{{ proto void xcache_coverager_stop([bool clean = false]) |
| 564 | | * stop coverager data collecting |
| 565 | | */ |
| 566 | | PHP_FUNCTION(xcache_coverager_stop) |
| 567 | | { |
| 568 | | zend_bool clean = 0; |
| 569 | | |
| 570 | | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &clean) == FAILURE) { |
| 571 | | return; |
| 572 | | } |
| 573 | | |
| 574 | | xc_coverager_disable(TSRMLS_C); |
| 575 | | if (clean) { |
| 576 | | xc_coverager_clean(TSRMLS_C); |
| 577 | | } |
| 578 | | } |
| 579 | | /* }}} */ |
| 580 | | /* {{{ proto array xcache_coverager_get([bool clean = false]) |
| 581 | | * get coverager data collected |
| 582 | | */ |
| 583 | | PHP_FUNCTION(xcache_coverager_get) |
| 584 | | { |
| 585 | | zend_bool clean = 0; |
| 586 | | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &clean) == FAILURE) { |
| 587 | | return; |
| 588 | | } |
| 589 | | |
| 590 | | xc_coverager_dump(return_value TSRMLS_CC); |
| 591 | | if (clean) { |
| 592 | | xc_coverager_clean(TSRMLS_C); |
| 593 | | } |
| 594 | | } |
| 595 | | /* }}} */ |
| | 684 | UNREGISTER_INI_ENTRIES(); |
| | 685 | return xcache_zend_extension_unregister(&xc_coverager_zend_extension_entry); |
| | 686 | } |
| | 687 | /* }}} */ |
| | 688 | |
| | 689 | static zend_module_entry xcache_coverager_module_entry = { /* {{{ */ |
| | 690 | STANDARD_MODULE_HEADER, |
| | 691 | XCACHE_NAME "_Coverager", |
| | 692 | xcache_coverager_functions, |
| | 693 | PHP_MINIT(xcache_coverager), |
| | 694 | PHP_MSHUTDOWN(xcache_coverager), |
| | 695 | PHP_RINIT(xcache_coverager), |
| | 696 | PHP_RSHUTDOWN(xcache_coverager), |
| | 697 | PHP_MINFO(xcache_coverager), |
| | 698 | XCACHE_VERSION, |
| | 699 | #ifdef PHP_GINIT |
| | 700 | NO_MODULE_GLOBALS, |
| | 701 | #endif |
| | 702 | #ifdef ZEND_ENGINE_2 |
| | 703 | NULL, |
| | 704 | #else |
| | 705 | NULL, |
| | 706 | NULL, |
| | 707 | #endif |
| | 708 | STANDARD_MODULE_PROPERTIES_EX |
| | 709 | }; |
| | 710 | /* }}} */ |
| | 711 | int xc_coverager_startup_module() /* {{{ */ |
| | 712 | { |
| | 713 | return zend_startup_module(&xcache_coverager_module_entry); |
| | 714 | } |
| | 715 | /* }}} */ |