Annotation of embedaddon/php/ext/readline/readline.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
                      5:    | Copyright (c) 1997-2012 The PHP Group                                |
                      6:    +----------------------------------------------------------------------+
                      7:    | This source file is subject to version 3.01 of the PHP license,      |
                      8:    | that is bundled with this package in the file LICENSE, and is        |
                      9:    | available through the world-wide-web at the following url:           |
                     10:    | http://www.php.net/license/3_01.txt                                  |
                     11:    | If you did not receive a copy of the PHP license and are unable to   |
                     12:    | obtain it through the world-wide-web, please send a note to          |
                     13:    | license@php.net so we can mail you a copy immediately.               |
                     14:    +----------------------------------------------------------------------+
                     15:    | Author: Thies C. Arntzen <thies@thieso.net>                          |
                     16:    +----------------------------------------------------------------------+
                     17: */
                     18: 
1.1.1.2 ! misho      19: /* $Id$ */
1.1       misho      20: 
                     21: /* {{{ includes & prototypes */
                     22: 
                     23: #ifdef HAVE_CONFIG_H
                     24: #include "config.h"
                     25: #endif
                     26: 
                     27: #include "php.h"
                     28: #include "php_readline.h"
1.1.1.2 ! misho      29: #include "readline_cli.h"
1.1       misho      30: 
                     31: #if HAVE_LIBREADLINE || HAVE_LIBEDIT
                     32: 
                     33: #ifndef HAVE_RL_COMPLETION_MATCHES
                     34: #define rl_completion_matches completion_matches
                     35: #endif
                     36: 
                     37: #ifdef HAVE_LIBEDIT
                     38: #include <editline/readline.h>
                     39: #else
                     40: #include <readline/readline.h>
                     41: #include <readline/history.h>
                     42: #endif
                     43: 
                     44: PHP_FUNCTION(readline);
                     45: PHP_FUNCTION(readline_add_history);
                     46: PHP_FUNCTION(readline_info);
                     47: PHP_FUNCTION(readline_clear_history);
                     48: #ifndef HAVE_LIBEDIT
                     49: PHP_FUNCTION(readline_list_history);
                     50: #endif
                     51: PHP_FUNCTION(readline_read_history);
                     52: PHP_FUNCTION(readline_write_history);
                     53: PHP_FUNCTION(readline_completion_function);
                     54: 
                     55: #if HAVE_RL_CALLBACK_READ_CHAR
                     56: PHP_FUNCTION(readline_callback_handler_install);
                     57: PHP_FUNCTION(readline_callback_read_char);
                     58: PHP_FUNCTION(readline_callback_handler_remove);
                     59: PHP_FUNCTION(readline_redisplay);
                     60: PHP_FUNCTION(readline_on_new_line);
                     61: 
                     62: static zval *_prepped_callback = NULL;
                     63: 
                     64: #endif
                     65: 
                     66: static zval *_readline_completion = NULL;
                     67: static zval _readline_array;
                     68: 
                     69: PHP_MINIT_FUNCTION(readline);
