From 04ef17151558db6c0cf1eb87a6dc68740b361afa Mon Sep 17 00:00:00 2001 From: zawz Date: Thu, 19 Aug 2021 17:48:46 +0200 Subject: [PATCH] optimize minify operations --- include/minify.hpp | 4 -- include/processing.hpp | 7 +++- src/main.cpp | 13 ++++-- src/minify.cpp | 90 ++++++++++++++++++++++++++++-------------- src/processing.cpp | 64 ++++++++++++++++++++++++++---- 5 files changed, 134 insertions(+), 44 deletions(-) diff --git a/include/minify.hpp b/include/minify.hpp index 124f2b0..b83bd5c 100644 --- a/include/minify.hpp +++ b/include/minify.hpp @@ -9,12 +9,8 @@ void minify_var(_obj* in, std::regex const& exclude); void minify_fct(_obj* in, std::regex const& exclude); -bool delete_unused_fct(_obj* in, std::regex const& exclude); -bool delete_unused_var(_obj* in, std::regex const& exclude); void delete_unused(_obj* in, std::regex const& var_exclude, std::regex const& fct_exclude); -void minify_quotes(_obj* in); - void minify_generic(_obj* in); #endif //MINIFY_HPP diff --git a/include/processing.hpp b/include/processing.hpp index dfa6158..d890f2b 100644 --- a/include/processing.hpp +++ b/include/processing.hpp @@ -35,7 +35,6 @@ countmap_t combine_common(countmap_t const& a, countmap_t const& b); /** map get functions (optimizations) **/ - // rescans void require_rescan_all(); void require_rescan_var(); @@ -46,6 +45,8 @@ void require_rescan_cmd(); void varmap_get(_obj* in, std::regex const& exclude); void fctmap_get(_obj* in, std::regex const& exclude); void cmdmap_get(_obj* in, std::regex const& exclude); +void fctcmdmap_get(_obj* in, std::regex const& exclude_fct, std::regex const& exclude_cmd); +void allmaps_get(_obj* in, std::regex const& exclude_var, std::regex const& exclude_fct, std::regex const& exclude_cmd); /** util functions **/ #ifdef DEBUG_MODE @@ -75,8 +76,12 @@ bool r_get_unsets(_obj* in, set_t* unsets); bool r_get_var(_obj* in, countmap_t* defmap, countmap_t* callmap); bool r_get_cmd(_obj* in, countmap_t* all_cmds); bool r_get_fct(_obj* in, countmap_t* fct_map); +bool r_get_fctcmd(_obj* in, countmap_t* all_cmds, countmap_t* fct_map); +bool r_get_all(_obj* in, countmap_t* defmap, countmap_t* callmap, countmap_t* all_cmds, countmap_t* fct_map); bool r_delete_fct(_obj* in, set_t* fcts); bool r_delete_var(_obj* in, set_t* vars); +bool r_delete_varfct(_obj* in, set_t* vars, set_t* fcts); +bool r_do_string_processor(_obj* in); /** Processing **/ diff --git a/src/main.cpp b/src/main.cpp index 8a4d169..c3ef500 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -198,13 +198,20 @@ int main(int argc, char* argv[]) if(options['m']) { opt_minify=true; - string_processors(sh); minify_generic(sh); } - if(options["minify-var"]) + if(options["minify-var"] && options["minify-fct"]) { + // optimization: get everything in one go + allmaps_get(sh, re_var_exclude, re_fct_exclude, regex_null); minify_var( sh, re_var_exclude ); - if(options["minify-fct"]) minify_fct( sh, re_fct_exclude ); + } + else if(options["minify-var"]) { + minify_var( sh, re_var_exclude ); + } + else if(options["minify-fct"]) { + minify_fct( sh, re_fct_exclude ); + } // other processing if(options["unset-var"]) add_unset_variables( sh, re_var_exclude ); diff --git a/src/minify.cpp b/src/minify.cpp index 8c09223..ebc1b90 100644 --- a/src/minify.cpp +++ b/src/minify.cpp @@ -224,11 +224,11 @@ bool r_minify_useless_quotes(_obj* in) redirect* t = dynamic_cast(in); if(t->here_document != nullptr) { - minify_quotes(t->target); + recurse(r_minify_useless_quotes, t->target); for(auto it: t->here_document->sa) { if(it->type!=_obj::subarg_string) { - minify_quotes(it); + recurse(r_minify_useless_quotes, it); } } // don't recurse on the rest @@ -324,8 +324,7 @@ void minify_fct(_obj* in, std::regex const& exclude) set_t excluded, unsets; strmap_t fctmap; // get fcts and cmds - fctmap_get(in, exclude); - cmdmap_get(in, regex_null); + fctcmdmap_get(in, exclude, regex_null); recurse(r_get_unsets, in, &unsets); // concatenate cmds, excluded and reserved excluded=map_to_set(m_cmds); @@ -346,8 +345,7 @@ bool delete_unused_fct(_obj* in, std::regex const& exclude) { set_t unused; // get fcts and cmds - fctmap_get(in, exclude); - cmdmap_get(in, regex_null); + fctcmdmap_get(in, exclude, regex_null); // find unused fcts for(auto it: m_fcts) { @@ -387,15 +385,35 @@ bool delete_unused_var(_obj* in, std::regex const& exclude) return false; } -void minify_quotes(_obj* in) +bool delete_unused_both(_obj* in, std::regex const& var_exclude, std::regex const& fct_exclude) { - recurse(r_minify_useless_quotes, in); + set_t unused_var, unused_fct; + // get all + allmaps_get(in, var_exclude, fct_exclude, regex_null); + // find unused + for(auto it: m_vardefs) + { + if(it.first!="" && m_varcalls.find(it.first) == m_varcalls.end()) + unused_var.insert(it.first); + } + for(auto it: m_fcts) + { + if(m_cmds.find(it.first) == m_cmds.end()) + unused_fct.insert(it.first); + } + if(unused_var.size()>0 || unused_fct.size()>0) + { + recurse(r_delete_varfct, in, &unused_var, &unused_fct); + require_rescan_all(); + return true; + } + return false; } void delete_unused(_obj* in, std::regex const& var_exclude, std::regex const& fct_exclude) { - while(delete_unused_fct(in, fct_exclude) || delete_unused_var(in, var_exclude)); - // keep deleting until both no function and no variables were deleted + while(delete_unused_both(in, var_exclude, fct_exclude)); + // keep deleting until both no deletion } @@ -424,7 +442,7 @@ bool r_minify_empty_manip(_obj* in) char c = ss->val[0]; // if its first would extend the var name: skip if(is_alphanum(c) || c == '_') - return true; + continue; } // if has no actual manipulation operation: set it to not manip if(ss->var->manip == nullptr || ss->var->manip->sa.size() == 0) @@ -468,39 +486,53 @@ bool r_minify_single_block(_obj* in) switch(in->type) { case _obj::_pipeline: { - pipeline* t = dynamic_cast(in); - for(uint32_t i=0; icmds.size(); i++) + bool has_operated=false; + do { - block* ret = do_one_minify_single_block(t->cmds[i]); - if(ret != nullptr) { - // concatenate redirects - for(uint32_t j=0; jcmds[i]->redirs.size(); j++) + // loop operating on current + // (if has operated, current object has changed) + has_operated=false; + pipeline* t = dynamic_cast(in); + for(uint32_t i=0; icmds.size(); i++) + { + block* ret = do_one_minify_single_block(t->cmds[i]); + if(ret != nullptr) { + // concatenate redirects + for(uint32_t j=0; jcmds[i]->redirs.size(); j++) ret->redirs.insert(ret->redirs.begin()+j, t->cmds[i]->redirs[j]); - // deindex - t->cmds[i]->redirs.resize(0); - if(t->cmds[i]->type == _obj::block_brace) + // deindex + t->cmds[i]->redirs.resize(0); + if(t->cmds[i]->type == _obj::block_brace) dynamic_cast(t->cmds[i])->lst->cls[0]->pls[0]->cmds[0] = nullptr; - else if(t->cmds[i]->type == _obj::block_subshell) + else if(t->cmds[i]->type == _obj::block_subshell) dynamic_cast(t->cmds[i])->lst->cls[0]->pls[0]->cmds[0] = nullptr; - // replace value - delete t->cmds[i]; - t->cmds[i] = ret; + // replace value + delete t->cmds[i]; + t->cmds[i] = ret; - recurse(r_minify_single_block, in); - return false; + has_operated=true; + } } } + while(has_operated); }; break; default: break; } return true; } +bool r_minify(_obj* in) +{ + r_minify_empty_manip(in); + r_minify_single_block(in); + r_minify_useless_quotes(in); + r_do_string_processor(in); + return true; +} + void minify_generic(_obj* in) { - recurse(r_minify_empty_manip, in); - recurse(r_minify_single_block, in); - minify_quotes(in); + recurse(r_minify, in); } diff --git a/src/processing.cpp b/src/processing.cpp index dac60cd..e047fc4 100644 --- a/src/processing.cpp +++ b/src/processing.cpp @@ -27,7 +27,6 @@ set_t m_excluded_var, m_excluded_fct, m_excluded_cmd; bool b_gotvar=false, b_gotfct=false, b_gotcmd=false; - // requires void require_rescan_var() @@ -214,6 +213,39 @@ void cmdmap_get(_obj* in, std::regex const& exclude) } } +void fctcmdmap_get(_obj* in, std::regex const& exclude_fct, std::regex const& exclude_cmd) +{ + if(!b_gotcmd && !b_gotfct) { + b_gotcmd = b_gotfct = true; + recurse(r_get_fctcmd, in, &m_cmds, &m_fcts); + m_excluded_fct = prune_matching(m_cmds, exclude_cmd); + concat_sets(m_excluded_fct, prune_matching(m_fcts, exclude_fct)); + } + else { + cmdmap_get(in, exclude_fct); + fctmap_get(in, exclude_cmd); + } +} + +void allmaps_get(_obj* in, std::regex const& exclude_var, std::regex const& exclude_fct, std::regex const& exclude_cmd) +{ + if(!b_gotvar && !b_gotcmd && !b_gotfct) + { + b_gotvar = b_gotcmd = b_gotfct = true; + recurse(r_get_all, in, &m_vardefs, &m_varcalls, &m_cmds, &m_fcts); + m_excluded_fct = prune_matching(m_cmds, exclude_cmd); + concat_sets(m_excluded_fct, prune_matching(m_fcts, exclude_fct)); + m_vars = combine_maps(m_vardefs, m_varcalls); + m_excluded_var = prune_matching(m_vars, exclude_var); + } + else + { + varmap_get(in, exclude_var); + cmdmap_get(in, exclude_fct); + fctmap_get(in, exclude_fct); + } +} + /** OUTPUT **/ void list_vars(_obj* in, std::regex const& exclude) @@ -324,11 +356,6 @@ bool r_get_unsets(_obj* in, set_t* unsets) cmd* t = dynamic_cast(in); if(t->is("unset")) { - for(auto it: t->var_assigns) - { - if(it.first != nullptr) - unsets->insert(it.first->varname); - } for(auto it: t->cmd_var_assigns) { if(it.first != nullptr) @@ -370,6 +397,21 @@ bool r_get_fct(_obj* in, countmap_t* fct_map) return true; } +bool r_get_fctcmd(_obj* in, countmap_t* all_cmds, countmap_t* fct_map) +{ + r_get_cmd(in, all_cmds); + r_get_fct(in, fct_map); + return true; +} + +bool r_get_all(_obj* in, countmap_t* defmap, countmap_t* callmap, countmap_t* all_cmds, countmap_t* fct_map) +{ + r_get_var(in, defmap, callmap); + r_get_cmd(in, all_cmds); + r_get_fct(in, fct_map); + return true; +} + // DELETE // bool r_delete_fct(_obj* in, set_t* fcts) @@ -461,6 +503,13 @@ bool r_delete_var(_obj* in, set_t* vars) return true; } +bool r_delete_varfct(_obj* in, set_t* vars, set_t* fcts) +{ + r_delete_var(in, vars); + r_delete_fct(in, fcts); + return true; +} + std::set find_lxsh_commands(shmain* sh) { std::set ret; @@ -533,7 +582,8 @@ bool r_do_string_processor(_obj* in) void string_processors(_obj* in) { - recurse(r_do_string_processor, in); + // recurse(r_do_string_processor, in); + ; } /** JSON **/