3838
3939#ifdef HAVE_RL_CALLBACK_READ_CHAR
4040
41- static zval _prepped_callback ;
41+ static zend_fcall_info_cache _prepped_callback ;
4242
4343#endif
4444
45- static zval _readline_completion ;
45+ static zend_fcall_info_cache _readline_completion ;
4646static zval _readline_array ;
4747
4848ZEND_TLS char * php_readline_custom_readline_name = NULL ;
@@ -81,9 +81,9 @@ PHP_MINIT_FUNCTION(readline)
8181 /* libedit don't need this call which set the tty in cooked mode */
8282 using_history ();
8383#endif
84- ZVAL_UNDEF ( & _readline_completion ) ;
84+ _readline_completion = empty_fcall_info_cache ;
8585#ifdef HAVE_RL_CALLBACK_READ_CHAR
86- ZVAL_UNDEF ( & _prepped_callback ) ;
86+ _prepped_callback = empty_fcall_info_cache ;
8787#endif
8888
8989 register_readline_symbols (module_number );
@@ -98,13 +98,13 @@ PHP_MSHUTDOWN_FUNCTION(readline)
9898
9999PHP_RSHUTDOWN_FUNCTION (readline )
100100{
101- zval_ptr_dtor (& _readline_completion );
102- ZVAL_UNDEF (& _readline_completion );
101+ if (ZEND_FCC_INITIALIZED (_readline_completion )) {
102+ zend_fcc_dtor (& _readline_completion );
103+ }
103104#ifdef HAVE_RL_CALLBACK_READ_CHAR
104- if (Z_TYPE (_prepped_callback ) != IS_UNDEF ) {
105+ if (ZEND_FCC_INITIALIZED (_prepped_callback )) {
105106 rl_callback_handler_remove ();
106- zval_ptr_dtor (& _prepped_callback );
107- ZVAL_UNDEF (& _prepped_callback );
107+ zend_fcc_dtor (& _prepped_callback );
108108 }
109109#endif
110110
@@ -449,24 +449,25 @@ char **php_readline_completion_cb(const char *text, int start, int end)
449449 ZVAL_LONG (& params [1 ], start );
450450 ZVAL_LONG (& params [2 ], end );
451451
452- if ( call_user_function ( NULL , NULL , & _readline_completion , & _readline_array , 3 , params ) == SUCCESS ) {
453- if ( Z_TYPE ( _readline_array ) == IS_ARRAY ) {
454- SEPARATE_ARRAY ( & _readline_array );
455- if (zend_hash_num_elements ( Z_ARRVAL ( _readline_array )) ) {
456- matches = rl_completion_matches ( text , _readline_command_generator );
457- } else {
458- /* libedit will read matches[2] */
459- matches = calloc ( 3 , sizeof ( char * ));
460- if (! matches ) {
461- goto out ;
462- }
463- matches [ 0 ] = strdup ( "" ) ;
452+ zend_call_known_fcc ( & _readline_completion , & _readline_array , 3 , params , NULL );
453+ zval_ptr_dtor ( & params [ 0 ]);
454+
455+ if (Z_TYPE ( _readline_array ) == IS_ARRAY ) {
456+ SEPARATE_ARRAY ( & _readline_array );
457+ if ( zend_hash_num_elements ( Z_ARRVAL ( _readline_array ))) {
458+ matches = rl_completion_matches ( text , _readline_command_generator );
459+ } else {
460+ /* libedit will read matches[2] */
461+ matches = calloc ( 3 , sizeof ( char * )) ;
462+ if (! matches ) {
463+ goto out ;
464464 }
465+ matches [0 ] = strdup ("" );
465466 }
466467 }
468+ // TODO: TypeError if return value is not array?
467469
468470out :
469- zval_ptr_dtor (& params [0 ]);
470471 zval_ptr_dtor (& _readline_array );
471472
472473 return matches ;
@@ -477,12 +478,14 @@ PHP_FUNCTION(readline_completion_function)
477478 zend_fcall_info fci ;
478479 zend_fcall_info_cache fcc ;
479480
480- if (FAILURE == zend_parse_parameters (ZEND_NUM_ARGS (), "f " , & fci , & fcc )) {
481+ if (FAILURE == zend_parse_parameters (ZEND_NUM_ARGS (), "F " , & fci , & fcc )) {
481482 RETURN_THROWS ();
482483 }
483484
484- zval_ptr_dtor (& _readline_completion );
485- ZVAL_COPY (& _readline_completion , & fci .function_name );
485+ if (ZEND_FCC_INITIALIZED (_readline_completion )) {
486+ zend_fcc_dtor (& _readline_completion );
487+ }
488+ zend_fcc_dup (& _readline_completion , & fcc );
486489
487490 /* NOTE: The rl_attempted_completion_function variable (and others) are part of the readline library, not php */
488491 rl_attempted_completion_function = php_readline_completion_cb ;
@@ -497,14 +500,12 @@ PHP_FUNCTION(readline_completion_function)
497500static void php_rl_callback_handler (char * the_line )
498501{
499502 zval params [1 ];
500- zval dummy ;
501503
502504 _readline_string_zval (& params [0 ], the_line );
503505
504- call_user_function ( NULL , NULL , & _prepped_callback , & dummy , 1 , params );
506+ zend_call_known_fcc ( & _prepped_callback , NULL , 1 , params , NULL );
505507
506508 zval_ptr_dtor (& params [0 ]);
507- zval_ptr_dtor (& dummy );
508509}
509510
510511/* {{{ Initializes the readline callback interface and terminal, prints the prompt and returns immediately */
@@ -515,16 +516,16 @@ PHP_FUNCTION(readline_callback_handler_install)
515516 zend_fcall_info_cache fcc ;
516517 size_t prompt_len ;
517518
518- if (FAILURE == zend_parse_parameters (ZEND_NUM_ARGS (), "sf " , & prompt , & prompt_len , & fci , & fcc )) {
519+ if (FAILURE == zend_parse_parameters (ZEND_NUM_ARGS (), "sF " , & prompt , & prompt_len , & fci , & fcc )) {
519520 RETURN_THROWS ();
520521 }
521522
522- if (Z_TYPE (_prepped_callback ) != IS_UNDEF ) {
523+ if (ZEND_FCC_INITIALIZED (_prepped_callback )) {
523524 rl_callback_handler_remove ();
524- zval_ptr_dtor (& _prepped_callback );
525+ zend_fcc_dtor (& _prepped_callback );
525526 }
526527
527- ZVAL_COPY (& _prepped_callback , & fci . function_name );
528+ zend_fcc_dup (& _prepped_callback , & fcc );
528529
529530 rl_callback_handler_install (prompt , php_rl_callback_handler );
530531
@@ -537,7 +538,7 @@ PHP_FUNCTION(readline_callback_read_char)
537538{
538539 ZEND_PARSE_PARAMETERS_NONE ();
539540
540- if (Z_TYPE (_prepped_callback ) != IS_UNDEF ) {
541+ if (ZEND_FCC_INITIALIZED (_prepped_callback )) {
541542 rl_callback_read_char ();
542543 }
543544}
@@ -548,10 +549,10 @@ PHP_FUNCTION(readline_callback_handler_remove)
548549{
549550 ZEND_PARSE_PARAMETERS_NONE ();
550551
551- if (Z_TYPE (_prepped_callback ) != IS_UNDEF ) {
552+ if (ZEND_FCC_INITIALIZED (_prepped_callback )) {
552553 rl_callback_handler_remove ();
553- zval_ptr_dtor (& _prepped_callback );
554- ZVAL_UNDEF ( & _prepped_callback ) ;
554+ zend_fcc_dtor (& _prepped_callback );
555+ _prepped_callback = empty_fcall_info_cache ;
555556 RETURN_TRUE ;
556557 }
557558 RETURN_FALSE ;
0 commit comments