1.1.1.2 ! misho      70: PHP_MSHUTDOWN_FUNCTION(readline);
1.1       misho      71: PHP_RSHUTDOWN_FUNCTION(readline);
1.1.1.2 ! misho      72: PHP_MINFO_FUNCTION(readline);
1.1       misho      73: 
                     74: /* }}} */
                     75: 
                     76: /* {{{ arginfo */
                     77: ZEND_BEGIN_ARG_INFO_EX(arginfo_readline, 0, 0, 0)
                     78:        ZEND_ARG_INFO(0, prompt)
                     79: ZEND_END_ARG_INFO()
                     80: 
                     81: ZEND_BEGIN_ARG_INFO_EX(arginfo_readline_info, 0, 0, 0)
                     82:        ZEND_ARG_INFO(0, varname)
                     83:        ZEND_ARG_INFO(0, newvalue)
                     84: ZEND_END_ARG_INFO()
                     85: 
                     86: ZEND_BEGIN_ARG_INFO_EX(arginfo_readline_add_history, 0, 0, 1)
                     87:        ZEND_ARG_INFO(0, prompt)
                     88: ZEND_END_ARG_INFO()
                     89: 
                     90: ZEND_BEGIN_ARG_INFO(arginfo_readline_clear_history, 0)
                     91: ZEND_END_ARG_INFO()
                     92: 
                     93: #ifndef HAVE_LIBEDIT
                     94: ZEND_BEGIN_ARG_INFO(arginfo_readline_list_history, 0)
                     95: ZEND_END_ARG_INFO()
                     96: #endif
                     97: 
                     98: ZEND_BEGIN_ARG_INFO_EX(arginfo_readline_read_history, 0, 0, 0)
                     99:        ZEND_ARG_INFO(0, filename)
                    100: ZEND_END_ARG_INFO()
                    101: 
                    102: ZEND_BEGIN_ARG_INFO_EX(arginfo_readline_write_history, 0, 0, 0)
                    103:        ZEND_ARG_INFO(0, filename)
                    104: ZEND_END_ARG_INFO()
                    105: 
                    106: ZEND_BEGIN_ARG_INFO_EX(arginfo_readline_completion_function, 0, 0, 1)
                    107:        ZEND_ARG_INFO(0, funcname)
                    108: ZEND_END_ARG_INFO()
                    109: 
                    110: #if HAVE_RL_CALLBACK_READ_CHAR
                    111: ZEND_BEGIN_ARG_INFO_EX(arginfo_readline_callback_handler_install, 0, 0, 2)
                    112:        ZEND_ARG_INFO(0, prompt)
                    113:        ZEND_ARG_INFO(0, callback)
                    114: ZEND_END_ARG_INFO()
                    115: 
                    116: ZEND_BEGIN_ARG_INFO(arginfo_readline_callback_read_char, 0)
                    117: ZEND_END_ARG_INFO()
                    118: 
                    119: ZEND_BEGIN_ARG_INFO(arginfo_readline_callback_handler_remove, 0)
                    120: ZEND_END_ARG_INFO()
                    121: 
                    122: ZEND_BEGIN_ARG_INFO(arginfo_readline_redisplay, 0)
                    123: ZEND_END_ARG_INFO()
                    124: 
                    125: ZEND_BEGIN_ARG_INFO(arginfo_readline_on_new_line, 0)
                    126: ZEND_END_ARG_INFO()
                    127: #endif
                    128: /* }}} */
                    129: 
                    130: /* {{{ module stuff */
                    131: static const zend_function_entry php_readline_functions[] = {
                    132:        PHP_FE(readline,                                arginfo_readline)
                    133:        PHP_FE(readline_info,               arginfo_readline_info)
                    134:        PHP_FE(readline_add_history,            arginfo_readline_add_history)
                    135:        PHP_FE(readline_clear_history,          arginfo_readline_clear_history)
                    136: #ifndef HAVE_LIBEDIT
                    137:        PHP_FE(readline_list_history,           arginfo_readline_list_history)
                    138: #endif
                    139:        PHP_FE(readline_read_history,           arginfo_readline_read_history)
                    140:        PHP_FE(readline_write_history,          arginfo_readline_write_history)
                    141:        PHP_FE(readline_completion_function,arginfo_readline_completion_function)
                    142: #if HAVE_RL_CALLBACK_READ_CHAR
                    143:        PHP_FE(readline_callback_handler_install, arginfo_readline_callback_handler_install)
                    144:        PHP_FE(readline_callback_read_char,                     arginfo_readline_callback_read_char)
                    145:        PHP_FE(readline_callback_handler_remove,        arginfo_readline_callback_handler_remove)
                    146:        PHP_FE(readline_redisplay, arginfo_readline_redisplay)
1.1.1.2 ! misho     147: #endif
        !           148: #if HAVE_RL_ON_NEW_LINE
1.1       misho     149:        PHP_FE(readline_on_new_line, arginfo_readline_on_new_line)
                    150: #endif
                    151:        PHP_FE_END
                    152: };
                    153: 
                    154: zend_module_entry readline_module_entry = { 
                    155:        STANDARD_MODULE_HEADER,
                    156:        "readline", 
                    157:        php_readline_functions, 
                    158:        PHP_MINIT(readline), 
1.1.1.2 ! misho     159:        PHP_MSHUTDOWN(readline),
1.1       misho     160:        NULL,
                    161:        PHP_RSHUTDOWN(readline),
1.1.1.2 ! misho     162:        PHP_MINFO(readline), 
        !           163:        PHP_VERSION,
1.1       misho     164:        STANDARD_MODULE_PROPERTIES
                    165: };
                    166: 
                    167: #ifdef COMPILE_DL_READLINE
                    168: ZEND_GET_MODULE(readline)
                    169: #endif
                    170: 
                    171: PHP_MINIT_FUNCTION(readline)
                    172: {
                    173:        using_history();
1.1.1.2 ! misho     174:        return PHP_MINIT(cli_readline)(INIT_FUNC_ARGS_PASSTHRU);
        !           175: }
        !           176: 
        !           177: PHP_MSHUTDOWN_FUNCTION(readline)
        !           178: {
        !           179:        return PHP_MSHUTDOWN(cli_readline)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
1.1       misho     180: }
                    181: 
                    182: PHP_RSHUTDOWN_FUNCTION(readline)
                    183: {
                    184:        if (_readline_completion) {
                    185:                zval_dtor(_readline_completion);
                    186:                FREE_ZVAL(_readline_completion);
                    187:        }
                    188: #if HAVE_RL_CALLBACK_READ_CHAR
                    189:        if (_prepped_callback) {
                    190:                rl_callback_handler_remove();
                    191:                zval_ptr_dtor(&_prepped_callback);
                    192:                _prepped_callback = 0;
                    193:        }
                    194: #endif
                    195: 
                    196:        return SUCCESS;
                    197: }
                    198: 
