xref: /PHP-5.4/ext/readline/readline.c (revision c0d060f5)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 5                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2014 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 
19 /* $Id$ */
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"
29 #include "readline_cli.h"
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);
70 PHP_MSHUTDOWN_FUNCTION(readline);
71 PHP_RSHUTDOWN_FUNCTION(readline);
72 PHP_MINFO_FUNCTION(readline);
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)
147 #endif
148 #if HAVE_RL_ON_NEW_LINE
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),
159 	PHP_MSHUTDOWN(readline),
160 	NULL,
161 	PHP_RSHUTDOWN(readline),
162 	PHP_MINFO(readline),
163 	PHP_VERSION,
164 	STANDARD_MODULE_PROPERTIES
165 };
166 
167 #ifdef COMPILE_DL_READLINE
168 ZEND_GET_MODULE(readline)
169 #endif
170 
PHP_MINIT_FUNCTION(readline)171 PHP_MINIT_FUNCTION(readline)
172 {
173     	using_history();
174     	return PHP_MINIT(cli_readline)(INIT_FUNC_ARGS_PASSTHRU);
175 }
176 
PHP_MSHUTDOWN_FUNCTION(readline)177 PHP_MSHUTDOWN_FUNCTION(readline)
178 {
179 	return PHP_MSHUTDOWN(cli_readline)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
180 }
181 
PHP_RSHUTDOWN_FUNCTION(readline)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 
PHP_MINFO_FUNCTION(readline)199 PHP_MINFO_FUNCTION(readline)
200 {
201 	PHP_MINFO(cli_readline)(ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU);
202 }
203 
204 /* }}} */
205 
206 /* {{{ proto string readline([string prompt])
207    Reads a line */
PHP_FUNCTION(readline)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. */
PHP_FUNCTION(readline_info)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 		add_assoc_long(return_value,"attempted_completion_over",rl_attempted_completion_over);
263 	} else {
264 		if (!strcasecmp(what,"line_buffer")) {
265 			oldstr = rl_line_buffer;
266 			if (value) {
267 				/* XXX if (rl_line_buffer) free(rl_line_buffer); */
268 				convert_to_string_ex(value);
269 				rl_line_buffer = strdup(Z_STRVAL_PP(value));
270 			}
271 			RETVAL_STRING(SAFE_STRING(oldstr),1);
272 		} else if (!strcasecmp(what, "point")) {
273 			RETVAL_LONG(rl_point);
274 		} else if (!strcasecmp(what, "end")) {
275 			RETVAL_LONG(rl_end);
276 #ifdef HAVE_LIBREADLINE
277 		} else if (!strcasecmp(what, "mark")) {
278 			RETVAL_LONG(rl_mark);
279 		} else if (!strcasecmp(what, "done")) {
280 			oldval = rl_done;
281 			if (value) {
282 				convert_to_long_ex(value);
283 				rl_done = Z_LVAL_PP(value);
284 			}
285 			RETVAL_LONG(oldval);
286 		} else if (!strcasecmp(what, "pending_input")) {
287 			oldval = rl_pending_input;
288 			if (value) {
289 				convert_to_string_ex(value);
290 				rl_pending_input = Z_STRVAL_PP(value)[0];
291 			}
292 			RETVAL_LONG(oldval);
293 		} else if (!strcasecmp(what, "prompt")) {
294 			RETVAL_STRING(SAFE_STRING(rl_prompt),1);
295 		} else if (!strcasecmp(what, "terminal_name")) {
296 			RETVAL_STRING((char *)SAFE_STRING(rl_terminal_name),1);
297 #endif
298 #if HAVE_ERASE_EMPTY_LINE
299 		} else if (!strcasecmp(what, "erase_empty_line")) {
300 			oldval = rl_erase_empty_line;
301 			if (value) {
302 				convert_to_long_ex(value);
303 				rl_erase_empty_line = Z_LVAL_PP(value);
304 			}
305 			RETVAL_LONG(oldval);
306 #endif
307 		} else if (!strcasecmp(what,"library_version")) {
308 			RETVAL_STRING((char *)SAFE_STRING(rl_library_version),1);
309 		} else if (!strcasecmp(what, "readline_name")) {
310 			oldstr = (char*)rl_readline_name;
311 			if (value) {
312 				/* XXX if (rl_readline_name) free(rl_readline_name); */
313 				convert_to_string_ex(value);
314 				rl_readline_name = strdup(Z_STRVAL_PP(value));;
315 			}
316 			RETVAL_STRING(SAFE_STRING(oldstr),1);
317 		} else if (!strcasecmp(what, "attempted_completion_over")) {
318 			oldval = rl_attempted_completion_over;
319 			if (value) {
320 				convert_to_long_ex(value);
321 				rl_attempted_completion_over = Z_LVAL_PP(value);
322 			}
323 			RETVAL_LONG(oldval);
324 		}
325 	}
326 }
327 
328 /* }}} */
329 /* {{{ proto bool readline_add_history(string prompt)
330    Adds a line to the history */
PHP_FUNCTION(readline_add_history)331 PHP_FUNCTION(readline_add_history)
332 {
333 	char *arg;
334 	int arg_len;
335 
336 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
337 		return;
338 	}
339 
340 	add_history(arg);
341 
342 	RETURN_TRUE;
343 }
344 
345 /* }}} */
346 /* {{{ proto bool readline_clear_history(void)
347    Clears the history */
PHP_FUNCTION(readline_clear_history)348 PHP_FUNCTION(readline_clear_history)
349 {
350 	if (zend_parse_parameters_none() == FAILURE) {
351 		return;
352 	}
353 
354 	clear_history();
355 
356 	RETURN_TRUE;
357 }
358 
359 /* }}} */
360 /* {{{ proto array readline_list_history(void)
361    Lists the history */
362 #ifndef HAVE_LIBEDIT
PHP_FUNCTION(readline_list_history)363 PHP_FUNCTION(readline_list_history)
364 {
365 	HIST_ENTRY **history;
366 
367 	if (zend_parse_parameters_none() == FAILURE) {
368 		return;
369 	}
370 
371 	history = history_list();
372 
373 	array_init(return_value);
374 
375 	if (history) {
376 		int i;
377 		for (i = 0; history[i]; i++) {
378 			add_next_index_string(return_value,history[i]->line,1);
379 		}
380 	}
381 }
382 #endif
383 /* }}} */
384 /* {{{ proto bool readline_read_history([string filename])
385    Reads the history */
PHP_FUNCTION(readline_read_history)386 PHP_FUNCTION(readline_read_history)
387 {
388 	char *arg = NULL;
389 	int arg_len;
390 
391 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|p", &arg, &arg_len) == FAILURE) {
392 		return;
393 	}
394 
395 	if (php_check_open_basedir(arg TSRMLS_CC)) {
396 		RETURN_FALSE;
397 	}
398 
399 	/* XXX from & to NYI */
400 	if (read_history(arg)) {
401 		RETURN_FALSE;
402 	} else {
403 		RETURN_TRUE;
404 	}
405 }
406 
407 /* }}} */
408 /* {{{ proto bool readline_write_history([string filename])
409    Writes the history */
PHP_FUNCTION(readline_write_history)410 PHP_FUNCTION(readline_write_history)
411 {
412 	char *arg = NULL;
413 	int arg_len;
414 
415 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|p", &arg, &arg_len) == FAILURE) {
416 		return;
417 	}
418 
419 	if (php_check_open_basedir(arg TSRMLS_CC)) {
420 		RETURN_FALSE;
421 	}
422 
423 	if (write_history(arg)) {
424 		RETURN_FALSE;
425 	} else {
426 		RETURN_TRUE;
427 	}
428 }
429 
430 /* }}} */
431 /* {{{ proto bool readline_completion_function(string funcname)
432    Readline completion function? */
433 
_readline_command_generator(const char * text,int state)434 static char *_readline_command_generator(const char *text, int state)
435 {
436 	HashTable  *myht = Z_ARRVAL(_readline_array);
437 	zval **entry;
438 
439 	if (!state) {
440 		zend_hash_internal_pointer_reset(myht);
441 	}
442 
443 	while (zend_hash_get_current_data(myht, (void **)&entry) == SUCCESS) {
444 		zend_hash_move_forward(myht);
445 
446 		convert_to_string_ex(entry);
447 		if (strncmp (Z_STRVAL_PP(entry), text, strlen(text)) == 0) {
448 			return (strdup(Z_STRVAL_PP(entry)));
449 		}
450 	}
451 
452 	return NULL;
453 }
454 
_readline_string_zval(const char * str)455 static zval *_readline_string_zval(const char *str)
456 {
457 	zval *ret;
458 	int len;
459 
460 	MAKE_STD_ZVAL(ret);
461 
462 	if (str) {
463 		len = strlen(str);
464 		ZVAL_STRINGL(ret, (char*)str, len, 1);
465 	} else {
466 		ZVAL_NULL(ret);
467 	}
468 
469 	return ret;
470 }
471 
_readline_long_zval(long l)472 static zval *_readline_long_zval(long l)
473 {
474 	zval *ret;
475 	MAKE_STD_ZVAL(ret);
476 
477 	Z_TYPE_P(ret) = IS_LONG;
478 	Z_LVAL_P(ret) = l;
479 	return ret;
480 }
481 
_readline_completion_cb(const char * text,int start,int end)482 static char **_readline_completion_cb(const char *text, int start, int end)
483 {
484 	zval *params[3];
485 	int i;
486 	char **matches = NULL;
487 	TSRMLS_FETCH();
488 
489 	params[0]=_readline_string_zval(text);
490 	params[1]=_readline_long_zval(start);
491 	params[2]=_readline_long_zval(end);
492 
493 	if (call_user_function(CG(function_table), NULL, _readline_completion, &_readline_array, 3, params TSRMLS_CC) == SUCCESS) {
494 		if (Z_TYPE(_readline_array) == IS_ARRAY) {
495 			if (zend_hash_num_elements(Z_ARRVAL(_readline_array))) {
496 				matches = rl_completion_matches(text,_readline_command_generator);
497 			} else {
498 				matches = malloc(sizeof(char *) * 2);
499 				if (!matches) {
500 					return NULL;
501 				}
502 				matches[0] = strdup("");
503 				matches[1] = '\0';
504 			}
505 		}
506 	}
507 
508 	for (i = 0; i < 3; i++) {
509 		zval_ptr_dtor(&params[i]);
510 	}
511 	zval_dtor(&_readline_array);
512 
513 	return matches;
514 }
515 
PHP_FUNCTION(readline_completion_function)516 PHP_FUNCTION(readline_completion_function)
517 {
518 	zval *arg = NULL;
519 	char *name = NULL;
520 
521 	if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg)) {
522 		RETURN_FALSE;
523 	}
524 
525 	if (!zend_is_callable(arg, 0, &name TSRMLS_CC)) {
526 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s is not callable", name);
527 		efree(name);
528 		RETURN_FALSE;
529 	}
530 	efree(name);
531 
532 	if (_readline_completion) {
533 		zval_dtor(_readline_completion);
534 		FREE_ZVAL(_readline_completion);
535 	}
536 
537 	MAKE_STD_ZVAL(_readline_completion);
538 	*_readline_completion = *arg;
539 	zval_copy_ctor(_readline_completion);
540 
541 	rl_attempted_completion_function = _readline_completion_cb;
542 	if (rl_attempted_completion_function == NULL) {
543 		efree(name);
544 		RETURN_FALSE;
545 	}
546 	RETURN_TRUE;
547 }
548 
549 /* }}} */
550 
551 #if HAVE_RL_CALLBACK_READ_CHAR
552 
php_rl_callback_handler(char * the_line)553 static void php_rl_callback_handler(char *the_line)
554 {
555 	zval *params[1];
556 	zval dummy;
557 	TSRMLS_FETCH();
558 
559 	ZVAL_NULL(&dummy);
560 
561 	params[0] = _readline_string_zval(the_line);
562 
563 	call_user_function(CG(function_table), NULL, _prepped_callback, &dummy, 1, params TSRMLS_CC);
564 
565 	zval_ptr_dtor(&params[0]);
566 	zval_dtor(&dummy);
567 }
568 
569 /* {{{ proto void readline_callback_handler_install(string prompt, mixed callback)
570    Initializes the readline callback interface and terminal, prints the prompt and returns immediately */
PHP_FUNCTION(readline_callback_handler_install)571 PHP_FUNCTION(readline_callback_handler_install)
572 {
573 	zval *callback;
574 	char *name = NULL;
575 	char *prompt;
576 	int prompt_len;
577 
578 	if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &prompt, &prompt_len, &callback)) {
579 		return;
580 	}
581 
582 	if (!zend_is_callable(callback, 0, &name TSRMLS_CC)) {
583 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s is not callable", name);
584 		efree(name);
585 		RETURN_FALSE;
586 	}
587 	efree(name);
588 
589 	if (_prepped_callback) {
590 		rl_callback_handler_remove();
591 		zval_dtor(_prepped_callback);
592 		FREE_ZVAL(_prepped_callback);
593 	}
594 
595 	ALLOC_ZVAL(_prepped_callback);
596 	MAKE_COPY_ZVAL(&callback, _prepped_callback);
597 
598 	rl_callback_handler_install(prompt, php_rl_callback_handler);
599 
600 	RETURN_TRUE;
601 }
602 /* }}} */
603 
604 /* {{{ proto void readline_callback_read_char()
605    Informs the readline callback interface that a character is ready for input */
PHP_FUNCTION(readline_callback_read_char)606 PHP_FUNCTION(readline_callback_read_char)
607 {
608 	if (_prepped_callback) {
609 		rl_callback_read_char();
610 	}
611 }
612 /* }}} */
613 
614 /* {{{ proto bool readline_callback_handler_remove()
615    Removes a previously installed callback handler and restores terminal settings */
PHP_FUNCTION(readline_callback_handler_remove)616 PHP_FUNCTION(readline_callback_handler_remove)
617 {
618 	if (_prepped_callback) {
619 		rl_callback_handler_remove();
620 		zval_dtor(_prepped_callback);
621 		FREE_ZVAL(_prepped_callback);
622 		_prepped_callback = 0;
623 		RETURN_TRUE;
624 	}
625 	RETURN_FALSE;
626 }
627 /* }}} */
628 
629 /* {{{ proto void readline_redisplay(void)
630    Ask readline to redraw the display */
PHP_FUNCTION(readline_redisplay)631 PHP_FUNCTION(readline_redisplay)
632 {
633 	rl_redisplay();
634 }
635 /* }}} */
636 
637 #endif
638 
639 #if HAVE_RL_ON_NEW_LINE
640 /* {{{ proto void readline_on_new_line(void)
641    Inform readline that the cursor has moved to a new line */
PHP_FUNCTION(readline_on_new_line)642 PHP_FUNCTION(readline_on_new_line)
643 {
644 	rl_on_new_line();
645 }
646 /* }}} */
647 
648 #endif
649 
650 
651 #endif /* HAVE_LIBREADLINE */
652 
653 /*
654  * Local variables:
655  * tab-width: 4
656  * c-basic-offset: 4
657  * End:
658  */
659