[ Index ] |
|
Code source de PRADO 3.0.6 |
1 <?php 2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 3 4 /* 5 (c) 2006 Jan Kneschke <jan@kneschke.de> 6 7 Permission is hereby granted, free of charge, to any person obtaining a copy of 8 this software and associated documentation files (the "Software"), to deal in 9 the Software without restriction, including without limitation the rights to 10 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 11 of the Software, and to permit persons to whom the Software is furnished to do 12 so, subject to the following conditions: 13 14 The above copyright notice and this permission notice shall be included in all 15 copies or substantial portions of the Software. 16 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 SOFTWARE. 24 */ 25 26 /** 27 * A interactive PHP Shell 28 * 29 * The more I work with other languages like python and ruby I like their way how they 30 * work on problems. While PHP is very forgiving on errors, it is weak on the debugging 31 * side. It was missing a simple to use interactive shell for years. Python and Ruby have 32 * their ipython and iruby shell which give you a direct way to interact with the objects. 33 * No need to write a script and execute it afterwards. 34 * 35 * Starting the Shell: 36 * 37 * The package contains a shell wrapper for windows and unix: 38 * <pre> 39 * sh> php-shell.sh 40 * win> php-shell 41 * </pre> 42 * 43 * Both are calling the wrapper script <code>php -q php-shell-cmd.php</code> 44 * 45 * Inline Help 46 * 47 * <pre> 48 * PHP-Shell - Version 0.2.0, with readline() support 49 * (c) 2006, Jan Kneschke <jan@kneschke.de> 50 * 51 * >> use '?' to open the inline help 52 * 53 * >> ? 54 * "inline help for the PHP-shell 55 * 56 * >> ? 57 * print this help 58 * >> ? <topic> 59 * get the doccomment for a class, method, property or function 60 * >> p <var> 61 * execute a verbose print (if implemented) 62 * >> quit 63 * leave shell 64 * " 65 * >> ? PHP_Shell 66 * </pre> 67 * Alternatives 68 * 69 * - http://david.acz.org/phpa/ 70 * - http://www.hping.org/phpinteractive/ 71 * - the embedded interactive php-shell: $ php -a 72 * 73 * @package PHP 74 */ 75 76 /** 77 * PHP_Shell 78 * 79 * a interactive PHP Shell with tab-completion and history 80 * it can catch FATAL errors before executing the code 81 * 82 * Extensions are provided through three side-classes: 83 * 84 * - PHP_Shell_Commands 85 * - PHP_Shell_Options 86 * - PHP_Shell_Extensions 87 * 88 * @package PHP 89 */ 90 91 require_once(dirname(__FILE__)."/Shell/Commands.php"); 92 require_once(dirname(__FILE__)."/Shell/Options.php"); /* for the tab-complete */ 93 94 class PHP_Shell { 95 /** 96 * current code-buffer 97 * @var string 98 */ 99 protected $code; 100 101 /** 102 * set if readline support is enabled 103 * @var bool 104 */ 105 protected $have_readline; 106 107 /** 108 * current version of the class 109 * @var string 110 */ 111 protected $version = '0.3.1'; 112 113 /** 114 * 115 */ 116 protected $stdin; 117 118 protected $code_buffer; 119 120 public $has_semicolon=false; 121 122 /** 123 * init the shell and change if readline support is available 124 */ 125 public function __construct() { 126 $this->code = ''; 127 128 $this->stdin = null; 129 130 $this->have_readline = function_exists('readline'); 131 132 if ($this->have_readline) { 133 readline_completion_function('__shell_readline_complete'); 134 } 135 136 $this->use_readline = true; 137 138 $cmd = PHP_Shell_Commands::getInstance(); 139 140 $cmd->registerCommand('#^quit$#', $this, 'cmdQuit', 'quit', 'leaves the shell'); 141 $cmd->registerCommand('#^\?$#', $this, 'cmdHelp', '?', 'show this help'); 142 $cmd->registerCommand('#^\?\s+license$#', $this, 'cmdLicense', '? license', 'show license of the shell'); 143 } 144 145 146 /** 147 * parse the PHP code 148 * 149 * we parse before we eval() the code to 150 * - fetch fatal errors before they come up 151 * - know about where we have to wait for closing braces 152 * 153 * @return int 0 if a executable statement is in the code-buffer, non-zero otherwise 154 */ 155 public function parse() { 156 ## remove empty lines 157 if (trim($this->code) == '') return 1; 158 159 $t = token_get_all('<?php '.$this->code.' ?>'); 160 161 $need_semicolon = 1; /* do we need a semicolon to complete the statement ? */ 162 $need_return = 1; /* can we prepend a return to the eval-string ? */ 163 $open_comment = 0; /* a open multi-line comment */ 164 $eval = ''; /* code to be eval()'ed later */ 165 $braces = array(); /* to track if we need more closing braces */ 166 167 $methods = array(); /* to track duplicate methods in a class declaration */ 168 $ts = array(); /* tokens without whitespaces */ 169 170 foreach ($t as $ndx => $token) { 171 if (is_array($token)) { 172 $ignore = 0; 173 174 switch($token[0]) { 175 case T_WHITESPACE: 176 case T_OPEN_TAG: 177 case T_CLOSE_TAG: 178 $ignore = 1; 179 break; 180 case T_FOREACH: 181 case T_DO: 182 case T_WHILE: 183 case T_FOR: 184 185 case T_IF: 186 case T_RETURN: 187 188 case T_CLASS: 189 case T_FUNCTION: 190 case T_INTERFACE: 191 192 case T_PRINT: 193 case T_ECHO: 194 195 case T_COMMENT: 196 case T_UNSET: 197 198 case T_INCLUDE: 199 case T_REQUIRE: 200 case T_INCLUDE_ONCE: 201 case T_REQUIRE_ONCE: 202 case T_TRY: 203 case T_SWITCH: 204 case T_DEFAULT: 205 case T_CASE: 206 case T_BREAK: 207 case T_DOC_COMMENT: 208 $need_return = 0; 209 break; 210 case T_EMPTY: 211 case T_ISSET: 212 case T_EVAL: 213 case T_EXIT: 214 215 case T_VARIABLE: 216 case T_STRING: 217 case T_NEW: 218 case T_EXTENDS: 219 case T_IMPLEMENTS: 220 case T_OBJECT_OPERATOR: 221 case T_DOUBLE_COLON: 222 case T_INSTANCEOF: 223 224 case T_CATCH: 225 case T_THROW: 226 227 case T_ELSE: 228 case T_AS: 229 case T_LNUMBER: 230 case T_DNUMBER: 231 case T_CONSTANT_ENCAPSED_STRING: 232 case T_ENCAPSED_AND_WHITESPACE: 233 case T_CHARACTER: 234 case T_ARRAY: 235 case T_DOUBLE_ARROW: 236 237 case T_CONST: 238 case T_PUBLIC: 239 case T_PROTECTED: 240 case T_PRIVATE: 241 case T_ABSTRACT: 242 case T_STATIC: 243 case T_VAR: 244 245 case T_INC: 246 case T_DEC: 247 case T_SL: 248 case T_SL_EQUAL: 249 case T_SR: 250 case T_SR_EQUAL: 251 252 case T_IS_EQUAL: 253 case T_IS_IDENTICAL: 254 case T_IS_GREATER_OR_EQUAL: 255 case T_IS_SMALLER_OR_EQUAL: 256 257 case T_BOOLEAN_OR: 258 case T_LOGICAL_OR: 259 case T_BOOLEAN_AND: 260 case T_LOGICAL_AND: 261 case T_LOGICAL_XOR: 262 case T_MINUS_EQUAL: 263 case T_PLUS_EQUAL: 264 case T_MUL_EQUAL: 265 case T_DIV_EQUAL: 266 case T_MOD_EQUAL: 267 case T_XOR_EQUAL: 268 case T_AND_EQUAL: 269 case T_OR_EQUAL: 270 271 case T_FUNC_C: 272 case T_CLASS_C: 273 case T_LINE: 274 case T_FILE: 275 276 case T_BOOL_CAST: 277 case T_INT_CAST: 278 case T_STRING_CAST: 279 280 /* just go on */ 281 break; 282 default: 283 /* debug unknown tags*/ 284 error_log(sprintf("unknown tag: %d (%s): %s".PHP_EOL, $token[0], token_name($token[0]), $token[1])); 285 286 break; 287 } 288 if (!$ignore) { 289 $eval .= $token[1]." "; 290 $ts[] = array("token" => $token[0], "value" => $token[1]); 291 } 292 } else { 293 $ts[] = array("token" => $token, "value" => ''); 294 295 $last = count($ts) - 1; 296 297 switch ($token) { 298 case '(': 299 /* walk backwards through the tokens */ 300 301 if ($last >= 4 && 302 $ts[$last - 1]['token'] == T_STRING && 303 $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && 304 $ts[$last - 3]['token'] == ')' ) { 305 /* func()->method() 306 * 307 * we can't know what func() is return, so we can't 308 * say if the method() exists or not 309 * 310 */ 311 } else if ($last >= 3 && 312 $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ 313 $ts[0]['token'] != T_ABSTRACT && /* if we are not in a class definition */ 314 $ts[1]['token'] != T_CLASS && /* if we are not in a class definition */ 315 $ts[$last - 1]['token'] == T_STRING && 316 $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && 317 $ts[$last - 3]['token'] == T_VARIABLE ) { 318 319 /* $object->method( */ 320 321 /* catch (Exception $e) does not set $e in $GLOBALS[] */ 322 $in_catch = 0; 323 324 foreach ($ts as $v) { 325 if ($v['token'] == T_CATCH) { 326 $in_catch = 1; 327 } 328 } 329 330 if (!$in_catch) { 331 /* $object has to exist and has to be a object */ 332 $objname = $ts[$last - 3]['value']; 333 334 if (!isset($GLOBALS[ltrim($objname, '$')])) { 335 throw new Exception(sprintf('Variable \'%s\' is not set', $objname)); 336 } 337 $object = $GLOBALS[ltrim($objname, '$')]; 338 339 if (!is_object($object)) { 340 throw new Exception(sprintf('Variable \'%s\' is not a class', $objname)); 341 } 342 343 $method = $ts[$last - 1]['value']; 344 345 /* obj */ 346 347 if (!method_exists($object, $method)) { 348 throw new Exception(sprintf("Variable %s (Class '%s') doesn't have a method named '%s'", 349 $objname, get_class($object), $method)); 350 } 351 } 352 } else if ($last >= 3 && 353 $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ 354 $ts[$last - 1]['token'] == T_VARIABLE && 355 $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && 356 $ts[$last - 3]['token'] == T_VARIABLE ) { 357 358 /* $object->$method( */ 359 360 /* $object has to exist and has to be a object */ 361 $objname = $ts[$last - 3]['value']; 362 363 if (!isset($GLOBALS[ltrim($objname, '$')])) { 364 throw new Exception(sprintf('Variable \'%s\' is not set', $objname)); 365 } 366 $object = $GLOBALS[ltrim($objname, '$')]; 367 368 if (!is_object($object)) { 369 throw new Exception(sprintf('Variable \'%s\' is not a class', $objname)); 370 } 371 372 $methodname = $ts[$last - 1]['value']; 373 374 if (!isset($GLOBALS[ltrim($methodname, '$')])) { 375 throw new Exception(sprintf('Variable \'%s\' is not set', $methodname)); 376 } 377 $method = $GLOBALS[ltrim($methodname, '$')]; 378 379 /* obj */ 380 381 if (!method_exists($object, $method)) { 382 throw new Exception(sprintf("Variable %s (Class '%s') doesn't have a method named '%s'", 383 $objname, get_class($object), $method)); 384 } 385 386 } else if ($last >= 6 && 387 $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ 388 $ts[$last - 1]['token'] == T_STRING && 389 $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && 390 $ts[$last - 3]['token'] == ']' && 391 /* might be anything as index */ 392 $ts[$last - 5]['token'] == '[' && 393 $ts[$last - 6]['token'] == T_VARIABLE ) { 394 395 /* $object[...]->method( */ 396 397 /* $object has to exist and has to be a object */ 398 $objname = $ts[$last - 6]['value']; 399 400 if (!isset($GLOBALS[ltrim($objname, '$')])) { 401 throw new Exception(sprintf('Variable \'%s\' is not set', $objname)); 402 } 403 $array = $GLOBALS[ltrim($objname, '$')]; 404 405 if (!is_array($array)) { 406 throw new Exception(sprintf('Variable \'%s\' is not a array', $objname)); 407 } 408 409 $andx = $ts[$last - 4]['value']; 410 411 if (!isset($array[$andx])) { 412 throw new Exception(sprintf('%s[\'%s\'] is not set', $objname, $andx)); 413 } 414 415 $object = $array[$andx]; 416 417 if (!is_object($object)) { 418 throw new Exception(sprintf('Variable \'%s\' is not a class', $objname)); 419 } 420 421 $method = $ts[$last - 1]['value']; 422 423 /* obj */ 424 425 if (!method_exists($object, $method)) { 426 throw new Exception(sprintf("Variable %s (Class '%s') doesn't have a method named '%s'", 427 $objname, get_class($object), $method)); 428 } 429 430 } else if ($last >= 3 && 431 $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ 432 $ts[$last - 1]['token'] == T_STRING && 433 $ts[$last - 2]['token'] == T_DOUBLE_COLON && 434 $ts[$last - 3]['token'] == T_STRING ) { 435 436 /* Class::method() */ 437 438 /* $object has to exist and has to be a object */ 439 $classname = $ts[$last - 3]['value']; 440 441 if (!class_exists($classname)) { 442 throw new Exception(sprintf('Class \'%s\' doesn\'t exist', $classname)); 443 } 444 445 $method = $ts[$last - 1]['value']; 446 447 if (!in_array($method, get_class_methods($classname))) { 448 throw new Exception(sprintf("Class '%s' doesn't have a method named '%s'", 449 $classname, $method)); 450 } 451 } else if ($last >= 3 && 452 $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ 453 $ts[$last - 1]['token'] == T_VARIABLE && 454 $ts[$last - 2]['token'] == T_DOUBLE_COLON && 455 $ts[$last - 3]['token'] == T_STRING ) { 456 457 /* $var::method() */ 458 459 /* $object has to exist and has to be a object */ 460 $classname = $ts[$last - 3]['value']; 461 462 if (!class_exists($classname)) { 463 throw new Exception(sprintf('Class \'%s\' doesn\'t exist', $classname)); 464 } 465 466 $methodname = $ts[$last - 1]['value']; 467 468 if (!isset($GLOBALS[ltrim($methodname, '$')])) { 469 throw new Exception(sprintf('Variable \'%s\' is not set', $methodname)); 470 } 471 $method = $GLOBALS[ltrim($methodname, '$')]; 472 473 if (!in_array($method, get_class_methods($classname))) { 474 throw new Exception(sprintf("Class '%s' doesn't have a method named '%s'", 475 $classname, $method)); 476 } 477 478 } else if ($last >= 2 && 479 $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ 480 $ts[$last - 1]['token'] == T_STRING && 481 $ts[$last - 2]['token'] == T_NEW ) { 482 483 /* new Class() */ 484 485 /* don't care about this in a class ... { ... } */ 486 487 $classname = $ts[$last - 1]['value']; 488 489 if (!class_exists($classname)) { 490 throw new Exception(sprintf('Class \'%s\' doesn\'t exist', $classname)); 491 } 492 493 $r = new ReflectionClass($classname); 494 495 if ($r->isAbstract()) { 496 throw new Exception(sprintf("Can't instantiate abstract Class '%s'", $classname)); 497 } 498 499 if (!$r->isInstantiable()) { 500 throw new Exception(sprintf('Class \'%s\' can\'t be instantiated. Is the class abstract ?', $classname)); 501 } 502 503 } else if ($last >= 2 && 504 $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ 505 $ts[$last - 1]['token'] == T_STRING && 506 $ts[$last - 2]['token'] == T_FUNCTION ) { 507 508 /* make sure we are not a in class definition */ 509 510 /* function a() */ 511 512 $func = $ts[$last - 1]['value']; 513 514 if (function_exists($func)) { 515 throw new Exception(sprintf('Function \'%s\' is already defined', $func)); 516 } 517 } else if ($last >= 4 && 518 $ts[0]['token'] == T_CLASS && 519 $ts[1]['token'] == T_STRING && 520 $ts[$last - 1]['token'] == T_STRING && 521 $ts[$last - 2]['token'] == T_FUNCTION ) { 522 523 /* make sure we are not a in class definition */ 524 525 /* class a { .. function a() ... } */ 526 527 $func = $ts[$last - 1]['value']; 528 $classname = $ts[1]['value']; 529 530 if (isset($methods[$func])) { 531 throw new Exception(sprintf("Can't redeclare method '%s' in Class '%s'", $func, $classname)); 532 } 533 534 $methods[$func] = 1; 535 536 } else if ($last >= 1 && 537 $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ 538 $ts[0]['token'] != T_ABSTRACT && /* if we are not in a class definition */ 539 $ts[1]['token'] != T_CLASS && /* if we are not in a class definition */ 540 $ts[$last - 1]['token'] == T_STRING ) { 541 /* func() */ 542 $funcname = $ts[$last - 1]['value']; 543 544 if (!function_exists($funcname)) { 545 throw new Exception(sprintf("Function %s() doesn't exist", $funcname)); 546 } 547 } else if ($last >= 1 && 548 $ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ 549 $ts[$last - 1]['token'] == T_VARIABLE ) { 550 551 /* $object has to exist and has to be a object */ 552 $funcname = $ts[$last - 1]['value']; 553 554 if (!isset($GLOBALS[ltrim($funcname, '$')])) { 555 throw new Exception(sprintf('Variable \'%s\' is not set', $funcname)); 556 } 557 $func = $GLOBALS[ltrim($funcname, '$')]; 558 559 if (!function_exists($func)) { 560 throw new Exception(sprintf("Function %s() doesn't exist", $func)); 561 } 562 563 } 564 565 array_push($braces, $token); 566 break; 567 case '{': 568 $need_return = 0; 569 570 if ($last >= 2 && 571 $ts[$last - 1]['token'] == T_STRING && 572 $ts[$last - 2]['token'] == T_CLASS ) { 573 574 /* class name { */ 575 576 $classname = $ts[$last - 1]['value']; 577 578 if (class_exists($classname, false)) { 579 throw new Exception(sprintf("Class '%s' can't be redeclared", $classname)); 580 } 581 } else if ($last >= 4 && 582 $ts[$last - 1]['token'] == T_STRING && 583 $ts[$last - 2]['token'] == T_EXTENDS && 584 $ts[$last - 3]['token'] == T_STRING && 585 $ts[$last - 4]['token'] == T_CLASS ) { 586 587 /* class classname extends classname { */ 588 589 $classname = $ts[$last - 3]['value']; 590 $extendsname = $ts[$last - 1]['value']; 591 592 if (class_exists($classname, false)) { 593 throw new Exception(sprintf("Class '%s' can't be redeclared", 594 $classname)); 595 } 596 if (!class_exists($extendsname, true)) { 597 throw new Exception(sprintf("Can't extend '%s' ... from not existing Class '%s'", 598 $classname, $extendsname)); 599 } 600 } else if ($last >= 4 && 601 $ts[$last - 1]['token'] == T_STRING && 602 $ts[$last - 2]['token'] == T_IMPLEMENTS && 603 $ts[$last - 3]['token'] == T_STRING && 604 $ts[$last - 4]['token'] == T_CLASS ) { 605 606 /* class name implements interface { */ 607 608 $classname = $ts[$last - 3]['value']; 609 $implements = $ts[$last - 1]['value']; 610 611 if (class_exists($classname, false)) { 612 throw new Exception(sprintf("Class '%s' can't be redeclared", 613 $classname)); 614 } 615 if (!interface_exists($implements, false)) { 616 throw new Exception(sprintf("Can't implement not existing Interface '%s' for Class '%s'", 617 $implements, $classname)); 618 } 619 } 620 621 array_push($braces, $token); 622 break; 623 case '}': 624 $need_return = 0; 625 case ')': 626 array_pop($braces); 627 break; 628 case '[': 629 if ($ts[0]['token'] != T_CLASS && /* if we are not in a class definition */ 630 $ts[0]['token'] != T_ABSTRACT && /* if we are not in a class definition */ 631 $ts[1]['token'] != T_CLASS && /* if we are not in a class definition */ 632 $ts[$last - 1]['token'] == T_VARIABLE) { 633 /* $a[] only works on array and string */ 634 635 /* $object has to exist and has to be a object */ 636 $objname = $ts[$last - 1]['value']; 637 638 if (!isset($GLOBALS[ltrim($objname, '$')])) { 639 throw new Exception(sprintf('Variable \'%s\' is not set', $objname)); 640 } 641 $obj = $GLOBALS[ltrim($objname, '$')]; 642 643 if (is_object($obj)) { 644 throw new Exception(sprintf('Objects (%s) don\'t support array access operators', $objname)); 645 } 646 } 647 break; 648 } 649 650 $eval .= $token; 651 } 652 } 653 654 $last = count($ts) - 1; 655 if ($last >= 2 && 656 $ts[$last - 0]['token'] == T_STRING && 657 $ts[$last - 1]['token'] == T_DOUBLE_COLON && 658 $ts[$last - 2]['token'] == T_STRING ) { 659 660 /* Class::constant */ 661 662 /* $object has to exist and has to be a object */ 663 $classname = $ts[$last - 2]['value']; 664 665 if (!class_exists($classname)) { 666 throw new Exception(sprintf('Class \'%s\' doesn\'t exist', $classname)); 667 } 668 669 $constname = $ts[$last - 0]['value']; 670 671 $c = new ReflectionClass($classname); 672 if (!$c->hasConstant($constname)) { 673 throw new Exception(sprintf("Class '%s' doesn't have a constant named '%s'", 674 $classname, $constname)); 675 } 676 } else if ($last == 0 && 677 $ts[$last - 0]['token'] == T_VARIABLE ) { 678 679 /* $var */ 680 681 $varname = $ts[$last - 0]['value']; 682 683 if (!isset($GLOBALS[ltrim($varname, '$')])) { 684 throw new Exception(sprintf('Variable \'%s\' is not set', $varname)); 685 } 686 } 687 688 689 $need_more = (count($braces) > 0) || $open_comment; 690 691 if ($need_more || ';' === $token) { 692 $need_semicolon = 0; 693 } 694 695 if ($need_return) { 696 $eval = "return ".$eval; 697 } 698 699 /* add a traling ; if necessary */ 700 if ($need_semicolon) 701 { 702 $this->has_semicolon = preg_match('/;\s*$/', $eval); 703 $eval .= ';'; 704 } 705 706 if (!$need_more) { 707 $this->code = $eval; 708 } 709 710 return $need_more; 711 } 712 713 /** 714 * show the prompt and fetch a single line 715 * 716 * uses readline() if avaialbe 717 * 718 * @return string a input-line 719 */ 720 public function readline() { 721 if (empty($this->code)) print PHP_EOL; 722 723 $prompt = (empty($this->code)) ? '>> ' : '.. '; 724 725 if (count($this->code_buffer) > 0) { 726 print $prompt; 727 728 $line = array_shift($this->code_buffer); 729 730 print $line.PHP_EOL; 731 732 return $line.PHP_EOL; 733 } 734 735 if ($this->have_readline) { 736 $l = readline($prompt); 737 738 readline_add_history($l); 739 } else { 740 print $prompt; 741 742 if (is_null($this->stdin)) { 743 if (false === ($this->stdin = fopen("php://stdin", "r"))) { 744 return false; 745 } 746 } 747 $l = fgets($this->stdin); 748 } 749 return $l; 750 } 751 752 /** 753 * get the inline help 754 * 755 * @return string the inline help as string 756 */ 757 public function cmdHelp($l) { 758 $o = 'Inline Help:'.PHP_EOL; 759 760 $cmds = PHP_Shell_Commands::getInstance()->getCommands(); 761 762 foreach ($cmds as $cmd) { 763 $o .= sprintf(' >> %s'.PHP_EOL.' %s'.PHP_EOL, 764 $cmd['command'], 765 $cmd['description'] 766 ); 767 } 768 769 return var_export($o, 1); 770 } 771 772 /** 773 * get the license string 774 * 775 * @return string the inline help as string 776 */ 777 public function cmdLicense($l) { 778 $o = <<<EOF 779 (c) 2006 Jan Kneschke <jan@kneschke.de> 780 781 Permission is hereby granted, free of charge, to any person obtaining a copy of 782 this software and associated documentation files (the "Software"), to deal in 783 the Software without restriction, including without limitation the rights to 784 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 785 of the Software, and to permit persons to whom the Software is furnished to do 786 so, subject to the following conditions: 787 788 The above copyright notice and this permission notice shall be included in all 789 copies or substantial portions of the Software. 790 791 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 792 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 793 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 794 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 795 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 796 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 797 SOFTWARE. 798 EOF; 799 800 return var_export($o, 1); 801 } 802 803 /** 804 * handle the 'quit' command 805 * 806 * @return bool false to leave the input() call 807 * @see input 808 */ 809 protected function cmdQuit($l) { 810 return false; 811 } 812 813 /** 814 * handle the input line 815 * 816 * read the input and handle the commands of the shell 817 * 818 * @return bool false on 'quit' or EOF, true otherwise 819 */ 820 public function input() { 821 $l = $this->readline(); 822 823 /* got EOF ? */ 824 if (false === $l) return false; 825 826 $l = trim($l); 827 828 if (empty($this->code)) { 829 $this->verbose = 0; 830 831 $cmds = PHP_Shell_Commands::getInstance()->getCommands(); 832 833 foreach ($cmds as $cmd) { 834 if (preg_match($cmd['regex'], $l)) { 835 $obj = $cmd['obj']; 836 $func = $cmd['method']; 837 838 if (false === ($l = $obj->$func($l))) { 839 ## quit 840 return false; 841 } 842 843 if (is_array($l)) { 844 $this->code_buffer = $l; 845 $l = ''; 846 } 847 break; 848 } 849 } 850 } 851 852 $this->appendCode($l); 853 854 return true; 855 } 856 857 /** 858 * get the code-buffer 859 * 860 * @return string the code-buffer 861 */ 862 public function getCode() { 863 return $this->code; 864 return $code; 865 } 866 867 /** 868 * reset the code-buffer 869 */ 870 public function resetCode() { 871 $this->has_semicolon=false; 872 $this->code = ''; 873 } 874 875 /** 876 * append code to the code-buffer 877 * 878 * @param string $code input buffer 879 */ 880 public function appendCode($code) { 881 if (strlen($code)) $code .= PHP_EOL; 882 883 $this->code .= $code; 884 } 885 886 /** 887 * check if readline support is enabled 888 * 889 * @return bool true if enabled, false otherwise 890 */ 891 public function hasReadline() { 892 return $this->have_readline; 893 } 894 895 /** 896 * get version of the class 897 * 898 * @return string version-string 899 */ 900 public function getVersion() { 901 return $this->version; 902 } 903 } 904 905 /** 906 * a readline completion callback 907 * 908 * @param string $str linebuffer 909 * @param integer $pos position in linebuffer 910 * @return array list of possible matches 911 */ 912 function __shell_readline_complete($str, $pos) { 913 $in = readline_info('line_buffer'); 914 915 /** 916 * parse the line-buffer backwards to see if we have a 917 * - constant 918 * - function 919 * - variable 920 */ 921 922 $m = array(); 923 924 if (preg_match('#\$([A-Za-z0-9_]+)->#', $in, $a)) { 925 /* check for $o->... */ 926 $name = $a[1]; 927 928 if (isset($GLOBALS[$name]) && is_object($GLOBALS[$name])) { 929 $c = get_class_methods($GLOBALS[$name]); 930 931 foreach ($c as $v) { 932 $m[] = $v.'('; 933 } 934 $c = get_class_vars(get_class($GLOBALS[$name])); 935 936 foreach ($c as $k => $v) { 937 $m[] = $k; 938 } 939 940 return $m; 941 } 942 } else if (preg_match('#\$([A-Za-z0-9_]+)\[([^\]]+)\]->#', $in, $a)) { 943 /* check for $o[...]->... */ 944 $name = $a[1]; 945 946 if (isset($GLOBALS[$name]) && 947 is_array($GLOBALS[$name]) && 948 isset($GLOBALS[$name][$a[2]])) { 949 950 $c = get_class_methods($GLOBALS[$name][$a[2]]); 951 952 foreach ($c as $v) { 953 $m[] = $v.'('; 954 } 955 $c = get_class_vars(get_class($GLOBALS[$name][$a[2]])); 956 957 foreach ($c as $k => $v) { 958 $m[] = $k; 959 } 960 return $m; 961 } 962 963 } else if (preg_match('#([A-Za-z0-9_]+)::#', $in, $a)) { 964 /* check for Class:: */ 965 $name = $a[1]; 966 967 if (class_exists($name, false)) { 968 $c = get_class_methods($name); 969 970 foreach ($c as $v) { 971 $m[] = sprintf('%s::%s(', $name, $v); 972 } 973 974 $cl = new ReflectionClass($name); 975 $c = $cl->getConstants(); 976 977 foreach ($c as $k => $v) { 978 $m[] = sprintf('%s::%s', $name, $k); 979 } 980 981 return $m; 982 } 983 } else if (preg_match('#\$([a-zA-Z]?[a-zA-Z0-9_]*)$#', $in)) { 984 $m = array_keys($GLOBALS); 985 986 return $m; 987 } else if (preg_match('#new #', $in)) { 988 $c = get_declared_classes(); 989 990 foreach ($c as $v) { 991 $m[] = $v.'('; 992 } 993 994 return $m; 995 } else if (preg_match('#^:set #', $in)) { 996 foreach (PHP_Shell_Options::getInstance()->getOptions() as $v) { 997 $m[] = $v; 998 } 999 1000 return $m; 1001 } 1002 1003 $f = get_defined_functions(); 1004 1005 foreach ($f['internal'] as $v) { 1006 $m[] = $v.'('; 1007 } 1008 1009 foreach ($f['user'] as $v) { 1010 $m[] = $v.'('; 1011 } 1012 1013 $c = get_declared_classes(); 1014 1015 foreach ($c as $v) { 1016 $m[] = $v.'::'; 1017 } 1018 1019 $c = get_defined_constants(); 1020 1021 foreach ($c as $k => $v) { 1022 $m[] = $k; 1023 } 1024 1025 /* taken from http://de3.php.net/manual/en/reserved.php */ 1026 $m[] = 'abstract'; 1027 $m[] = 'and'; 1028 $m[] = 'array('; 1029 $m[] = 'as'; 1030 $m[] = 'break'; 1031 $m[] = 'case'; 1032 $m[] = 'catch'; 1033 $m[] = 'class'; 1034 $m[] = 'const'; 1035 $m[] = 'continue'; 1036 # $m[] = 'declare'; 1037 $m[] = 'default'; 1038 $m[] = 'die('; 1039 $m[] = 'do'; 1040 $m[] = 'echo('; 1041 $m[] = 'else'; 1042 $m[] = 'elseif'; 1043 $m[] = 'empty('; 1044 # $m[] = 'enddeclare'; 1045 $m[] = 'eval('; 1046 $m[] = 'exception'; 1047 $m[] = 'extends'; 1048 $m[] = 'exit('; 1049 $m[] = 'extends'; 1050 $m[] = 'final'; 1051 $m[] = 'for ('; 1052 $m[] = 'foreach ('; 1053 $m[] = 'function'; 1054 $m[] = 'global'; 1055 $m[] = 'if'; 1056 $m[] = 'implements'; 1057 $m[] = 'include "'; 1058 $m[] = 'include_once "'; 1059 $m[] = 'interface'; 1060 $m[] = 'isset('; 1061 $m[] = 'list('; 1062 $m[] = 'new'; 1063 $m[] = 'or'; 1064 $m[] = 'print('; 1065 $m[] = 'private'; 1066 $m[] = 'protected'; 1067 $m[] = 'public'; 1068 $m[] = 'require "'; 1069 $m[] = 'require_once "'; 1070 $m[] = 'return'; 1071 $m[] = 'static'; 1072 $m[] = 'switch ('; 1073 $m[] = 'throw'; 1074 $m[] = 'try'; 1075 $m[] = 'unset('; 1076 # $m[] = 'use'; 1077 $m[] = 'var'; 1078 $m[] = 'while'; 1079 $m[] = 'xor'; 1080 $m[] = '__FILE__'; 1081 $m[] = '__FUNCTION__'; 1082 $m[] = '__CLASS__'; 1083 $m[] = '__LINE__'; 1084 $m[] = '__METHOD__'; 1085 1086 # printf("%s ... %s\n", $str, $pos); 1087 return $m; 1088 } 1089 1090
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 21:07:04 2007 | par Balluche grâce à PHPXref 0.7 |