#include "processing.hpp" #include #include "recursive.hpp" #include "parse.hpp" #include "util.hpp" // Global regex std::regex re_var_exclude; std::regex re_fct_exclude; const std::regex regex_null; // Object maps countmap_t m_vars, m_vardefs, m_varcalls; countmap_t m_fcts, m_cmds; 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() { b_gotvar = false; m_vars.clear(); m_vardefs.clear(); m_varcalls.clear(); m_excluded_var.clear(); } void require_rescan_fct() { b_gotcmd = false; m_fcts.clear(); m_excluded_fct.clear(); } void require_rescan_cmd() { b_gotfct = false; m_cmds.clear(); m_excluded_cmd.clear(); } void require_rescan_all() { require_rescan_var(); require_rescan_fct(); require_rescan_cmd(); } /** TOOLS **/ // type tools 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 list_map(countmap_t const& map) { uint32_t max=0; for(auto it: map) if(it.second > max) max=it.second; for(auto it: map) printf("%*d %s\n", (uint32_t)log10(max)+1, it.second, it.first.c_str()); } inline std::vector get_list(std::string const& in) { return split(in, ", \t\n"); } std::regex gen_regex_from_list(std::vector const& in) { std::string re; for(auto it: in) re += '('+it+")|"; if(re.size()>0) re.pop_back(); return std::regex(re); } std::vector gen_var_excludes(std::string const& in, bool include_reserved) { std::vector ret; if(include_reserved) { ret = {RESERVED_VARIABLES, strf("[0-9%s]", SPECIAL_VARS)}; } auto t = get_list(in); ret.insert(ret.end(), t.begin(), t.end()); return ret; } std::regex var_exclude_regex(std::string const& in, bool include_reserved) { return gen_regex_from_list(gen_var_excludes(in, include_reserved)); } std::regex fct_exclude_regex(std::string const& in) { return gen_regex_from_list(get_list(in)); } // Variable checks and extensions bool is_varname(std::string const& in) { if(in.size() <= 0 || !(is_alpha(in[0]) || in[0]== '_') ) return false; uint32_t i=1; while(isa.size() < 1 || in->sa[0]->type != _obj::subarg_string) return ""; std::string str = in->sa[0]->generate(0); if(in->sa.size() >= 1 && is_varname(str)) return get_varname(str); return ""; } bool cmd_is_argvar(std::string const& in) { return is_in_vector(in, posix_cmdvar) || is_in_vector(in, bash_cmdvar); } bool cmd::is_argvar() { return is_cmdvar; } bool cmd::is(std::string const& in) { return in == this->arg_string(0); } /** GETTERS **/ void varmap_get(_obj* in, std::regex const& exclude) { if(!b_gotvar) { b_gotvar=true; recurse(r_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(r_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(r_get_cmd, in, &m_cmds); m_excluded_fct = prune_matching(m_cmds, exclude); } } /** OUTPUT **/ void list_vars(_obj* in, std::regex const& exclude) { varmap_get(in, exclude); list_map(m_vars); } void list_var_defs(_obj* in, std::regex const& exclude) { varmap_get(in, exclude); list_map(m_vardefs); } void list_var_calls(_obj* in, std::regex const& exclude) { varmap_get(in, exclude); list_map(m_varcalls); } void list_fcts(_obj* in, std::regex const& exclude) { fctmap_get(in, exclude); list_map(m_fcts); } void list_cmds(_obj* in, std::regex const& exclude) { cmdmap_get(in, exclude); list_map(m_cmds); } /** FUNCTIONS **/ void add_unset_variables(shmain* sh, std::regex const& exclude) { varmap_get(sh, exclude); if(m_vars.size()>0) { cmd* unset_cmd = new cmd; unset_cmd->add(new arg("unset")); unset_cmd->is_cmdvar=true; for(auto it: m_vars) { unset_cmd->var_assigns.push_back(std::make_pair(new variable(it.first), nullptr)); } condlist* cl = new condlist(unset_cmd); sh->lst->cls.insert(sh->lst->cls.begin(), cl); } } /** RECURSIVES **/ // GET // bool r_get_var(_obj* in, countmap_t* defmap, countmap_t* callmap) { switch(in->type) { case _obj::_variable: { variable* t = dynamic_cast(in); if(t->definition) { if(!defmap->insert( std::make_pair(t->varname, 1) ).second) (*defmap)[t->varname]++; } else { if(!callmap->insert( std::make_pair(t->varname, 1) ).second) (*callmap)[t->varname]++; } }; break; default: break; } return true; } bool r_get_unsets(_obj* in, set_t* unsets) { switch(in->type) { case _obj::block_cmd: { cmd* t = dynamic_cast(in); if(t->is("unset")) { for(auto it: t->var_assigns) { if(it.first != nullptr) unsets->insert(it.first->varname); } } }; break; default: break; } return true; } bool r_get_cmd(_obj* in, countmap_t* all_cmds) { switch(in->type) { case _obj::block_cmd: { cmd* t = dynamic_cast(in); std::string cmdname = t->arg_string(0); if(cmdname != "" && !all_cmds->insert( std::make_pair(cmdname, 1) ).second) (*all_cmds)[cmdname]++; }; break; default: break; } return true; } bool r_get_fct(_obj* in, countmap_t* fct_map) { switch(in->type) { case _obj::block_function: { function* t = dynamic_cast(in); if(!fct_map->insert( std::make_pair(t->name, 1) ).second) (*fct_map)[t->name]++; }; break; default: break; } return true; } // DELETE // bool r_delete_fct(_obj* in, set_t* fcts) { switch(in->type) { case _obj::_list: { list* t = dynamic_cast(in); for(uint32_t i=0; icls.size(); i++) { block* tb = t->cls[i]->first_block(); if(tb != nullptr && tb->type == _obj::block_function) { function* fc = dynamic_cast(tb); if(fcts->find(fc->name)!=fcts->end()) { delete t->cls[i]; t->cls.erase(t->cls.begin()+i); i--; } } } } default: break; } return true; } bool r_delete_var(_obj* in, set_t* vars) { switch(in->type) { case _obj::_list: { list* t = dynamic_cast(in); for(uint32_t i=0; icls.size(); i++) { block* tb = t->cls[i]->first_block(); bool to_delete=false; bool has_deleted=false; if(tb != nullptr && tb->type == _obj::block_cmd) { cmd* c = dynamic_cast(tb); for(uint32_t j=0; jvar_assigns.size(); j++) { if( c->var_assigns[j].first != nullptr && vars->find(c->var_assigns[j].first->varname) != vars->end() ) { if(c->var_assigns[j].first != nullptr) delete c->var_assigns[j].first; if(c->var_assigns[j].second != nullptr) delete c->var_assigns[j].second; c->var_assigns.erase(c->var_assigns.begin()+j); has_deleted=true; j--; } } if(has_deleted && c->var_assigns.size()<=0 && (c->arglist_size()<=0 || c->is_cmdvar) ) to_delete=true; } if(to_delete) { delete t->cls[i]; t->cls.erase(t->cls.begin()+i); i--; } } } default: break; } return true; } std::string quote_string(std::string const& in) { return '"' + stringReplace(in, "\"", "\\\"") + '"'; } std::string gen_json(std::vector> const& vec) { std::string ret; for(auto it: vec) { ret += it.first + ":" + it.second + ','; } if(ret != "") ret.pop_back(); return "{" + ret + "}"; } std::string gen_json(std::vector const& vec) { std::string ret; for(auto it: vec) { ret += it + ','; } if(ret != "") ret.pop_back(); return "[" + ret + "]"; } std::string boolstring(bool in) { if(in) return "true"; else return "false"; } std::string gen_json_struc(_obj* o) { if(o==nullptr) return "{}"; std::vector> vec; switch(o->type) { case _obj::_variable : { variable* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("variable") ) ); vec.push_back(std::make_pair(quote_string("varname"), quote_string(t->varname))); vec.push_back(std::make_pair(quote_string("definition"), boolstring(t->definition))); vec.push_back(std::make_pair(quote_string("index"), gen_json_struc(t->index))); vec.push_back(std::make_pair(quote_string("is_manip"), boolstring(t->is_manip) ) ); vec.push_back(std::make_pair(quote_string("precedence"), boolstring(t->precedence) ) ); vec.push_back(std::make_pair(quote_string("manip"), gen_json_struc(t->manip) ) ); break; } case _obj::_redirect : { redirect* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("redirect") ) ); vec.push_back(std::make_pair(quote_string("op"), quote_string(t->op))); vec.push_back(std::make_pair(quote_string("target"), gen_json_struc(t->target))); break; } case _obj::_arg : { arg* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("arg") ) ); std::vector tvec; for(auto it: t->sa) tvec.push_back(gen_json_struc(it)); vec.push_back(std::make_pair(quote_string("sa"), gen_json(tvec))); break; } case _obj::_arglist : { arglist* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("arglist") ) ); std::vector tvec; for(auto it: t->args) tvec.push_back(gen_json_struc(it)); vec.push_back(std::make_pair(quote_string("args"), gen_json(tvec))); break; } case _obj::_pipeline : { pipeline* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("pipeline") ) ); vec.push_back(std::make_pair(quote_string("negated"), boolstring(t->negated) ) ); std::vector tvec; for(auto it: t->cmds) tvec.push_back(gen_json_struc(it)); vec.push_back(std::make_pair(quote_string("cmds"), gen_json(tvec))); break; } case _obj::_condlist : { condlist* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("condlist") ) ); vec.push_back(std::make_pair(quote_string("parallel"), boolstring(t->parallel) ) ); std::vector tvec; for(auto it: t->pls) tvec.push_back(gen_json_struc(it)); vec.push_back(std::make_pair(quote_string("pls"), gen_json(tvec))); std::vector ttvec; for(auto it: t->or_ops) { ttvec.push_back(boolstring(it)); } vec.push_back(std::make_pair(quote_string("or_ops"), gen_json(ttvec))); break; } case _obj::_list : { list* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("list") ) ); std::vector tvec; for(auto it: t->cls) tvec.push_back(gen_json_struc(it)); vec.push_back(std::make_pair(quote_string("cls"), gen_json(tvec))); break; } case _obj::block_subshell : { subshell* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("subshell") ) ); vec.push_back(std::make_pair(quote_string("lst"), gen_json_struc(t->lst))); std::vector tvec; for(auto it: t->redirs) tvec.push_back(gen_json_struc(it)); vec.push_back(std::make_pair(quote_string("redirs"), gen_json(tvec))); break; } case _obj::block_brace : { brace* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("brace") ) ); vec.push_back(std::make_pair(quote_string("lst"), gen_json_struc(t->lst))); std::vector tvec; for(auto it: t->redirs) tvec.push_back(gen_json_struc(it)); vec.push_back(std::make_pair(quote_string("redirs"), gen_json(tvec))); break; } case _obj::block_main : { shmain* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("main") ) ); vec.push_back(std::make_pair(quote_string("shebang"), quote_string(t->shebang) ) ); vec.push_back(std::make_pair(quote_string("lst"), gen_json_struc(t->lst))); std::vector tvec; for(auto it: t->redirs) tvec.push_back(gen_json_struc(it)); vec.push_back(std::make_pair(quote_string("redirs"), gen_json(tvec))); break; } case _obj::block_function : { function* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("function") ) ); vec.push_back(std::make_pair(quote_string("name"), quote_string(t->name) ) ); vec.push_back(std::make_pair(quote_string("lst"), gen_json_struc(t->lst))); std::vector tvec; for(auto it: t->redirs) tvec.push_back(gen_json_struc(it)); vec.push_back(std::make_pair(quote_string("redirs"), gen_json(tvec))); break; } case _obj::block_cmd : { cmd* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("cmd") ) ); vec.push_back(std::make_pair(quote_string("args"), gen_json_struc(t->args))); vec.push_back(std::make_pair(quote_string("is_cmdvar"), boolstring(t->is_cmdvar))); std::vector aa; for(auto it: t->var_assigns) { std::vector> ttvec; ttvec.push_back( std::make_pair(quote_string("var"), gen_json_struc(it.first)) ); ttvec.push_back( std::make_pair(quote_string("value"), gen_json_struc(it.second)) ); aa.push_back(gen_json(ttvec)); } vec.push_back(std::make_pair( quote_string("var_assigns"), gen_json(aa))); std::vector tvec; for(auto it: t->redirs) tvec.push_back(gen_json_struc(it)); vec.push_back(std::make_pair(quote_string("redirs"), gen_json(tvec))); break; } case _obj::block_case : { case_block* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("case") ) ); vec.push_back(std::make_pair(quote_string("carg"), gen_json_struc(t->carg))); // [ {matchers:[], exec:{}} ] // cases std::vector tt; for(auto sc: t->cases) { std::vector> onecase; std::vector matchers; for(auto it: sc.first) matchers.push_back(gen_json_struc(it)); onecase.push_back( std::make_pair(quote_string("matcher"), gen_json(matchers)) ); onecase.push_back( std::make_pair(quote_string("execution"), gen_json_struc(sc.second)) ); tt.push_back(gen_json(onecase)); } vec.push_back( std::make_pair(quote_string("cases"),gen_json(tt)) ); std::vector tvec; for(auto it: t->redirs) tvec.push_back(gen_json_struc(it)); vec.push_back(std::make_pair(quote_string("redirs"), gen_json(tvec))); break; } case _obj::block_if : { if_block* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("if") ) ); std::vector condblocks; // ifs for(auto sc: t->blocks) { std::vector > one_cond; one_cond.push_back(std::make_pair(quote_string("condition"), gen_json_struc(sc.first) ) ); one_cond.push_back(std::make_pair(quote_string("execution"), gen_json_struc(sc.second) ) ); condblocks.push_back(gen_json(one_cond)); } vec.push_back( std::make_pair(quote_string("blocks"), gen_json(condblocks)) ); // else vec.push_back(std::make_pair(quote_string("else_lst"), gen_json_struc(t->else_lst))); std::vector tvec; for(auto it: t->redirs) tvec.push_back(gen_json_struc(it)); vec.push_back(std::make_pair(quote_string("redirs"), gen_json(tvec))); break; } case _obj::block_for : { for_block* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("for") ) ); vec.push_back(std::make_pair(quote_string("var"), gen_json_struc(t->var))); vec.push_back(std::make_pair(quote_string("iter"), gen_json_struc(t->iter))); vec.push_back(std::make_pair(quote_string("ops"), gen_json_struc(t->ops))); std::vector tvec; for(auto it: t->redirs) tvec.push_back(gen_json_struc(it)); vec.push_back(std::make_pair(quote_string("redirs"), gen_json(tvec))); break; } case _obj::block_while : { while_block* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("while") ) ); vec.push_back(std::make_pair(quote_string("cond"), gen_json_struc(t->cond) ) ); vec.push_back(std::make_pair(quote_string("ops"), gen_json_struc(t->ops) ) ); std::vector tvec; for(auto it: t->redirs) tvec.push_back(gen_json_struc(it)); vec.push_back(std::make_pair(quote_string("redirs"), gen_json(tvec))); break; } case _obj::subarg_variable : { variable_subarg* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("subarg_variable") ) ); vec.push_back(std::make_pair(quote_string("var"), gen_json_struc(t->var) ) ); break; } case _obj::subarg_subshell : { subshell_subarg* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("subarg_subshell") ) ); vec.push_back(std::make_pair(quote_string("sbsh"), gen_json_struc(t->sbsh) ) ); break; } case _obj::subarg_procsub : { procsub_subarg* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("subarg_procsub") ) ); vec.push_back(std::make_pair(quote_string("is_output"), boolstring(t->is_output) ) ); vec.push_back(std::make_pair(quote_string("sbsh"), gen_json_struc(t->sbsh) ) ); break; } case _obj::subarg_arithmetic : { arithmetic_subarg* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("subarg_arithmetic") ) ); vec.push_back(std::make_pair(quote_string("arith"), gen_json_struc(t->arith) ) ); break; } case _obj::subarg_string : { string_subarg* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("subarg_string") ) ); vec.push_back(std::make_pair(quote_string("val"), quote_string(t->val) ) ); break; } case _obj::arithmetic_variable : { variable_arithmetic* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("arithmetic_variable") ) ); vec.push_back(std::make_pair(quote_string("var"), gen_json_struc(t->var) ) ); break; } case _obj::arithmetic_subshell : { subshell_arithmetic* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("arithmetic_subshell") ) ); vec.push_back(std::make_pair(quote_string("sbsh"), gen_json_struc(t->sbsh) ) ); break; } case _obj::arithmetic_operation : { operation_arithmetic* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("arithmetic_operation") ) ); vec.push_back(std::make_pair(quote_string("val1"), gen_json_struc(t->val1) ) ); vec.push_back(std::make_pair(quote_string("val2"), gen_json_struc(t->val2) ) ); break; } case _obj::arithmetic_parenthesis : { parenthesis_arithmetic* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("arithmetic_parenthesis") ) ); vec.push_back(std::make_pair(quote_string("val"), gen_json_struc(t->val) ) ); break; } case _obj::arithmetic_number : { number_arithmetic* t = dynamic_cast(o); vec.push_back(std::make_pair(quote_string("type"), quote_string("arithmetic_number") ) ); vec.push_back(std::make_pair(quote_string("val"), quote_string(t->val) ) ); break; } } return gen_json(vec); }