pajoye                                   Tue, 22 Feb 2011 12:59:50 +0000

Revision: http://svn.php.net/viewvc?view=revision&revision=308565

Log:
- missing files

Changed paths:
    A   php/php-src/trunk/sapi/cli/php_cli_readline.c
    A   php/php-src/trunk/sapi/cli/php_cli_readline.h

Added: php/php-src/trunk/sapi/cli/php_cli_readline.c
===================================================================
--- php/php-src/trunk/sapi/cli/php_cli_readline.c	                        (rev 0)
+++ php/php-src/trunk/sapi/cli/php_cli_readline.c	2011-02-22 12:59:50 UTC (rev 308565)
@@ -0,0 +1,448 @@
+/*
+   +----------------------------------------------------------------------+
+   | PHP Version 5                                                        |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 1997-2011 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          |
+   | lice...@php.net so we can mail you a copy immediately.               |
+   +----------------------------------------------------------------------+
+   | Author: Marcus Boerger <he...@php.net>                               |
+   |         Johannes Schlueter <johan...@php.net>                        |
+   +----------------------------------------------------------------------+
+*/
+
+/* $Id: php_cli_readline.c 306939 2011-01-01 02:19:59Z felipe $ */
+
+#include "php.h"
+
+#if (HAVE_LIBREADLINE || HAVE_LIBEDIT) && !defined(COMPILE_DL_READLINE)
+
+#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"
+
+#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"
+
+typedef enum {
+	body,
+	sstring,
+	dstring,
+	sstring_esc,
+	dstring_esc,
+	comment_line,
+	comment_block,
+	heredoc_start,
+	heredoc,
+	outside,
+} php_code_type;
+
+int cli_is_valid_code(char *code, int len, char **prompt TSRMLS_DC) /* {{{ */
+{
+	int valid_end = 1, last_valid_end;
+	int brackets_count = 0;
+	int brace_count = 0;
+	int i;
+	php_code_type code_type = body;
+	char *heredoc_tag;
+	int heredoc_len;
+
+	for (i = 0; i < len; ++i) {
+		switch(code_type) {
+			default:
+				switch(code[i]) {
+					case '{':
+						brackets_count++;
+						valid_end = 0;
+						break;
+					case '}':
+						if (brackets_count > 0) {
+							brackets_count--;
+						}
+						valid_end = brackets_count ? 0 : 1;
+						break;
+					case '(':
+						brace_count++;
+						valid_end = 0;
+						break;
+					case ')':
+						if (brace_count > 0) {
+							brace_count--;
+						}
+						valid_end = 0;
+						break;
+					case ';':
+						valid_end = brace_count == 0 && brackets_count == 0;
+						break;
+					case ' ':
+					case '\r':
+					case '\n':
+					case '\t':
+						break;
+					case '\'':
+						code_type = sstring;
+						break;
+					case '"':
+						code_type = dstring;
+						break;
+					case '#':
+						code_type = comment_line;
+						break;
+					case '/':
+						if (code[i+1] == '/') {
+							i++;
+							code_type = comment_line;
+							break;
+						}
+						if (code[i+1] == '*') {
+							last_valid_end = valid_end;
+							valid_end = 0;
+							code_type = comment_block;
+							i++;
+							break;
+						}
+						valid_end = 0;
+						break;
+					case '%':
+						if (!CG(asp_tags)) {
+							valid_end = 0;
+							break;
+						}
+						/* no break */
+					case '?':
+						if (code[i+1] == '>') {
+							i++;
+							code_type = outside;
+							break;
+						}
+						valid_end = 0;
+						break;
+					case '<':
+						valid_end = 0;
+						if (i + 2 < len && code[i+1] == '<' && code[i+2] == '<') {
+							i += 2;
+							code_type = heredoc_start;
+							heredoc_len = 0;
+						}
+						break;
+					default:
+						valid_end = 0;
+						break;
+				}
+				break;
+			case sstring:
+				if (code[i] == '\\') {
+					code_type = sstring_esc;
+				} else {
+					if (code[i] == '\'') {
+						code_type = body;
+					}
+				}
+				break;
+			case sstring_esc:
+				code_type = sstring;
+				break;
+			case dstring:
+				if (code[i] == '\\') {
+					code_type = dstring_esc;
+				} else {
+					if (code[i] == '"') {
+						code_type = body;
+					}
+				}
+				break;
+			case dstring_esc:
+				code_type = dstring;
+				break;
+			case comment_line:
+				if (code[i] == '\n') {
+					code_type = body;
+				}
+				break;
+			case comment_block:
+				if (code[i-1] == '*' && code[i] == '/') {
+					code_type = body;
+					valid_end = last_valid_end;
+				}
+				break;
+			case heredoc_start:
+				switch(code[i]) {
+					case ' ':
+					case '\t':
+						break;
+					case '\r':
+					case '\n':
+						code_type = heredoc;
+						break;
+					default:
+						if (!heredoc_len) {
+							heredoc_tag = code+i;
+						}
+						heredoc_len++;
+						break;
+				}
+				break;
+			case heredoc:
+				if (code[i - (heredoc_len + 1)] == '\n' && !strncmp(code + i - heredoc_len, heredoc_tag, heredoc_len) && code[i] == '\n') {
+					code_type = body;
+				} else if (code[i - (heredoc_len + 2)] == '\n' && !strncmp(code + i - heredoc_len - 1, heredoc_tag, heredoc_len) && code[i-1] == ';' && code[i] == '\n') {
+					code_type = body;
+					valid_end = 1;
+				}
+				break;
+			case outside:
+				if ((CG(short_tags) && !strncmp(code+i-1, "<?", 2))
+				||  (CG(asp_tags) && !strncmp(code+i-1, "<%", 2))
+				||  (i > 3 && !strncmp(code+i-4, "<?php", 5))
+				) {
+					code_type = body;
+				}
+				break;
+		}
+	}
+
+	switch (code_type) {
+		default:
+			if (brace_count) {
+				*prompt = "php ( ";
+			} else if (brackets_count) {
+				*prompt = "php { ";
+			} else {
+				*prompt = "php > ";
+			}
+			break;
+		case sstring:
+		case sstring_esc:
+			*prompt = "php ' ";
+			break;
+		case dstring:
+		case dstring_esc:
+			*prompt = "php \" ";
+			break;
+		case comment_block:
+			*prompt = "/*  > ";
+			break;
+		case heredoc:
+			*prompt = "<<< > ";
+			break;
+		case outside:
+			*prompt = "    > ";
+			break;
+	}
+
+	if (!valid_end || brackets_count) {
+		return 0;
+	} else {
+		return 1;
+	}
+}
+/* }}} */
+
+static char *cli_completion_generator_ht(const char *text, int textlen, int *state, HashTable *ht, void **pData TSRMLS_DC) /* {{{ */
+{
+	char *name;
+	ulong number;
+
+	if (!(*state % 2)) {
+		zend_hash_internal_pointer_reset(ht);
+		(*state)++;
+	}
+	while(zend_hash_has_more_elements(ht) == SUCCESS) {
+		zend_hash_get_current_key(ht, &name, &number, 0);
+		if (!textlen || !strncmp(name, text, textlen)) {
+			if (pData) {
+				zend_hash_get_current_data(ht, pData);
+			}
+			zend_hash_move_forward(ht);
+			return name;
+		}
+		if (zend_hash_move_forward(ht) == FAILURE) {
+			break;
+		}
+	}
+	(*state)++;
+	return NULL;
+} /* }}} */
+
+static char *cli_completion_generator_var(const char *text, int textlen, int *state TSRMLS_DC) /* {{{ */
+{
+	char *retval, *tmp;
+
+	tmp = retval = cli_completion_generator_ht(text + 1, textlen - 1, state, EG(active_symbol_table), NULL TSRMLS_CC);
+	if (retval) {
+		retval = malloc(strlen(tmp) + 2);
+		retval[0] = '$';
+		strcpy(&retval[1], tmp);
+		rl_completion_append_character = '\0';
+	}
+	return retval;
+} /* }}} */
+
+static char *cli_completion_generator_func(const char *text, int textlen, int *state, HashTable *ht TSRMLS_DC) /* {{{ */
+{
+	zend_function *func;
+	char *retval = cli_completion_generator_ht(text, textlen, state, ht, (void**)&func TSRMLS_CC);
+	if (retval) {
+		rl_completion_append_character = '(';
+		retval = strdup(func->common.function_name);
+	}
+
+	return retval;
+} /* }}} */
+
+static char *cli_completion_generator_class(const char *text, int textlen, int *state TSRMLS_DC) /* {{{ */
+{
+	zend_class_entry **pce;
+	char *retval = cli_completion_generator_ht(text, textlen, state, EG(class_table), (void**)&pce TSRMLS_CC);
+	if (retval) {
+		rl_completion_append_character = '\0';
+		retval = strdup((*pce)->name);
+	}
+
+	return retval;
+} /* }}} */
+
+static char *cli_completion_generator_define(const char *text, int textlen, int *state, HashTable *ht TSRMLS_DC) /* {{{ */
+{
+	zend_class_entry **pce;
+	char *retval = cli_completion_generator_ht(text, textlen, state, ht, (void**)&pce TSRMLS_CC);
+	if (retval) {
+		rl_completion_append_character = '\0';
+		retval = strdup(retval);
+	}
+
+	return retval;
+} /* }}} */
+
+static int cli_completion_state;
+
+static char *cli_completion_generator(const char *text, int index) /* {{{ */
+{
+/*
+TODO:
+- constants
+- maybe array keys
+- language constructs and other things outside a hashtable (echo, try, function, class, ...)
+- object/class members
+
+- future: respect scope ("php > function foo() { $[tab]" should only expand to local variables...)
+*/
+	char *retval = NULL;
+	int textlen = strlen(text);
+	TSRMLS_FETCH();
+
+	if (!index) {
+		cli_completion_state = 0;
+	}
+	if (text[0] == '$') {
+		retval = cli_completion_generator_var(text, textlen, &cli_completion_state TSRMLS_CC);
+	} else {
+		char *lc_text, *class_name, *class_name_end;
+		int class_name_len;
+		zend_class_entry **pce = NULL;
+
+		class_name_end = strstr(text, "::");
+		if (class_name_end) {
+			class_name_len = class_name_end - text;
+			class_name = zend_str_tolower_dup(text, class_name_len);
+			class_name[class_name_len] = '\0'; /* not done automatically */
+			if (zend_lookup_class(class_name, class_name_len, &pce TSRMLS_CC)==FAILURE) {
+				efree(class_name);
+				return NULL;
+			}
+			lc_text = zend_str_tolower_dup(class_name_end + 2, textlen - 2 - class_name_len);
+			textlen -= (class_name_len + 2);
+		} else {
+			lc_text = zend_str_tolower_dup(text, textlen);
+		}
+
+		switch (cli_completion_state) {
+			case 0:
+			case 1:
+				retval = cli_completion_generator_func(lc_text, textlen, &cli_completion_state, pce ? &(*pce)->function_table : EG(function_table) TSRMLS_CC);
+				if (retval) {
+					break;
+				}
+			case 2:
+			case 3:
+				retval = cli_completion_generator_define(text, textlen, &cli_completion_state, pce ? &(*pce)->constants_table : EG(zend_constants) TSRMLS_CC);
+				if (retval || pce) {
+					break;
+				}
+			case 4:
+			case 5:
+				retval = cli_completion_generator_class(lc_text, textlen, &cli_completion_state TSRMLS_CC);
+				break;
+			default:
+				break;
+		}
+		efree(lc_text);
+		if (class_name_end) {
+			efree(class_name);
+		}
+		if (pce && retval) {
+			int len = class_name_len + 2 + strlen(retval) + 1;
+			char *tmp = malloc(len);
+
+			snprintf(tmp, len, "%s::%s", (*pce)->name, retval);
+			free(retval);
+			retval = tmp;
+		}
+	}
+
+	return retval;
+} /* }}} */
+
+char **cli_code_completion(const char *text, int start, int end) /* {{{ */
+{
+	return rl_completion_matches(text, cli_completion_generator);
+}
+/* }}} */
+
+#endif /* HAVE_LIBREADLINE || HAVE_LIBEDIT */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */

Added: php/php-src/trunk/sapi/cli/php_cli_readline.h
===================================================================
--- php/php-src/trunk/sapi/cli/php_cli_readline.h	                        (rev 0)
+++ php/php-src/trunk/sapi/cli/php_cli_readline.h	2011-02-22 12:59:50 UTC (rev 308565)
@@ -0,0 +1,25 @@
+/*
+   +----------------------------------------------------------------------+
+   | PHP Version 5                                                        |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 1997-2011 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          |
+   | lice...@php.net so we can mail you a copy immediately.               |
+   +----------------------------------------------------------------------+
+   | Author: Marcus Boerger <he...@php.net>                               |
+   +----------------------------------------------------------------------+
+*/
+
+/* $Id: php_cli_readline.h 306939 2011-01-01 02:19:59Z felipe $ */
+
+#include "php.h"
+
+int cli_is_valid_code(char *code, int len, char **prompt TSRMLS_DC);
+
+char **cli_code_completion(const char *text, int start, int end);
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to