From b3f02ce06d8841e5efb089168d8386ea096557ec Mon Sep 17 00:00:00 2001 From: zawz Date: Fri, 20 Nov 2020 22:19:28 +0100 Subject: [PATCH] Optimize var operations on get argument var definitions --- include/minimize.hpp | 17 ++-- include/parse.hpp | 4 + src/generate.cpp | 13 --- src/main.cpp | 4 +- src/minimize.cpp | 196 +++++++++++++++++++++++++++++-------------- src/parse.cpp | 13 --- 6 files changed, 149 insertions(+), 98 deletions(-) diff --git a/include/minimize.hpp b/include/minimize.hpp index 805c1b4..9c64dec 100644 --- a/include/minimize.hpp +++ b/include/minimize.hpp @@ -6,21 +6,26 @@ #include #include +typedef std::map countmap_t; + extern std::regex re_var_exclude; extern std::regex re_fct_exclude; +extern const std::regex regex_null; + #define RESERVED_VARIABLES "HOME", "PATH", "SHELL", "PWD", "OPTIND", "OPTARG" std::regex var_exclude_regex(std::string const& in); std::regex fct_exclude_regex(std::string const& in); -void list_vars(_obj* in, std::regex exclude); -void list_fcts(_obj* in, std::regex exclude); -void list_cmds(_obj* in, std::regex exclude); +void list_vars(_obj* in, std::regex const& exclude); +void list_fcts(_obj* in, std::regex const& exclude); +void list_cmds(_obj* in, std::regex const& exclude); -void minimize_var(_obj* in, std::regex exclude); -void minimize_fct(_obj* in, std::regex exclude); +void minimize_var(_obj* in, std::regex const& exclude); +void minimize_fct(_obj* in, std::regex const& exclude); -void delete_unused_fct(_obj* in, std::regex exclude); +void delete_unused_fct(_obj* in, std::regex const& exclude); +// void delete_unused_var(_obj* in, std::regex const& exclude); #endif //MINIMIZE_HPP diff --git a/include/parse.hpp b/include/parse.hpp index de5f722..b13b979 100644 --- a/include/parse.hpp +++ b/include/parse.hpp @@ -21,6 +21,10 @@ #define SPECIAL_VARS "!#*@$?" +inline bool is_num(char c) { return (c >= '0' && c <= '9'); } +inline bool is_alpha(char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } +inline bool is_alphanum(char c) { return is_alpha(c) || is_num(c); } + std::string import_file(std::string const& path); shmain* parse_text(const char* in, uint32_t size, std::string const& filename=""); diff --git a/src/generate.cpp b/src/generate.cpp index e665518..ee135ee 100644 --- a/src/generate.cpp +++ b/src/generate.cpp @@ -6,19 +6,6 @@ #include "options.hpp" #include "parse.hpp" -inline bool is_num(char c) -{ - return (c >= '0' && c <= '9'); -} -inline bool is_alpha(char c) -{ - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); -} -inline bool is_alphanum(char c) -{ - return is_alpha(c) || is_num(c); -} - bool is_sub_special_cmd(std::string in) { return in == "%include_sub" || in == "%resolve_sub"; diff --git a/src/main.cpp b/src/main.cpp index 6559e7a..ce2b52a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -160,9 +160,9 @@ int main(int argc, char* argv[]) if(options["list-var"]) list_vars(sh, re_var_exclude); else if(options["list-fct"]) - list_fcts(sh, re_var_exclude); + list_fcts(sh, re_fct_exclude); else if(options["list-cmd"]) - list_cmds(sh, re_var_exclude); + list_cmds(sh, regex_null); else if(is_exec) { ret = execute(sh, args); diff --git a/src/minimize.cpp b/src/minimize.cpp index 51ffbd5..bb7d709 100644 --- a/src/minimize.cpp +++ b/src/minimize.cpp @@ -11,6 +11,14 @@ std::regex re_var_exclude; std::regex re_fct_exclude; +const std::regex regex_null; + +countmap_t m_vars, m_vardefs, m_varcalls; +countmap_t m_fcts, m_cmds; +std::set m_excluded_var, m_excluded_fct, m_excluded_cmd; + +bool b_gotvar=false, b_gotfct=false, b_gotcmd=false; + std::vector get_list(std::string const& in) { return split(in, ", \t\n"); @@ -43,6 +51,20 @@ std::regex fct_exclude_regex(std::string const& in) return gen_regex_from_list(get_list(in)); } +bool is_varname(std::string const& in) +{ + if(in.size() <= 0 || !(is_alpha(in[0]) || in[0]== '_') ) + return false; + uint32_t i=1; + while(i cmd::arg_vars() { std::vector ret; @@ -57,16 +79,8 @@ std::vector cmd::arg_vars() arg* ta = args->args[i]; if(ta->sa.size() < 1 || ta->sa[0]->type != _obj::subarg_string) continue; - if(ta->sa.size() == 1) - { - if( std::regex_match(ta->sa[0]->generate(0), std::regex("[a-zA-Z_][0-9a-zA-Z_]*([=](.*)?)?") ) ) - ret.push_back(ta->sa[0]); - } - else if(ta->sa.size() > 1) - { - if( std::regex_match(ta->sa[0]->generate(0), std::regex("[a-zA-Z_][0-9a-zA-Z_]*=.*") ) ) - ret.push_back(ta->sa[0]); - } + if(ta->sa.size() >= 1 && is_varname(ta->sa[0]->generate(0))) + ret.push_back(ta->sa[0]); } } @@ -87,37 +101,35 @@ std::string get_varname(subarg* in) /** VAR RECURSE **/ -bool get_map_varname(_obj* in, std::map* variable_map) +bool get_var(_obj* in, countmap_t* defmap, countmap_t* callmap) { - if(variable_map == nullptr) - return false; switch(in->type) { case _obj::subarg_variable: { variable_subarg* t = dynamic_cast(in); - if(!variable_map->insert( std::make_pair(t->varname, 1) ).second) - (*variable_map)[t->varname]++; + if(!callmap->insert( std::make_pair(t->varname, 1) ).second) + (*callmap)[t->varname]++; }; break; case _obj::subarg_manipulation: { manipulation_subarg* t = dynamic_cast(in); - if(!variable_map->insert( std::make_pair(t->varname, 1) ).second) - (*variable_map)[t->varname]++; + if(!callmap->insert( std::make_pair(t->varname, 1) ).second) + (*callmap)[t->varname]++; }; break; case _obj::block_for: { for_block* t = dynamic_cast(in); - if(!variable_map->insert( std::make_pair(t->varname, 1) ).second) - (*variable_map)[t->varname]++; + if(!defmap->insert( std::make_pair(t->varname, 1) ).second) + (*defmap)[t->varname]++; }; break; case _obj::block_cmd: { cmd* t = dynamic_cast(in); for(auto it: t->var_assigns) - if(!variable_map->insert( std::make_pair(it.first, 1) ).second) - (*variable_map)[it.first]++; + if(!defmap->insert( std::make_pair(it.first, 1) ).second) + (*defmap)[it.first]++; for(auto it: t->arg_vars()) { std::string varname=get_varname(it); - if(!variable_map->insert( std::make_pair(varname, 1) ).second) - (*variable_map)[varname]++; + if(!defmap->insert( std::make_pair(varname, 1) ).second) + (*defmap)[varname]++; } }; break; default: break; @@ -176,7 +188,7 @@ bool replace_varname(_obj* in, std::map* varmap) /** FCT RECURSE **/ -bool get_map_cmd(_obj* in, std::map* all_cmds) +bool get_cmd(_obj* in, countmap_t* all_cmds) { switch(in->type) { @@ -191,7 +203,7 @@ bool get_map_cmd(_obj* in, std::map* all_cmds) return true; } -bool get_map_fctname(_obj* in, std::map* fct_map) +bool get_fct(_obj* in, countmap_t* fct_map) { switch(in->type) { @@ -296,7 +308,54 @@ std::string minimal_name(uint32_t n) } } -std::map gen_map(std::map const& vars, std::set excluded) +countmap_t combine_maps(countmap_t const& a, countmap_t const& b) +{ + countmap_t ret; + for(auto it: a) + { + if(!ret.insert( it ).second) + ret[it.first] += it.second; + } + for(auto it: b) + { + if(!ret.insert( it ).second) + ret[it.first] += it.second; + } + return ret; +} + +void varmap_get(_obj* in, std::regex const& exclude) +{ + if(!b_gotvar) + { + b_gotvar=true; + recurse(get_var, in, &m_vardefs, &m_varcalls); + m_vars = combine_maps(m_vardefs, m_varcalls); + m_excluded_var = prune_matching(m_vars, exclude); + } +} + +void fctmap_get(_obj* in, std::regex const& exclude) +{ + if(!b_gotfct) + { + b_gotfct=true; + recurse(get_fct, in, &m_fcts); + m_excluded_fct = prune_matching(m_fcts, exclude); + } +} + +void cmdmap_get(_obj* in, std::regex const& exclude) +{ + if(!b_gotcmd) + { + b_gotcmd=true; + recurse(get_cmd, in, &m_cmds); + m_excluded_fct = prune_matching(m_cmds, exclude); + } +} + +std::map gen_minimal_map(countmap_t const& vars, std::set excluded) { std::map ret; auto ordered = sort_by_value(vars); @@ -313,65 +372,71 @@ std::map gen_map(std::map const& return ret; } -void minimize_var(_obj* in, std::regex exclude) +void minimize_var(_obj* in, std::regex const& exclude) { - std::map vars; + // countmap_t vars; std::set excluded; std::map varmap; // get vars - recurse(get_map_varname, in, &vars); - // remove excluded - excluded = prune_matching(vars, exclude); + varmap_get(in, exclude); // create mapping - varmap=gen_map(vars, excluded); + varmap=gen_minimal_map(m_vars, m_excluded_var); // perform replace recurse(replace_varname, in, &varmap); } -void minimize_fct(_obj* in, std::regex exclude) +void minimize_fct(_obj* in, std::regex const& exclude) { - std::map fcts, cmdmap; + // countmap_t fcts, cmdmap; std::set allcmds, excluded; std::map fctmap; - // get fcts - recurse(get_map_fctname, in, &fcts); - // get cmds - recurse(get_map_cmd, in, &cmdmap); - allcmds=map_to_set(cmdmap); - // remove excluded - excluded = prune_matching(fcts, exclude); - // concatenate excluded to commands - concat_sets(allcmds, excluded); + // get fcts and cmds + fctmap_get(in, exclude); + cmdmap_get(in, regex_null); + // concatenate cmds and excluded commands + allcmds=map_to_set(m_cmds); + concat_sets(allcmds, m_excluded_fct); // create mapping - fctmap=gen_map(fcts, allcmds); + fctmap=gen_minimal_map(m_fcts, allcmds); // perform replace recurse(replace_fctname, in, &fctmap); } -void delete_unused_fct(_obj* in, std::regex exclude) +void delete_unused_fct(_obj* in, std::regex const& exclude) { - std::map fctmap, cmdmap; std::set unused; - // get fcts - recurse(get_map_fctname, in, &fctmap); - // get cmds - recurse(get_map_cmd, in, &cmdmap); - // remove excluded - prune_matching(fctmap, exclude); - for(auto it: fctmap) + // get fcts and cmds + fctmap_get(in, exclude); + cmdmap_get(in, regex_null); + // find unused fcts + for(auto it: m_fcts) { - if(cmdmap.find(it.first) == cmdmap.end()) + if(m_cmds.find(it.first) == m_cmds.end()) unused.insert(it.first); } + // perform deletion if(unused.size()>0) recurse(delete_fcts, in, &unused); } -void list_stuff(_obj* in, std::regex exclude, bool (&fct)(_obj*,std::map*) ) +void delete_unused_var(_obj* in, std::regex const& exclude) +{ + std::set unused; + // get fcts and cmds + varmap_get(in, exclude); + // find unused vars + for(auto it: m_vardefs) + { + if(m_varcalls.find(it.first) == m_varcalls.end()) + unused.insert(it.first); + } + // perform deletion + if(unused.size()>0) + recurse(delete_fcts, in, &unused); +} + +void list_map(countmap_t const& map) { - std::map map; - recurse(fct, in, &map); - prune_matching(map, exclude); uint32_t max=0; for(auto it: map) if(it.second > max) @@ -380,17 +445,20 @@ void list_stuff(_obj* in, std::regex exclude, bool (&fct)(_obj*,std::map= '0' && c <= '9'); -} -inline bool is_alpha(char c) -{ - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); -} -inline bool is_alphanum(char c) -{ - return is_alpha(c) || is_num(c); -} - bool valid_name(std::string const& str) { if(!is_alpha(str[0]) && str[0] != '_') return false;