1.1.1.2 ! misho     199: PHP_MINFO_FUNCTION(readline)
        !           200: {
        !           201:        return PHP_MINFO(cli_readline)(ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU);
        !           202: }
        !           203: 
1.1       misho     204: /* }}} */
                    205: 
                    206: /* {{{ proto string readline([string prompt]) 
                    207:    Reads a line */
                    208: PHP_FUNCTION(readline)
                    209: {
                    210:        char *prompt = NULL;
                    211:        int prompt_len;
                    212:        char *result;
                    213: 
                    214:        if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!", &prompt, &prompt_len)) {
                    215:                RETURN_FALSE;
                    216:        }
                    217: 
                    218:        result = readline(prompt);
                    219: 
                    220:        if (! result) {
                    221:                RETURN_FALSE;
                    222:        } else {
                    223:                RETVAL_STRING(result,1);
                    224:                free(result);
                    225:        }
                    226: }
                    227: 
                    228: /* }}} */
                    229: 
                    230: #define SAFE_STRING(s) ((s)?(char*)(s):"")
                    231: 
                    232: /* {{{ proto mixed readline_info([string varname [, string newvalue]]) 
                    233:    Gets/sets various internal readline variables. */
                    234: PHP_FUNCTION(readline_info)
                    235: {
                    236:        char *what = NULL;
                    237:        zval **value = NULL;
                    238:        int what_len, oldval;
                    239:        char *oldstr;
                    240: 
                    241:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sZ", &what, &what_len, &value) == FAILURE) {
                    242:                return;
                    243:        }
                    244: 
                    245:        if (!what) {
                    246:                array_init(return_value);
                    247:                add_assoc_string(return_value,"line_buffer",SAFE_STRING(rl_line_buffer),1);
                    248:                add_assoc_long(return_value,"point",rl_point);
                    249:                add_assoc_long(return_value,"end",rl_end);
                    250: #ifdef HAVE_LIBREADLINE
                    251:                add_assoc_long(return_value,"mark",rl_mark);
                    252:                add_assoc_long(return_value,"done",rl_done);
                    253:                add_assoc_long(return_value,"pending_input",rl_pending_input);
                    254:                add_assoc_string(return_value,"prompt",SAFE_STRING(rl_prompt),1);
                    255:                add_assoc_string(return_value,"terminal_name",(char *)SAFE_STRING(rl_terminal_name),1);
                    256: #endif
                    257: #if HAVE_ERASE_EMPTY_LINE
                    258:                add_assoc_long(return_value,"erase_empty_line",rl_erase_empty_line);
                    259: #endif
                    260:                add_assoc_string(return_value,"library_version",(char *)SAFE_STRING(rl_library_version),1);
                    261:                add_assoc_string(return_value,"readline_name",(char *)SAFE_STRING(rl_readline_name),1);
                    262:        } else {
                    263:                if (!strcasecmp(what,"line_buffer")) {
                    264:                        oldstr = rl_line_buffer;
                    265:                        if (value) {
                    266:                                /* XXX if (rl_line_buffer) free(rl_line_buffer); */
                    267:                                convert_to_string_ex(value);
                    268:                                rl_line_buffer = strdup(Z_STRVAL_PP(value));
                    269:                        }
                    270:                        RETVAL_STRING(SAFE_STRING(oldstr),1);
                    271:                } else if (!strcasecmp(what, "point")) {
                    272:                        RETVAL_LONG(rl_point);
                    273:                } else if (!strcasecmp(what, "end")) {
                    274:                        RETVAL_LONG(rl_end);
                    275: #ifdef HAVE_LIBREADLINE
                    276:                } else if (!strcasecmp(what, "mark")) {
                    277:                        RETVAL_LONG(rl_mark);
                    278:                } else if (!strcasecmp(what, "done")) {
                    279:                        oldval = rl_done;
                    280:                        if (value) {
                    281:                                convert_to_long_ex(value);
                    282:                                rl_done = Z_LVAL_PP(value);
                    283:                        }
                    284:                        RETVAL_LONG(oldval);
                    285:                } else if (!strcasecmp(what, "pending_input")) {
                    286:                        oldval = rl_pending_input;
                    287:                        if (value) {
                    288:                                convert_to_string_ex(value);
                    289:                                rl_pending_input = Z_STRVAL_PP(value)[0];
                    290:                        }
                    291:                        RETVAL_LONG(oldval);
                    292:                } else if (!strcasecmp(what, "prompt")) {
                    293:                        RETVAL_STRING(SAFE_STRING(rl_prompt),1);
                    294:                } else if (!strcasecmp(what, "terminal_name")) {
                    295:                        RETVAL_STRING((char *)SAFE_STRING(rl_terminal_name),1);
                    296: #endif
                    297: #if HAVE_ERASE_EMPTY_LINE
                    298:                } else if (!strcasecmp(what, "erase_empty_line")) {
                    299:                        oldval = rl_erase_empty_line;
                    300:                        if (value) {
                    301:                                convert_to_long_ex(value);
                    302:                                rl_erase_empty_line = Z_LVAL_PP(value);
                    303:                        }
                    304:                        RETVAL_LONG(oldval);
                    305: #endif
                    306:                } else if (!strcasecmp(what,"library_version")) {
                    307:                        RETVAL_STRING((char *)SAFE_STRING(rl_library_version),1);
                    308:                } else if (!strcasecmp(what, "readline_name")) {
                    309:                        oldstr = (char*)rl_readline_name;
                    310:                        if (value) {
                    311:                                /* XXX if (rl_readline_name) free(rl_readline_name); */
                    312:                                convert_to_string_ex(value);
                    313:                                rl_readline_name = strdup(Z_STRVAL_PP(value));;
                    314:                        }
                    315:                        RETVAL_STRING(SAFE_STRING(oldstr),1);
                    316:                } 
                    317:        }
                    318: }
                    319: 
                    320: /* }}} */
                    321: /* {{{ proto bool readline_add_history(string prompt) 
                    322:    Adds a line to the history */
                    323: PHP_FUNCTION(readline_add_history)
                    324: {
                    325:        char *arg;
                    326:        int arg_len;
                    327: 
                    328:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
                    329:                return;
                    330:        }
                    331: 
                    332:        add_history(arg);
                    333: 
                    334:        RETURN_TRUE;
                    335: }
                    336: 
                    337: /* }}} */
                    338: /* {{{ proto bool readline_clear_history(void) 
                    339:    Clears the history */
                    340: PHP_FUNCTION(readline_clear_history)
                    341: {
                    342:        if (zend_parse_parameters_none() == FAILURE) {
                    343:                return;
                    344:        }
                    345: 
                    346:        clear_history();
                    347: 
                    348:        RETURN_TRUE;
                    349: }
                    350: 
                    351: /* }}} */
                    352: /* {{{ proto array readline_list_history(void) 
                    353:    Lists the history */
                    354: #ifndef HAVE_LIBEDIT
                    355: PHP_FUNCTION(readline_list_history)
                    356: {
                    357:        HIST_ENTRY **history;
                    358: 
                    359:        if (zend_parse_parameters_none() == FAILURE) {
                    360:                return;
                    361:        }
                    362:        
                    363:        history = history_list();
                    364:        
                    365:        array_init(return_value);
                    366: 
                    367:        if (history) {
                    368:                int i;
                    369:                for (i = 0; history[i]; i++) {
                    370:                        add_next_index_string(return_value,history[i]->line,1);
                    371:                }
                    372:        }
                    373: }
                    374: #endif
                    375: /* }}} */
                    376: /* {{{ proto bool readline_read_history([string filename]) 
                    377:    Reads the history */
                    378: PHP_FUNCTION(readline_read_history)
                    379: {
                    380:        char *arg = NULL;
                    381:        int arg_len;
                    382: 
1.1.1.2 ! misho     383:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|p", &arg, &arg_len) == FAILURE) {
1.1       misho     384:                return;
                    385:        }
                    386: 
