ab41
  +   lY>eJ}@?q1hρ_I|+ ?     /*
   +----------------------------------------------------------------------+
   | PHP Version 5                                                        |
   +----------------------------------------------------------------------+
   | Copyright (c) 1997-2016 The PHP Group                                |
   +----------------------------------------------------------------------+
   | This source file is subject to version 3.01 of the PHP license,      |
   | that is bundled with this package in the file LICENSE, and is        |
   | available through the world-wide-web at the following url:           |
   | http://www.php.net/license/3_01.txt                                  |
   | If you did not receive a copy of the PHP license and are unable to   |
   | obtain it through the world-wide-web, please send a note to          |
   | license@php.net so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
   | Author: Marcus Boerger <helly@php.net>                               |
   |         Johannes Schlueter <johannes@php.net>                        |
   +----------------------------------------------------------------------+
*/

/* $Id$ */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"

#ifndef HAVE_RL_COMPLETION_MATCHES
#define rl_completion_matches completion_matches
#endif

#include "php_globals.h"
#include "php_variables.h"
#include "zend_hash.h"
#include "zend_modules.h"

#include "SAPI.h"

#if HAVE_SETLOCALE
#include <locale.h>
#endif
#include "zend.h"
#include "zend_extensions.h"
#include "php_ini.h"
#include "php_globals.h"
#include "php_main.h"
#include "fopen_wrappers.h"
#include "ext/standard/php_standard.h"
#include "ext/standard/php_smart_str.h"

#ifdef __riscos__
#include <unixlib/local.h>
#endif

#if HAVE_LIBEDIT
#include <editline/readline.h>
#else
#include <readline/readline.h>
#include <readline/history.h>
#endif

#include "zend_compile.h"
#include "zend_execute.h"
#include "zend_highlight.h"
#include "zend_indent.h"
#include "zend_exceptions.h"

#include "sapi/cli/cli.h"
#include "readline_cli.h"

#ifdef COMPILE_DL_READLINE
#include <dlfcn.h>
#endif

#ifndef RTLD_DEFAULT
#define RTLD_DEFAULT NULL
#endif

#define DEFAULT_PROMPT "\\b \\> "

ZEND_DECLARE_MODULE_GLOBALS(cli_readline);

static char php_last_char = '\0';
static FILE *pager_pipe = NULL;

static size_t readline_shell_write(const char *str, uint str_length TSRMLS_DC) /* {{{ */
{
	if (CLIR_G(prompt_str)) {
		smart_str_appendl(CLIR_G(prompt_str), str, str_length);
		return str_length;
	}

	if (CLIR_G(pager) && *CLIR_G(pager) && !pager_pipe) {
		pager_pipe = VCWD_POPEN(CLIR_G(pager), "w");
	}
	if (pager_pipe) {
		return fwrite(str, 1, MIN(str_length, 16384), pager_pipe);
	}

	return -1;
}
/* }}} */

static int readline_shell_ub_write(const char *str, uint str_length TSRMLS_DC) /* {{{ */
{
	/* We just store the last char here and then pass back to the
	   caller (sapi_cli_single_write in sapi/cli) which will actually
	   write due to -1 return code */
	php_last_char = str[str_length-1];
	return -1;
}
/* }}} */

static void cli_readline_init_globals(zend_cli_readline_globals *rg TSRMLS_DC)
{
	rg->pager = NULL;
	rg->prompt = NULL;
	rg->prompt_str = NULL;
}

PHP_INI_BEGIN()
	STD_PHP_INI_ENTRY("cli.pager", "", PHP_INI_ALL, OnUpdateString, pager, zend_cli_readline_globals, cli_readline_globals)
	STD_PHP_INI_ENTRY("cli.prompt", DEFAULT_PROMPT, PHP_INI_ALL, OnUpdateString, prompt, zend_cli_readline_globals, cli_readline_globals)
PHP_INI_END()



typedef enum {
	body,
	sstring,
	dstring,
	sstring_esc,
	dstring_esc,
	comment_line,
	comment_block,
	heredoc_start,
	heredoc,
	outside,
} php_code_type;

static char *cli_get_prompt(char *block, char prompt TSRMLS_DC) /* {{{ */
{
	smart_str retval = {0};
	char *prompt_spec = CLIR_G(prompt) ? CLIR_G(prompt) : DEFAULT_PROMPT;

	do {
		if (*prompt_spec == '\\') {
			switch (prompt_spec[1]) {
			case '\\':
				smart_str_appendc(&retval, '\\');
				prompt_spe