3v4l.org

run code in 300+ PHP versions simultaneously
<?php header("content-type: text/plain"); error_reporting(E_ALL); $var='derp global $var...'; function hhb_var_dump() { //<changelog> //version 5 ( 1370984700423 ) //v5, fixed warnings on PHP < 5.0.2 (PHP_EOL not defined) (although we do not undefine("PHP_EOL") .. not sure how to do that :( ), //also we can use xdebug_var_dump when available now. tested working with 5.0.0 to 5.5.0beta2 (thanks to http://viper-7.com and http://3v4l.org ) //and fixed a (corner-case) bug with "0" (empty() considders string("0") to be empty, this caused a bug in sourcecode analyze) //v4, now (tries to) tell you the source code that lead to the variables //v3, HHB_VAR_DUMP_START and HHB_VAR_DUMP_END . //v2, now compat with.. PHP5.0 + i think? tested down to 5.2.17 (previously only 5.4.0+ worked) //</changelog> //<settings> $settings=array(); if(!defined('PHP_EOL')){//for PHP <5.0.2 $we_defined_PHP_EOL=true; define('PHP_EOL',"\n"); } $settings['debug_hhb_var_dump'] = false; //if true, may throw exceptions on errors.. $settings['use_xdebug_var_dump']=true;//try to use xdebug_var_dump (instead of var_dump) if available? $settings['analyze_sourcecode'] = true; //false to disable the source code analyze stuff. //(it will fallback to making $settings['analyze_sourcecode']=false, if it fail to analyze the code, anyway..) $settings['hhb_var_dump_prepend'] = 'HHB_VAR_DUMP_START'.PHP_EOL; $settings['hhb_var_dump_append'] = 'HHB_VAR_DUMP_END'.PHP_EOL; //</settings> $settings['use_xdebug_var_dump']=($settings['use_xdebug_var_dump'] && is_callable("xdebug_var_dump")); $argv = func_get_args(); $argc = count($argv, COUNT_NORMAL); if (version_compare(PHP_VERSION, '5.4.0', '>=')) { $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1); } else if (version_compare(PHP_VERSION, '5.3.6', '>=')) { $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); } else if (version_compare(PHP_VERSION, '5.2.5', '>=')) { $bt = debug_backtrace(false); } else { $bt = debug_backtrace(); }; $analyze_sourcecode = $settings['analyze_sourcecode']; //later, $analyze_sourcecode will be compared with $config['analyze_sourcecode'] //to determine if the reason was an error analyzing, or if it was disabled.. $bt = $bt[0]; //<analyzeSourceCode> if ($analyze_sourcecode) { $argvSourceCode = array(0 => 'ignore [0]...'); try { if (version_compare(PHP_VERSION, '5.2.2', '<')) { throw new Exception("PHP version is <5.2.2 .. see token_get_all changelog.."); }; $xsource = file_get_contents($bt['file']); if (empty($xsource)) { throw new Exception('cant get the source of '.$bt['file']); }; $xsource.= '<?php ignore_this_hhb_var_dump_workaround();'; //workaround, making sure that at least 1 token is an array, and has the $tok[2] >= line of hhb_var_dump $xTokenArray = token_get_all($xsource); //<trim$xTokenArray> $tmpstr=''; $tmpUnsetKeyArray = array(); ForEach($xTokenArray as $xKey => $xToken) { if (is_array($xToken)) { $tmpstr = trim($xToken[1]); if (empty($tmpstr) && $tmpstr!=='0'/*string("0") is considered "empty" -.-*/) { $tmpUnsetKeyArray[] = $xKey; continue; }; switch ($xToken[0]) { case T_COMMENT: case T_DOC_COMMENT: //T_ML_COMMENT in PHP4 -.- case T_INLINE_HTML: { $tmpUnsetKeyArray[] = $xKey; continue; }; default: { continue; } } } else if (is_string($xToken)) { $tmpstr = trim($xToken); if (empty($tmpstr) && $tmpstr!=='0'/*string("0") is considered "empty" -.-*/) { $tmpUnsetKeyArray[] = $xKey; }; continue; } else { //should be unreachable.. //failed both is_array() and is_string() ??? throw new LogicException('Impossible! $xToken fails both is_array() and is_string() !! .. '); }; }; ForEach($tmpUnsetKeyArray as $toUnset) { unset($xTokenArray[$toUnset]); }; $xTokenArray = array_values($xTokenArray); //fixing the keys.. //die(var_dump('die(var_dump(...)) in '.__FILE__.':'.__LINE__,'before:',count(token_get_all($xsource),COUNT_NORMAL),'after',count($xTokenArray,COUNT_NORMAL))); unset($tmpstr,$xKey, $xToken, $toUnset, $tmpUnsetKeyArray); //</trim$xTokenArray> $firstInterestingLineTokenKey = -1; $lastInterestingLineTokenKey = -1; //<find$lastInterestingLineTokenKey> ForEach($xTokenArray as $xKey => $xToken) { if (!is_array($xToken) || !array_key_exists(2,$xToken) || !is_integer($xToken[2]) || $xToken[2] < $bt['line']) continue; $tmpkey = $xKey; //we don't got what we want yet.. while (true) { if (!array_key_exists($tmpkey, $xTokenArray)) { throw new Exception('1unable to find $lastInterestingLineTokenKey !'); }; if ($xTokenArray[$tmpkey] === ';') { //var_dump(__LINE__.":SUCCESS WITH",$tmpkey,$xTokenArray[$tmpkey]); $lastInterestingLineTokenKey = $tmpkey; break; } //var_dump(__LINE__.":FAIL WITH ",$tmpkey,$xTokenArray[$tmpkey]); //if $xTokenArray has >=PHP_INT_MAX keys, we don't want an infinite loop, do we? ;p //i wonder how much memory that would require though.. over-engineering, err, time-wasting, ftw? if ($tmpkey >= PHP_INT_MAX) { throw new Exception('2unable to find $lastIntperestingLineTokenKey ! (PHP_INT_MAX reached without finding ";"...)'); }; ++$tmpkey; } break; }; if ($lastInterestingLineTokenKey <= -1) { throw new Exception('3unable to find $lastInterestingLineTokenKey !'); }; unset($xKey,$xToken,$tmpkey); //</find$lastInterestingLineTokenKey> //<find$firstInterestingLineTokenKey> //now work ourselves backwards from $lastInterestingLineTokenKey to the first token where $xTokenArray[$tmpi][1] == "hhb_var_dump" //i doubt this is fool-proof but.. cant think of a better way (in userland, anyway) atm.. $tmpi = $lastInterestingLineTokenKey; do { if (array_key_exists($tmpi, $xTokenArray) && is_array($xTokenArray[$tmpi]) && array_key_exists(1, $xTokenArray[$tmpi]) && is_string($xTokenArray[$tmpi][1]) && strcasecmp($xTokenArray[$tmpi][1], $bt['function']) === 0) { //var_dump(__LINE__."SUCCESS WITH",$tmpi,$xTokenArray[$tmpi]); if (!array_key_exists($tmpi + 2, $xTokenArray)) { //+2 because [0] is (or should be) "hhb_var_dump" and [1] is (or should be) "(" throw new Exception('1unable to find the $firstInterestingLineTokenKey...'); }; $firstInterestingLineTokenKey = $tmpi + 2; break; /**/ }; //var_dump(__LINE__."FAIL WITH ",$tmpi,$xTokenArray[$tmpi]); --$tmpi; } while (-1 < $tmpi); //die(var_dump('die(var_dump(...)) in '.__FILE__.':'.__LINE__,$tmpi)); if ($firstInterestingLineTokenKey <= -1) { throw new Exception('2unable to find the $firstInterestingLineTokenKey...'); }; unset($tmpi); //Note: $lastInterestingLineTokeyKey is likely to contain more stuff than only the stuff we want.. //</find$firstInterestingLineTokenKey> //<rebuildInterestingSourceCode> //ok, now we have $firstInterestingLineTokenKey and $lastInterestingLineTokenKey.... $interestingTokensArray = array_slice($xTokenArray, $firstInterestingLineTokenKey, (($lastInterestingLineTokenKey - $firstInterestingLineTokenKey) + 1)); unset($addUntil, $tmpi, $tmpstr,$tmpi,$argvsourcestr, $tmpkey,$xTokenKey,$xToken); $addUntil = array(); $tmpi = 0; $tmpstr = ""; $tmpkey = ""; $argvsourcestr = ""; //$argvSourceCode[X]='source code..'; ForEach($interestingTokensArray as $xTokenKey => $xToken) { if (is_array($xToken)) { $tmpstr = $xToken[1]; //var_dump($xToken[1]); } else if (is_string($xToken)) { $tmpstr = $xToken; //var_dump($xToken); } else { /*should never reach this */ throw new LogicException('Impossible situation? $xToken fails is_array() and fails is_string() ...'); }; $argvsourcestr.= $tmpstr; if ($xToken === '(') { $addUntil[] = ')'; continue; }; if ($xToken === ')') { if (false === ($tmpkey = array_search(')', $addUntil, false))) { $argvSourceCode[] = substr($argvsourcestr, 0, -1); //-1 is to strip the ")" if (count($argvSourceCode, COUNT_NORMAL) - 1 === $argc) /*-1 because $argvSourceCode[0] is bullshit*/ { break; /*We read em all! :D (.. i hope)*/ }; /*else... oh crap*/ throw new Exception('failed to read source code of (what i think is) argv['.count($argvSourceCode, COUNT_NORMAL).'] ! sorry..'); } unset($addUntil[$tmpkey]); continue; } if (empty($addUntil) && $xToken === ','){ $argvSourceCode[] = substr($argvsourcestr, 0, -1); //-1 is to strip the comma $argvsourcestr = ""; }; }; //die(var_dump('die(var_dump(...)) in '.__FILE__.':'.__LINE__, //$firstInterestingLineTokenKey,$lastInterestingLineTokenKey,$interestingTokensArray,$tmpstr //$argvSourceCode)); if (count($argvSourceCode, COUNT_NORMAL) - 1 != $argc) /*-1 because $argvSourceCode[0] is bullshit*/ { throw new Exception('failed to read source code of all the arguments! (and idk which ones i missed)! sorry..'); }; //</rebuildInterestingSourceCode> } catch (Exception $ex) { $argvSourceCode = array(); //clear it //TODO: failed to read source code //die("TODO N STUFF..".__FILE__.__LINE__); $analyze_sourcecode = false; //ERROR.. if ($settings['debug_hhb_var_dump']) { throw $ex; } else {/*exception ignored, continue as normal without $analyze_sourcecode */}; } unset($xsource, $xToken, $xTokenArray, $firstInterestingLineTokenKey, $lastInterestingLineTokenKey, $xTokenKey, $tmpi, $tmpkey,$argvsourcestr); }; //</analyzeSourceCode> $msg = $settings['hhb_var_dump_prepend']; if ($analyze_sourcecode != $settings['analyze_sourcecode']) { $msg.= ' (PS: some error analyzing source code)'.PHP_EOL; }; $msg.= 'in "'.$bt['file']. '": on line "'.$bt['line']. '": '.$argc. ' variable'.($argc === 1 ? '' : 's') //because over-engineering ftw? .PHP_EOL; if ($analyze_sourcecode) { $msg.= ' hhb_var_dump('; $msg.= implode(",", array_slice($argvSourceCode, 1));//$argvSourceCode[0] is bullshit. $msg.= ')'.PHP_EOL; } //array_unshift($bt,$msg); echo $msg; $i = 0; foreach($argv as &$val) { echo 'argv['.++$i.']'; if ($analyze_sourcecode) { echo ' >>>'.$argvSourceCode[$i].'<<<'; } echo ':'; if ($settings['use_xdebug_var_dump']) { xdebug_var_dump($val); } else { var_dump($val); }; } echo $settings['hhb_var_dump_append']; //call_user_func_array("var_dump",$args); } function shutdownf(){ global $starttime; //echo 'time used: ',microtime(true)-$starttime; } function f(){ return 'f() returns lol n stuff :D'; } register_shutdown_function("shutdownf"); $starttime=microtime(true); hhb_var_dump ( $var,'lol',array(array(array('',100)),NULL),"",f('', 'break(break me!!) break me!', 100, NULL ,array(array( '',100)) ),NULL,"",1337, 0 , (1?true:false) ,(1) && true );

preferences:
35.01 ms | 402 KiB | 5 Q