php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
readline_cli.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Marcus Boerger <helly@php.net> |
14 | Johannes Schlueter <johannes@php.net> |
15 +----------------------------------------------------------------------+
16*/
17
18#ifdef HAVE_CONFIG_H
19#include <config.h>
20#endif
21
22#include "php.h"
23
24#ifndef HAVE_RL_COMPLETION_MATCHES
25#define rl_completion_matches completion_matches
26#endif
27
28#include "zend_hash.h"
29
30#include "SAPI.h"
31#include <locale.h>
32#include "zend.h"
33#include "php_ini.h"
34#include "ext/standard/info.h"
35#include "zend_smart_str.h"
36
37#ifdef __riscos__
38#include <unixlib/local.h>
39#endif
40
41#ifdef HAVE_LIBEDIT
42#include <editline/readline.h>
43#else
44#include <readline/readline.h>
45#include <readline/history.h>
46#endif
47
48#include "zend_compile.h"
49#include "zend_execute.h"
50#include "zend_highlight.h"
51#include "zend_exceptions.h"
52
53#include "sapi/cli/cli.h"
54#include "readline_cli.h"
55
56#if defined(COMPILE_DL_READLINE) && !defined(PHP_WIN32)
57#include <dlfcn.h>
58#endif
59
60#ifndef RTLD_DEFAULT
61#define RTLD_DEFAULT NULL
62#endif
63
64#define DEFAULT_PROMPT "\\b \\> "
65
67
68static char php_last_char = '\0';
69static FILE *pager_pipe = NULL;
70
71static size_t readline_shell_write(const char *str, size_t str_length) /* {{{ */
72{
73 if (CLIR_G(prompt_str)) {
74 smart_str_appendl(CLIR_G(prompt_str), str, str_length);
75 return str_length;
76 }
77
78 if (CLIR_G(pager) && *CLIR_G(pager) && !pager_pipe) {
79 pager_pipe = VCWD_POPEN(CLIR_G(pager), "w");
80 }
81 if (pager_pipe) {
82 return fwrite(str, 1, MIN(str_length, 16384), pager_pipe);
83 }
84
85 return -1;
86}
87/* }}} */
88
89static size_t readline_shell_ub_write(const char *str, size_t str_length) /* {{{ */
90{
91 /* We just store the last char here and then pass back to the
92 caller (sapi_cli_single_write in sapi/cli) which will actually
93 write due to -1 return code */
94 php_last_char = str[str_length-1];
95
96 return (size_t) -1;
97}
98/* }}} */
99
100static void cli_readline_init_globals(zend_cli_readline_globals *rg)
101{
102 rg->pager = NULL;
103 rg->prompt = NULL;
104 rg->prompt_str = NULL;
105}
106
108 STD_PHP_INI_ENTRY("cli.pager", "", PHP_INI_ALL, OnUpdateString, pager, zend_cli_readline_globals, cli_readline_globals)
109 STD_PHP_INI_ENTRY("cli.prompt", DEFAULT_PROMPT, PHP_INI_ALL, OnUpdateString, prompt, zend_cli_readline_globals, cli_readline_globals)
111
112
113
126
127static zend_string *cli_get_prompt(char *block, char prompt) /* {{{ */
128{
129 smart_str retval = {0};
130 char *prompt_spec = CLIR_G(prompt) ? CLIR_G(prompt) : DEFAULT_PROMPT;
131 bool unicode_warned = false;
132
133 do {
134 if (*prompt_spec == '\\') {
135 switch (prompt_spec[1]) {
136 case '\\':
137 smart_str_appendc(&retval, '\\');
138 prompt_spec++;
139 break;
140 case 'n':
141 smart_str_appendc(&retval, '\n');
142 prompt_spec++;
143 break;
144 case 't':
145 smart_str_appendc(&retval, '\t');
146 prompt_spec++;
147 break;
148 case 'e':
149 smart_str_appendc(&retval, '\033');
150 prompt_spec++;
151 break;
152
153
154 case 'v':
155 smart_str_appends(&retval, PHP_VERSION);
156 prompt_spec++;
157 break;
158 case 'b':
159 smart_str_appends(&retval, block);
160 prompt_spec++;
161 break;
162 case '>':
163 smart_str_appendc(&retval, prompt);
164 prompt_spec++;
165 break;
166 case '`':
167 smart_str_appendc(&retval, '`');
168 prompt_spec++;
169 break;
170 default:
171 smart_str_appendc(&retval, '\\');
172 break;
173 }
174 } else if (*prompt_spec == '`') {
175 char *prompt_end = strstr(prompt_spec + 1, "`");
176 char *code;
177
178 if (prompt_end) {
179 code = estrndup(prompt_spec + 1, prompt_end - prompt_spec - 1);
180
182 zend_try {
183 zend_eval_stringl(code, prompt_end - prompt_spec - 1, NULL, "php prompt code");
184 } zend_end_try();
186 efree(code);
187 prompt_spec = prompt_end;
188 }
189 } else {
190 if (!(*prompt_spec & 0x80)) {
191 smart_str_appendc(&retval, *prompt_spec);
192 } else {
193 if (!unicode_warned) {
195 "prompt contains unsupported unicode characters");
196 unicode_warned = true;
197 }
198 smart_str_appendc(&retval, '?');
199 }
200 }
201 } while (++prompt_spec && *prompt_spec);
202 smart_str_0(&retval);
203 return retval.s;
204}
205/* }}} */
206
207static int cli_is_valid_code(char *code, size_t len, zend_string **prompt) /* {{{ */
208{
209 int valid_end = 1, last_valid_end;
210 int brackets_count = 0;
211 int brace_count = 0;
212 size_t i;
213 php_code_type code_type = body;
214 char *heredoc_tag = NULL;
215 size_t heredoc_len;
216
217 for (i = 0; i < len; ++i) {
218 switch(code_type) {
219 default:
220 switch(code[i]) {
221 case '{':
222 brackets_count++;
223 valid_end = 0;
224 break;
225 case '}':
226 if (brackets_count > 0) {
227 brackets_count--;
228 }
229 valid_end = brackets_count ? 0 : 1;
230 break;
231 case '(':
232 brace_count++;
233 valid_end = 0;
234 break;
235 case ')':
236 if (brace_count > 0) {
237 brace_count--;
238 }
239 valid_end = 0;
240 break;
241 case ';':
242 valid_end = brace_count == 0 && brackets_count == 0;
243 break;
244 case ' ':
245 case '\r':
246 case '\n':
247 case '\t':
248 break;
249 case '\'':
250 code_type = sstring;
251 break;
252 case '"':
253 code_type = dstring;
254 break;
255 case '#':
256 if (code[i+1] == '[') {
257 valid_end = 0;
258 break;
259 }
260 code_type = comment_line;
261 break;
262 case '/':
263 if (code[i+1] == '/') {
264 i++;
265 code_type = comment_line;
266 break;
267 }
268 if (code[i+1] == '*') {
269 last_valid_end = valid_end;
270 valid_end = 0;
271 code_type = comment_block;
272 i++;
273 break;
274 }
275 valid_end = 0;
276 break;
277 case '?':
278 if (code[i+1] == '>') {
279 i++;
280 code_type = outside;
281 break;
282 }
283 valid_end = 0;
284 break;
285 case '<':
286 valid_end = 0;
287 if (i + 2 < len && code[i+1] == '<' && code[i+2] == '<') {
288 i += 2;
289 code_type = heredoc_start;
290 heredoc_tag = NULL;
291 heredoc_len = 0;
292 }
293 break;
294 default:
295 valid_end = 0;
296 break;
297 }
298 break;
299 case sstring:
300 if (code[i] == '\\') {
301 code_type = sstring_esc;
302 } else {
303 if (code[i] == '\'') {
304 code_type = body;
305 }
306 }
307 break;
308 case sstring_esc:
309 code_type = sstring;
310 break;
311 case dstring:
312 if (code[i] == '\\') {
313 code_type = dstring_esc;
314 } else {
315 if (code[i] == '"') {
316 code_type = body;
317 }
318 }
319 break;
320 case dstring_esc:
321 code_type = dstring;
322 break;
323 case comment_line:
324 if (code[i] == '\n') {
325 code_type = body;
326 }
327 break;
328 case comment_block:
329 if (code[i-1] == '*' && code[i] == '/') {
330 code_type = body;
331 valid_end = last_valid_end;
332 }
333 break;
334 case heredoc_start:
335 switch(code[i]) {
336 case ' ':
337 case '\t':
338 case '\'':
339 case '"':
340 break;
341 case '\r':
342 case '\n':
343 if (heredoc_tag) {
344 code_type = heredoc;
345 } else {
346 /* Malformed heredoc without label */
347 code_type = body;
348 }
349 break;
350 default:
351 if (!heredoc_tag) {
352 heredoc_tag = code+i;
353 }
354 heredoc_len++;
355 break;
356 }
357 break;
358 case heredoc:
359 ZEND_ASSERT(heredoc_tag);
360 if (!strncmp(code + i - heredoc_len + 1, heredoc_tag, heredoc_len)) {
361 unsigned char c = code[i + 1];
362 char *p = code + i - heredoc_len;
363
364 if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_' || c >= 0x80) break;
365 while (*p == ' ' || *p == '\t') p--;
366 if (*p != '\n') break;
367 code_type = body;
368 }
369 break;
370 case outside:
371 if ((CG(short_tags) && !strncmp(code+i-1, "<?", 2))
372 || (i > 3 && !strncmp(code+i-4, "<?php", 5))
373 ) {
374 code_type = body;
375 }
376 break;
377 }
378 }
379
380 switch (code_type) {
381 default:
382 if (brace_count) {
383 *prompt = cli_get_prompt("php", '(');
384 } else if (brackets_count) {
385 *prompt = cli_get_prompt("php", '{');
386 } else {
387 *prompt = cli_get_prompt("php", '>');
388 }
389 break;
390 case sstring:
391 case sstring_esc:
392 *prompt = cli_get_prompt("php", '\'');
393 break;
394 case dstring:
395 case dstring_esc:
396 *prompt = cli_get_prompt("php", '"');
397 break;
398 case comment_block:
399 *prompt = cli_get_prompt("/* ", '>');
400 break;
401 case heredoc:
402 *prompt = cli_get_prompt("<<<", '>');
403 break;
404 case outside:
405 *prompt = cli_get_prompt(" ", '>');
406 break;
407 }
408
409 if (!valid_end || brackets_count) {
410 return 0;
411 } else {
412 return 1;
413 }
414}
415/* }}} */
416
417static char *cli_completion_generator_ht(const char *text, size_t textlen, int *state, HashTable *ht, void **pData) /* {{{ */
418{
420 zend_ulong number;
421
422 if (!(*state % 2)) {
423 zend_hash_internal_pointer_reset(ht);
424 (*state)++;
425 }
426 while(zend_hash_has_more_elements(ht) == SUCCESS) {
427 zend_hash_get_current_key(ht, &name, &number);
428 if (!textlen || !strncmp(ZSTR_VAL(name), text, textlen)) {
429 if (pData) {
431 }
432 zend_hash_move_forward(ht);
433 return ZSTR_VAL(name);
434 }
435 if (zend_hash_move_forward(ht) == FAILURE) {
436 break;
437 }
438 }
439 (*state)++;
440 return NULL;
441} /* }}} */
442
443static char *cli_completion_generator_var(const char *text, size_t textlen, int *state) /* {{{ */
444{
445 char *retval, *tmp;
446 zend_array *symbol_table = &EG(symbol_table);
447
448 tmp = retval = cli_completion_generator_ht(text + 1, textlen - 1, state, symbol_table, NULL);
449 if (retval) {
450 retval = malloc(strlen(tmp) + 2);
451 retval[0] = '$';
452 strcpy(&retval[1], tmp);
453 rl_completion_append_character = '\0';
454 }
455 return retval;
456} /* }}} */
457
458static char *cli_completion_generator_ini(const char *text, size_t textlen, int *state) /* {{{ */
459{
460 char *retval, *tmp;
461
462 tmp = retval = cli_completion_generator_ht(text + 1, textlen - 1, state, EG(ini_directives), NULL);
463 if (retval) {
464 retval = malloc(strlen(tmp) + 2);
465 retval[0] = '#';
466 strcpy(&retval[1], tmp);
467 rl_completion_append_character = '=';
468 }
469 return retval;
470} /* }}} */
471
472static char *cli_completion_generator_func(const char *text, size_t textlen, int *state, HashTable *ht) /* {{{ */
473{
475 char *retval = cli_completion_generator_ht(text, textlen, state, ht, (void**)&func);
476 if (retval) {
477 rl_completion_append_character = '(';
478 retval = strdup(ZSTR_VAL(func->common.function_name));
479 }
480
481 return retval;
482} /* }}} */
483
484static char *cli_completion_generator_class(const char *text, size_t textlen, int *state) /* {{{ */
485{
487 char *retval = cli_completion_generator_ht(text, textlen, state, EG(class_table), (void**)&ce);
488 if (retval) {
489 rl_completion_append_character = '\0';
490 retval = strdup(ZSTR_VAL(ce->name));
491 }
492
493 return retval;
494} /* }}} */
495
496static char *cli_completion_generator_define(const char *text, size_t textlen, int *state, HashTable *ht) /* {{{ */
497{
498 zend_class_entry **pce;
499 char *retval = cli_completion_generator_ht(text, textlen, state, ht, (void**)&pce);
500 if (retval) {
501 rl_completion_append_character = '\0';
502 retval = strdup(retval);
503 }
504
505 return retval;
506} /* }}} */
507
508static int cli_completion_state;
509
510static char *cli_completion_generator(const char *text, int index) /* {{{ */
511{
512/*
513TODO:
514- constants
515- maybe array keys
516- language constructs and other things outside a hashtable (echo, try, function, class, ...)
517- object/class members
518
519- future: respect scope ("php > function foo() { $[tab]" should only expand to local variables...)
520*/
521 char *retval = NULL;
522 size_t textlen = strlen(text);
523
524 if (!index) {
525 cli_completion_state = 0;
526 }
527 if (text[0] == '$') {
528 retval = cli_completion_generator_var(text, textlen, &cli_completion_state);
529 } else if (text[0] == '#' && text[1] != '[') {
530 retval = cli_completion_generator_ini(text, textlen, &cli_completion_state);
531 } else {
532 char *lc_text, *class_name_end;
533 zend_string *class_name = NULL;
535
536 class_name_end = strstr(text, "::");
537 if (class_name_end) {
538 size_t class_name_len = class_name_end - text;
539 class_name = zend_string_alloc(class_name_len, 0);
540 zend_str_tolower_copy(ZSTR_VAL(class_name), text, class_name_len);
541 if ((ce = zend_lookup_class(class_name)) == NULL) {
542 zend_string_release_ex(class_name, 0);
543 return NULL;
544 }
545 lc_text = zend_str_tolower_dup(class_name_end + 2, textlen - 2 - class_name_len);
546 textlen -= (class_name_len + 2);
547 } else {
548 lc_text = zend_str_tolower_dup(text, textlen);
549 }
550
551 switch (cli_completion_state) {
552 case 0:
553 case 1:
554 retval = cli_completion_generator_func(lc_text, textlen, &cli_completion_state, ce ? &ce->function_table : EG(function_table));
555 if (retval) {
556 break;
557 }
559 case 2:
560 case 3:
561 retval = cli_completion_generator_define(text, textlen, &cli_completion_state, ce ? &ce->constants_table : EG(zend_constants));
562 if (retval || ce) {
563 break;
564 }
566 case 4:
567 case 5:
568 retval = cli_completion_generator_class(lc_text, textlen, &cli_completion_state);
569 break;
570 default:
571 break;
572 }
573 efree(lc_text);
574 if (class_name) {
575 zend_string_release_ex(class_name, 0);
576 }
577 if (ce && retval) {
578 size_t len = ZSTR_LEN(ce->name) + 2 + strlen(retval) + 1;
579 char *tmp = malloc(len);
580
581 snprintf(tmp, len, "%s::%s", ZSTR_VAL(ce->name), retval);
582 free(retval);
583 retval = tmp;
584 }
585 }
586
587 return retval;
588} /* }}} */
589
590static char **cli_code_completion(const char *text, int start, int end) /* {{{ */
591{
592 return rl_completion_matches(text, cli_completion_generator);
593}
594/* }}} */
595
596static int readline_shell_run(void) /* {{{ */
597{
598 char *line;
599 size_t size = 4096, pos = 0, len;
600 char *code = emalloc(size);
601 zend_string *prompt = cli_get_prompt("php", '>');
602 char *history_file;
603 int history_lines_to_write = 0;
604
605 if (PG(auto_prepend_file) && PG(auto_prepend_file)[0]) {
606 zend_file_handle prepend_file;
607
608 zend_stream_init_filename(&prepend_file, PG(auto_prepend_file));
609 zend_execute_scripts(ZEND_REQUIRE, NULL, 1, &prepend_file);
610 zend_destroy_file_handle(&prepend_file);
611 }
612
613#ifndef PHP_WIN32
614 const char *histfile_env_name = "PHP_HISTFILE";
615 if (getenv(histfile_env_name)) {
616 spprintf(&history_file, MAXPATHLEN, "%s", getenv(histfile_env_name));
617 } else {
618 spprintf(&history_file, MAXPATHLEN, "%s/.php_history", getenv("HOME"));
619 }
620#else
621 spprintf(&history_file, MAX_PATH, "%s/.php_history", getenv("USERPROFILE"));
622#endif
623 /* Install the default completion function for 'php -a'.
624 *
625 * But if readline_completion_function() was called by PHP code prior to the shell starting
626 * (e.g. with 'php -d auto_prepend_file=prepend.php -a'),
627 * then use that instead of PHP's default. */
628 if (rl_attempted_completion_function != php_readline_completion_cb) {
629 rl_attempted_completion_function = cli_code_completion;
630 }
631#ifndef PHP_WIN32
632 rl_special_prefixes = "$";
633#endif
634 read_history(history_file);
635
636 EG(exit_status) = 0;
637 while ((line = readline(ZSTR_VAL(prompt))) != NULL) {
638 if (strcmp(line, "exit") == 0 || strcmp(line, "quit") == 0) {
639 free(line);
640 break;
641 }
642
643 if (!pos && !*line) {
644 free(line);
645 continue;
646 }
647
648 len = strlen(line);
649
650 if (line[0] == '#' && line[1] != '[') {
651 char *param = strstr(&line[1], "=");
652 if (param) {
653 zend_string *cmd;
654 param++;
655 cmd = zend_string_init(&line[1], param - &line[1] - 1, 0);
656
659 add_history(line);
660
662 /* TODO: This might be wrong! */
663 prompt = cli_get_prompt("php", '>');
664 continue;
665 }
666 }
667
668 if (pos + len + 2 > size) {
669 size = pos + len + 2;
670 code = erealloc(code, size);
671 }
672 memcpy(&code[pos], line, len);
673 pos += len;
674 code[pos] = '\n';
675 code[++pos] = '\0';
676
677 if (*line) {
678 add_history(line);
679 history_lines_to_write += 1;
680 }
681
682 free(line);
684
685 if (!cli_is_valid_code(code, pos, &prompt)) {
686 continue;
687 }
688
689 if (history_lines_to_write) {
690#ifdef HAVE_LIBEDIT
691 write_history(history_file);
692#else
693 append_history(history_lines_to_write, history_file);
694#endif
695 history_lines_to_write = 0;
696 }
697
698 zend_try {
699 zend_eval_stringl(code, pos, NULL, "php shell code");
700 } zend_end_try();
701
702 pos = 0;
703
704 if (!pager_pipe && php_last_char != '\0' && php_last_char != '\n') {
705 php_write("\n", 1);
706 }
707
708 if (EG(exception)) {
710 }
711
712 if (pager_pipe) {
713 fclose(pager_pipe);
714 pager_pipe = NULL;
715 }
716
717 php_last_char = '\0';
718 }
719 efree(history_file);
720 efree(code);
722 return EG(exit_status);
723}
724/* }}} */
725
726#ifdef PHP_WIN32
727typedef cli_shell_callbacks_t *(__cdecl *get_cli_shell_callbacks)(void);
728#define GET_SHELL_CB(cb) \
729 do { \
730 get_cli_shell_callbacks get_callbacks; \
731 HMODULE hMod = GetModuleHandle("php.exe"); \
732 (cb) = NULL; \
733 if (strlen(sapi_module.name) >= 3 && 0 == strncmp("cli", sapi_module.name, 3)) { \
734 get_callbacks = (get_cli_shell_callbacks)GetProcAddress(hMod, "php_cli_get_shell_callbacks"); \
735 if (get_callbacks) { \
736 (cb) = get_callbacks(); \
737 } \
738 } \
739 } while(0)
740
741#else
742/*
743#ifdef COMPILE_DL_READLINE
744This dlsym() is always used as even the CGI SAPI is linked against "CLI"-only
745extensions. If that is being changed dlsym() should only be used when building
746this extension sharedto offer compatibility.
747*/
748#define GET_SHELL_CB(cb) \
749 do { \
750 (cb) = NULL; \
751 cli_shell_callbacks_t *(*get_callbacks)(void); \
752 get_callbacks = dlsym(RTLD_DEFAULT, "php_cli_get_shell_callbacks"); \
753 if (get_callbacks) { \
754 (cb) = get_callbacks(); \
755 } \
756 } while(0)
757/*#else
758#define GET_SHELL_CB(cb) (cb) = php_cli_get_shell_callbacks()
759#endif*/
760#endif
761
763{
765
766 ZEND_INIT_MODULE_GLOBALS(cli_readline, cli_readline_init_globals, NULL);
768
770 if (cb) {
771 cb->cli_shell_write = readline_shell_write;
772 cb->cli_shell_ub_write = readline_shell_ub_write;
773 cb->cli_shell_run = readline_shell_run;
774 }
775
776 return SUCCESS;
777}
778
780{
782
784
786 if (cb) {
787 cb->cli_shell_write = NULL;
788 cb->cli_shell_ub_write = NULL;
789 cb->cli_shell_run = NULL;
790 }
791
792 return SUCCESS;
793}
794
796{
798 php_info_print_table_row(2, "Readline Support", "enabled");
799#ifdef PHP_WIN32
800 php_info_print_table_row(2, "Readline library", "WinEditLine");
801#else
802 php_info_print_table_row(2, "Readline library", (rl_library_version ? rl_library_version : "Unknown"));
803#endif
805
807}
size_t len
Definition apprentice.c:174
char * cb
Definition assert.c:26
bool exception
Definition assert.c:30
getenv(?string $name=null, bool $local_only=false)
fwrite($stream, string $data, ?int $length=null)
fclose($stream)
strstr(string $haystack, string $needle, bool $before_needle=false)
new_type size
Definition ffi.c:4365
memcpy(ptr1, ptr2, size)
HashTable * ht
Definition ffi.c:4838
buf start
Definition ffi.c:4687
#define NULL
Definition gdcache.h:45
#define SUCCESS
Definition hash_sha3.c:261
PHPAPI size_t php_write(void *buf, size_t size)
Definition main.c:931
php_info_print_table_start()
Definition info.c:1064
php_info_print_table_row(2, "PDO Driver for Firebird", "enabled")
php_info_print_table_end()
Definition info.c:1074
#define PHP_MSHUTDOWN_FUNCTION
Definition php.h:401
#define PHP_MINIT_FUNCTION
Definition php.h:400
#define PHP_MINFO_FUNCTION
Definition php.h:404
int line
Definition php_ffi.h:54
unsigned const char * end
Definition php_ffi.h:51
unsigned const char * pos
Definition php_ffi.h:52
unsigned const char * text
Definition php_ffi.h:53
#define PG(v)
Definition php_globals.h:31
#define PHP_INI_STAGE_RUNTIME
Definition php_ini.h:75
#define PHP_INI_ALL
Definition php_ini.h:45
#define PHP_INI_USER
Definition php_ini.h:41
#define PHP_INI_BEGIN
Definition php_ini.h:52
#define STD_PHP_INI_ENTRY
Definition php_ini.h:64
#define PHP_INI_END
Definition php_ini.h:53
#define PHP_VERSION
Definition php_version.h:7
readline(?string $prompt=null)
#define DEFAULT_PROMPT
php_code_type
@ comment_line
@ sstring_esc
@ body
@ comment_block
@ dstring
@ dstring_esc
@ outside
@ sstring
@ heredoc
@ heredoc_start
#define GET_SHELL_CB(cb)
#define rl_completion_matches
char ** php_readline_completion_cb(const char *text, int start, int end)
smart_str * prompt_str
#define CLIR_G(v)
char * prompt
char * pager
p
Definition session.c:1105
#define spprintf
Definition spprintf.h:29
HashTable constants_table
Definition zend.h:165
zend_string * name
Definition zend.h:149
HashTable function_table
Definition zend.h:163
ZEND_API zend_result zend_execute_scripts(int type, zval *retval, int file_count,...)
Definition zend.c:1954
ZEND_API ZEND_COLD void zend_error(int type, const char *format,...)
Definition zend.c:1666
#define zend_try
Definition zend.h:270
#define zend_end_try()
Definition zend.h:280
#define ZEND_INIT_MODULE_GLOBALS(module_name, globals_ctor, globals_dtor)
Definition zend_API.h:272
#define ZEND_DECLARE_MODULE_GLOBALS(module_name)
Definition zend_API.h:268
#define estrndup(s, length)
Definition zend_alloc.h:165
#define efree(ptr)
Definition zend_alloc.h:155
#define erealloc(ptr, size)
Definition zend_alloc.h:159
#define emalloc(size)
Definition zend_alloc.h:151
strlen(string $string)
strncmp(string $string1, string $string2, int $length)
strcmp(string $string1, string $string2)
zend_string_release_ex(func->internal_function.function_name, 0)
execute_data func
#define ZEND_REQUIRE
ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle)
#define snprintf
#define E_WARNING
Definition zend_errors.h:24
ZEND_API ZEND_COLD zend_result zend_exception_error(zend_object *ex, int severity)
ZEND_API zend_class_entry * zend_lookup_class(zend_string *name)
ZEND_API zend_result zend_eval_stringl(const char *str, size_t str_len, zval *retval_ptr, const char *string_name)
union _zend_function zend_function
#define CG(v)
#define EG(v)
#define zend_hash_get_current_data_ptr(ht)
Definition zend_hash.h:990
ZEND_API zend_result zend_alter_ini_entry_chars_ex(zend_string *name, const char *value, size_t value_length, int modify_type, int stage, int force_change)
Definition zend_ini.c:344
#define UNREGISTER_INI_ENTRIES()
Definition zend_ini.h:204
#define REGISTER_INI_ENTRIES()
Definition zend_ini.h:203
#define DISPLAY_INI_ENTRIES()
Definition zend_ini.h:205
struct _zend_file_handle zend_file_handle
uint32_t zend_ulong
Definition zend_long.h:43
struct _zend_string zend_string
ZEND_API char *ZEND_FASTCALL zend_str_tolower_copy(char *dest, const char *source, size_t length)
ZEND_API char *ZEND_FASTCALL zend_str_tolower_dup(const char *source, size_t length)
#define MIN(a, b)
#define ZEND_FALLTHROUGH
#define ZEND_ASSERT(c)
struct _zend_array zend_array
struct _zend_class_entry zend_class_entry
ZEND_API void zend_stream_init_filename(zend_file_handle *handle, const char *filename)
Definition zend_stream.c:70
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
struct _zend_array HashTable
Definition zend_types.h:386
@ FAILURE
Definition zend_types.h:61
#define VCWD_POPEN(command, type)
#define MAXPATHLEN
zval retval
zend_string * name