From faab8fcfaf34bcaaccf5ac604bfa47c34ea7d439 Mon Sep 17 00:00:00 2001 From: Pavel Shevaev Date: Wed, 18 May 2022 12:17:58 +0300 Subject: [PATCH] first commit --- bhl.inc.php | 424 ++++++++++++++++++++++++++++++++++++++++++++++++++ composer.json | 11 ++ 2 files changed, 435 insertions(+) create mode 100644 bhl.inc.php create mode 100644 composer.json diff --git a/bhl.inc.php b/bhl.inc.php new file mode 100644 index 0000000..959d74f --- /dev/null +++ b/bhl.inc.php @@ -0,0 +1,424 @@ + 'bhc'], function(array $args) +{ + global $GAME_ROOT; + + if(count($args) < 1) + { + echo "Usage: ./gamectl bhl_callstack \"\""; + return; + } + + $items = explode("\n", $args[0]); + + foreach($items as $item) + { + $item = trim($item); + if(!$item) + continue; + + if(preg_match('~(\d+)\s+\(\)\s+\(at (\d+):(\d+)\)~', $item, $m)) + { + $func_hash = (int)$m[1]; + $file_hash = (int)$m[2]; + $line_num = (int)$m[3]; + + $func_name = key(bhl_find_name_hash($func_hash)); + + $file_name = bhl_find_module($file_hash); + if(!$file_name) + $file_name = "?"; + else + $file_name = normalize_path($file_name, true); + + echo ($func_name ? $func_name : $func_hash) . "() in $file_name@$line_num \n"; + } + } +}); + +task('bhl_callstack_file', function(array $args) +{ + global $GAME_ROOT; + + if(count($args) < 1) + { + echo "Usage: ./gamectl bhl_callstack_file \"\""; + return; + } + + $callstack = ensure_read($args[0]); + run('bhl_callstack', [$callstack]); +}); + +function bhl_find_name_hash($hash) +{ + global $GAME_ROOT; + + $result = array(); + + $files = scan_files_rec(array(config_base_dir()), array('bhl')); + foreach($files as $file) + { + $cont = file_get_contents($file); + if(preg_match_all('/(\w+)/', $cont, $ms)) + { + foreach($ms[1] as $name) + { + $name = trim($name, '"'); + $var_hash = crc32($name) & 0xFFFFFFF; + if($var_hash === $hash) + { + if(!isset($result[$name])) + $result[$name] = array(); + $result[$name][$file] = true; + } + } + } + } + + return $result; +} + +task('bhl_find_module', function(array $args) +{ + if(count($args) < 1) + { + echo "Usage: ./gamectl bhl_find_module "; + return; + } + + $mod_id = (int)$args[0]; + $bhl_file = bhl_find_module($mod_id); + if($bhl_file) + echo "Found '$bhl_file'\n"; +}); + +function bhl_find_module($mod_id) +{ + global $GAME_ROOT; + + $files = scan_files_rec(array(config_base_dir()), array('.bhl')); + + $conf_dir = normalize_path(config_base_dir(), true); + + foreach($files as $bhl_file) + { + $module_path = str_replace($conf_dir, '', $bhl_file); + $module_path = ltrim(substr($module_path, 0, strlen($module_path)-4), '/'); + if(crc32($module_path) === $mod_id) + return $bhl_file; + } +} + +function bhl_result_file() +{ + global $GAME_ROOT; + return "$GAME_ROOT/build/ext_config/bhl.bytes"; +} + +function bhl_dir() +{ + global $GAME_ROOT; + return "$GAME_ROOT/composer/vendor/bit/bhl"; +} + +function bhl_shell($cmd, &$ret_var, &$ret_out) +{ + $prev_path = mono_try_override_path(); + + try + { + shell_try(bhl_dir()."/bhl $cmd", $ret_var, $ret_out); + } + finally + { + mono_try_restore_path($prev_path); + } +} + +function bhl_shell_ensure($cmd) +{ + bhl_shell($cmd, $ret_var, $ret_out); + if($ret_var !== 0) + throw new Exception("Error executing shell cmd: $ret_var"); +} + +function bhl_run($debug = true, $force = false, $check_deps = true, $exit_on_err = true) +{ + global $GAME_ROOT; + + $bhl_inc_dir = config_base_dir(); + + $all_files = scan_files_rec(array(config_base_dir()), array('.bhl')); + $res_file = bhl_result_file(); + + _bhl_shuffle_files($all_files); + + $res_file = bhl_result_file(); + $res = bhl_run_ex($bhl_inc_dir, $all_files, $res_file, $debug, $force, $check_deps, $exit_on_err); + + return $res; +} + +function _bhl_shuffle_files(&$files) +{ + shuffle($files); +} + +function bhl_run_ex($bhl_inc_dir, array $bhl_files, $result_file, $debug = true, $force = false, $check_deps = true, $exit_on_err = true) +{ + global $GAME_ROOT; + + ensure_mkdir("$GAME_ROOT/build"); + + $post_proc_file = "$GAME_ROOT/build/bhl.post.".crc32($result_file); + $err_file = "$GAME_ROOT/build/bhl.error"; + ensure_rm($err_file); + + $user_sources = array( + "$GAME_ROOT/unity/Assets/Scripts/bhl/register.cs", + "$GAME_ROOT/dll_src/bhl/autobind.cs", + "$GAME_ROOT/unity/Assets/Scripts/bhl/autobind.cs" + ); + + $postproc_sources = array( + "$GAME_ROOT/dll_src/bhl/postproc.cs", + "$GAME_ROOT/dll_src/bhl/result.cs" + ); + + $bhl_deps = $bhl_files; + $bhl_deps = array_merge($bhl_deps, $user_sources); + $bhl_deps = array_merge($bhl_deps, $postproc_sources); + $bhl_deps = array_merge($bhl_deps, scan_files_rec(array(bhl_dir()), array(".cs"))); + + if($force || need_to_regen($result_file, $bhl_deps) || need_to_regen($post_proc_file, $bhl_deps)) + { + $bhl_file_list = "$GAME_ROOT/build/bhl/file_list.tmp"; + ensure_write($bhl_file_list, implode("\n", $bhl_files)); + + putenv("POSTPROC_PROJ_ROOT=$GAME_ROOT"); + putenv("POSTPROC_RESULT=$post_proc_file"); + if($force) + putenv("POSTPROC_FORCE=1"); + + $bhl_dir = bhl_dir(); + + bhl_shell("run " . + "--user-sources=".implode(",",$user_sources)." --postproc-sources=".implode(",",$postproc_sources)." " . + "--dir=$bhl_inc_dir --files=$bhl_file_list --result=$result_file " . + "--cache_dir=$GAME_ROOT/build/bhl/ " . + "--error=$GAME_ROOT/build/bhl.error " . + "--deterministic " . + "--threads=" . (is_win() ? 1 : 4) . " " . + ($debug ? " -d" : "") . " " . + ($force ? " -C" : "") . " ". + (!$check_deps ? " -N" : "") . " ", + $ret_var, $ret_out + ); + + if($ret_var != 0) + { + bhl_handle_error_result($ret_out, $err_file, $exit_on_err); + if(!$exit_on_err) + return false; + } + else + echo "BHL BUNDLE: total " . kb_len(filesize($result_file)) . "\n"; + } + + @touch($result_file); + @touch($post_proc_file); + $res = bhl_ast_post_proc($result_file, $post_proc_file); + + return $res; +} + +function bhl_handle_error_result(array $ret_out, $err_file, $exit = true) +{ + if(!is_file($err_file)) + { + stderr("Something went wrong: " . (is_array($ret_out) ? implode("\n", $ret_out) : "????")); + if($exit) + exit(1); + } + + $err = file_get_contents($err_file); + $jerr = json_decode($err); + if(!$jerr) + { + stderr("Something went wrong, bhl error is in invalid format: $err"); + if($exit) + exit(1); + } + $file = $jerr->file; + + $err_line = null; + $err_row = null; + if(preg_match('~@\((\d+),(\d+)\)~', $jerr->error, $merr)) + { + $err_line = (int)$merr[1]; + $err_row = (int)$merr[2]; + } + + stderr("BHL ERROR: \n" . + $jerr->error . + //substr($jerr->error, 0, 500) . + " \nin '$file'\n"); + if($err_line !== null && $err_row !== null) + stderr(bhl_show_position($err_line, $err_row, file($file)) . "\n"); + if($exit) + exit(1); +} + +class BhlAstProcResult +{ + var $res_file; + var $func2assets_deep = array(); + var $func2refs_deep = array(); +} + +function bhl_ast_post_proc($res_file, $post_proc_file) +{ + $res = new BhlAstProcResult(); + $res->res_file = $res_file; + $data = config_msgpack_unpack(ensure_read($post_proc_file)); + if(!$data) + return $res; + + $func2assets = $data[0]; + foreach($func2assets as $item) + { + list($func1, $func2, $assets) = $item; + $func = ($func2 << 31) | $func1; + $res->func2assets_deep[$func] = array_flip($assets); + } + + $func2crefs = $data[1]; + foreach($func2crefs as $item) + { + list($func1, $func2, $crefs) = $item; + $func = ($func2 << 31) | $func1; + $res->func2refs_deep[$func] = array_flip($crefs); + } + + return $res; +} + +function bhl_clean() +{ + global $GAME_ROOT; + + $files = scan_files_rec(array(config_base_dir()), array('js', 'gen.bhl')); + foreach($files as $file) + { + $is_conf = strpos($file, '.gen.bhl') === false; + + if($is_conf) + { + //skipping .def.js files + if(strpos($file, '.def.js') !== false) + continue; + @touch($file); + } + else if(!$is_conf) + { + ensure_rm($file); + } + } + + bhl_clean_cache(); + + bhl_shell_ensure("clean"); +} + +function bhl_clean_cache() +{ + global $GAME_ROOT; + ensure_rm("$GAME_ROOT/build/bhl/"); +} + +function bhl_show_position($line, $row, array $lines) +{ + if($line < count($lines)) + { + $txt = $lines[$line-1]; + $c = str_repeat('-', $row); + return "{$txt}{$c}^"; + } + //weird special case + else if($line-1 == count($lines)) + { + $txt = $lines[count($lines)-1]; + $c = str_repeat('-', $row); + return "{$txt}{$c}^"; + } + else + return "???"; +} + +function bhl_get_past_input($c, $in, $context_chars) +{ + $past = substr($in, 0, $c+1); + return (strlen($past) > $context_chars ? '...' : '') . substr($past, -$context_chars); +} + +function bhl_get_upcoming_input($c, $in, $context_chars) +{ + $next = substr($in, $c+1); + return substr($next, 0, $context_chars) . (strlen($next) > $context_chars ? '...' : ''); +} + +function bhl_line_row_to_pos($file, $line, $row) +{ + $pos = 0; + $lines = file($file); + //something went wrong + if(count($lines) < $line) + return null; + for($i=0;$i<($line-1);++$i) + $pos += strlen($lines[$i]); + $pos += $row; + return $pos; +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..2a37f6e --- /dev/null +++ b/composer.json @@ -0,0 +1,11 @@ +{ + "name": "bit/taskman_bhl", + "description": "taskman bhl utils", + "homepage": "https://git.bit5.ru/composer/taskman_bhl", + "require": { + "php": ">=7.4" + }, + "autoload": { + "classmap": ["bhl.inc.php"] + } +}