1.1.1.2 ! misho     387:        if (php_check_open_basedir(arg TSRMLS_CC)) {
        !           388:                RETURN_FALSE;
        !           389:        }
        !           390: 
1.1       misho     391:        /* XXX from & to NYI */
                    392:        if (read_history(arg)) {
                    393:                RETURN_FALSE;
                    394:        } else {
                    395:                RETURN_TRUE;
                    396:        }
                    397: }
                    398: 
                    399: /* }}} */
                    400: /* {{{ proto bool readline_write_history([string filename]) 
                    401:    Writes the history */
                    402: PHP_FUNCTION(readline_write_history)
                    403: {
                    404:        char *arg = NULL;
                    405:        int arg_len;
                    406: 
1.1.1.2 ! misho     407:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|p", &arg, &arg_len) == FAILURE) {
1.1       misho     408:                return;
                    409:        }
                    410: 
1.1.1.2 ! misho     411:        if (php_check_open_basedir(arg TSRMLS_CC)) {
        !           412:                RETURN_FALSE;
        !           413:        }
        !           414: 
1.1       misho     415:        if (write_history(arg)) {
                    416:                RETURN_FALSE;
                    417:        } else {
                    418:                RETURN_TRUE;
                    419:        }
                    420: }
                    421: 
                    422: /* }}} */
                    423: /* {{{ proto bool readline_completion_function(string funcname) 
                    424:    Readline completion function? */
                    425: 
                    426: static char *_readline_command_generator(const char *text, int state)
                    427: {
                    428:        HashTable  *myht = Z_ARRVAL(_readline_array);
                    429:        zval **entry;
                    430:        
                    431:        if (!state) {
                    432:                zend_hash_internal_pointer_reset(myht);
                    433:        }
                    434:        
                    435:        while (zend_hash_get_current_data(myht, (void **)&entry) == SUCCESS) {
                    436:                zend_hash_move_forward(myht);
                    437: 
                    438:                convert_to_string_ex(entry);
                    439:                if (strncmp (Z_STRVAL_PP(entry), text, strlen(text)) == 0) {
                    440:                        return (strdup(Z_STRVAL_PP(entry)));
                    441:                }
                    442:        }
                    443: 
                    444:        return NULL;
                    445: }
                    446: 
                    447: static zval *_readline_string_zval(const char *str)
                    448: {
                    449:        zval *ret;
                    450:        int len;
                    451:        
                    452:        MAKE_STD_ZVAL(ret);
                    453:        
                    454:        if (str) {
                    455:                len = strlen(str);
                    456:                ZVAL_STRINGL(ret, (char*)str, len, 1);
                    457:        } else {
                    458:                ZVAL_NULL(ret);
                    459:        }
                    460: 
                    461:        return ret;
                    462: }
                    463: 
                    464: static zval *_readline_long_zval(long l)
                    465: {
                    466:        zval *ret;
                    467:        MAKE_STD_ZVAL(ret);
                    468: 
                    469:        Z_TYPE_P(ret) = IS_LONG;
                    470:        Z_LVAL_P(ret) = l;
                    471:        return ret;
                    472: }
                    473: 
                    474: static char **_readline_completion_cb(const char *text, int start, int end)
                    475: { 
                    476:        zval *params[3];
                    477:        int i;
                    478:        char **matches = NULL;
                    479:        TSRMLS_FETCH();
                    480: 
                    481:        params[0]=_readline_string_zval(text);
                    482:        params[1]=_readline_long_zval(start);
                    483:        params[2]=_readline_long_zval(end);
                    484: 
                    485:        if (call_user_function(CG(function_table), NULL, _readline_completion, &_readline_array, 3, params TSRMLS_CC) == SUCCESS) {
                    486:                if (Z_TYPE(_readline_array) == IS_ARRAY) {
                    487:                        if (zend_hash_num_elements(Z_ARRVAL(_readline_array))) {
                    488:                                matches = rl_completion_matches(text,_readline_command_generator);
                    489:                        } else {
                    490:                                matches = malloc(sizeof(char *) * 2);
                    491:                                if (!matches) {
                    492:                                        return NULL;
                    493:                                }
                    494:                                matches[0] = strdup("");
                    495:                                matches[1] = '\0';
                    496:                        }
                    497:                }
                    498:        }
                    499:        
                    500:        for (i = 0; i < 3; i++) {
                    501:                zval_ptr_dtor(&params[i]);
                    502:        }
                    503:        zval_dtor(&_readline_array);
                    504:        
                    505:        return matches; 
                    506: }
                    507: 
                    508: PHP_FUNCTION(readline_completion_function)
                    509: {
                    510:        zval *arg = NULL;
                    511:        char *name = NULL;
                    512: 
                    513:        if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg)) {
                    514:                RETURN_FALSE;
                    515:        }
                    516: 
                    517:        if (!zend_is_callable(arg, 0, &name TSRMLS_CC)) {
                    518:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s is not callable", name);
                    519:                efree(name);
                    520:                RETURN_FALSE;
                    521:        }
                    522:        efree(name);
                    523: 
                    524:        if (_readline_completion) {
                    525:                zval_dtor(_readline_completion);
                    526:                FREE_ZVAL(_readline_completion);
                    527:        }
                    528: 
                    529:        MAKE_STD_ZVAL(_readline_completion);
                    530:        *_readline_completion = *arg;
                    531:        zval_copy_ctor(_readline_completion);
                    532: 
                    533:        rl_attempted_completion_function = _readline_completion_cb;
                    534:        if (rl_attempted_completion_function == NULL) {
                    535:                efree(name);
                    536:                RETURN_FALSE;
                    537:        }
                    538:        RETURN_TRUE;
                    539: }
                    540: 
                    541: /* }}} */
                    542: 
                    543: #if HAVE_RL_CALLBACK_READ_CHAR
                    544: 
                    545: static void php_rl_callback_handler(char *the_line)
                    546: {
                    547:        zval *params[1];
                    548:        zval dummy;
                    549:        TSRMLS_FETCH();
                    550: 
                    551:        ZVAL_NULL(&dummy);
                    552: 
                    553:        params[0] = _readline_string_zval(the_line);
                    554: 
                    555:        call_user_function(CG(function_table), NULL, _prepped_callback, &dummy, 1, params TSRMLS_CC);
                    556: 
                    557:        zval_ptr_dtor(&params[0]);
                    558:        zval_dtor(&dummy);
                    559: }
                    560: 
                    561: /* {{{ proto void readline_callback_handler_install(string prompt, mixed callback)
                    562:    Initializes the readline callback interface and terminal, prints the prompt and returns immediately */
                    563: PHP_FUNCTION(readline_callback_handler_install)
                    564: {
                    565:        zval *callback;
                    566:        char *name = NULL;
                    567:        char *prompt;
                    568:        int prompt_len;
                    569: 
                    570:        if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &prompt, &prompt_len, &callback)) {
                    571:                return;
                    572:        }
                    573: 
                    574:        if (!zend_is_callable(callback, 0, &name TSRMLS_CC)) {
                    575:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s is not callable", name);
                    576:                efree(name);
                    577:                RETURN_FALSE;
                    578:        }
                    579:        efree(name);
                    580: 
                    581:        if (_prepped_callback) {
                    582:                rl_callback_handler_remove();
                    583:                zval_dtor(_prepped_callback);
                    584:                FREE_ZVAL(_prepped_callback);
                    585:        }
                    586: 
1.1.1.2 ! misho     587:        ALLOC_ZVAL(_prepped_callback);
        !           588:        MAKE_COPY_ZVAL(&callback, _prepped_callback);
1.1       misho     589: 
                    590:        rl_callback_handler_install(prompt, php_rl_callback_handler);
                    591: 
                    592:        RETURN_TRUE;
                    593: }
                    594: /* }}} */
                    595: 
                    596: /* {{{ proto void readline_callback_read_char()
                    597:    Informs the readline callback interface that a character is ready for input */
                    598: PHP_FUNCTION(readline_callback_read_char)
                    599: {
                    600:        if (_prepped_callback) {
                    601:                rl_callback_read_char();
                    602:        }
                    603: }
                    604: /* }}} */
                    605: 
                    606: /* {{{ proto bool readline_callback_handler_remove()
                    607:    Removes a previously installed callback handler and restores terminal settings */
                    608: PHP_FUNCTION(readline_callback_handler_remove)
                    609: {
                    610:        if (_prepped_callback) {
                    611:                rl_callback_handler_remove();
                    612:                zval_dtor(_prepped_callback);
                    613:                FREE_ZVAL(_prepped_callback);
                    614:                _prepped_callback = 0;
                    615:                RETURN_TRUE;
                    616:        }
                    617:        RETURN_FALSE;
                    618: }
                    619: /* }}} */
                    620: 
                    621: /* {{{ proto void readline_redisplay(void)
                    622:    Ask readline to redraw the display */
                    623: PHP_FUNCTION(readline_redisplay)
                    624: {
                    625:        rl_redisplay();
                    626: }
                    627: /* }}} */
                    628: 
1.1.1.2 ! misho     629: #endif
        !           630: 
        !           631: #if HAVE_RL_ON_NEW_LINE
1.1       misho     632: /* {{{ proto void readline_on_new_line(void)
                    633:    Inform readline that the cursor has moved to a new line */
                    634: PHP_FUNCTION(readline_on_new_line)
                    635: {
                    636:        rl_on_new_line();
                    637: }
                    638: /* }}} */
                    639: 
                    640: #endif
                    641: 
                    642: 
                    643: #endif /* HAVE_LIBREADLINE */
                    644: 
                    645: /*
                    646:  * Local variables:
                    647:  * tab-width: 4
                    648:  * c-basic-offset: 4
                    649:  * End:
                    650:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>