diff --git a/include/processing.hpp b/include/processing.hpp index 759a253..14e8904 100644 --- a/include/processing.hpp +++ b/include/processing.hpp @@ -21,11 +21,15 @@ extern std::regex re_var_exclude; extern std::regex re_fct_exclude; extern const std::regex regex_null; +// globals +extern const std::vector argvar_cmds; + // Object maps (optimizations) extern countmap_t m_vars, m_vardefs, m_varcalls; extern countmap_t m_fcts, m_cmds; extern set_t m_excluded_var, m_excluded_fct, m_excluded_cmd; + extern bool b_gotvar, b_gotfct, b_gotcmd; /** map get functions (optimizations) **/ diff --git a/include/struc.hpp b/include/struc.hpp index f58589c..49f1f87 100644 --- a/include/struc.hpp +++ b/include/struc.hpp @@ -115,6 +115,12 @@ public: void set(std::string const& str); + void insert(uint32_t i, subarg* val); + void insert(uint32_t i, arg const& a); + + inline void add(subarg* in) { sa.push_back(in); } + inline size_t size() { return sa.size(); } + std::vector sa; // return if is a string and only one subarg @@ -134,14 +140,15 @@ public: arglist(arg* in) { type=_obj::_arglist; this->add(in); } ~arglist() { for( auto it: args ) delete it; } inline void add(arg* in) { args.push_back(in); } - inline void push_back(arg* in) { args.push_back(in); } std::vector args; std::vector strargs(uint32_t start); - inline uint64_t size() { return args.size(); } - inline arg* operator[](uint32_t i) { return args[i]; } + void insert(uint32_t i, arg* val); + void insert(uint32_t i, arglist const& lst); + + inline size_t size() { return args.size(); } std::string generate(int ind); }; @@ -205,6 +212,7 @@ public: bool parallel; // & at the end void add(pipeline* pl, bool or_op=false); + // don't push_back here, use add() instead std::vector pls; std::vector or_ops; // size of 1 less than pls, defines separator between pipelines @@ -227,7 +235,7 @@ public: ~list() { for(auto it: cls) delete it; } std::vector cls; - void add(condlist* in) { cls.push_back(in); } + inline void add(condlist* in) { cls.push_back(in); } condlist* last_cond() { return cls[cls.size()-1]; } @@ -235,7 +243,6 @@ public: void insert(uint32_t i, list const& lst); size_t size() { return cls.size(); } - condlist* operator[](uint32_t i) { return cls[i]; } std::string generate(int ind, bool first_indent); std::string generate(int ind) { return this->generate(ind, true); } diff --git a/src/debashify.cpp b/src/debashify.cpp index 1e44fe9..8fb1388 100644 --- a/src/debashify.cpp +++ b/src/debashify.cpp @@ -5,17 +5,39 @@ #include "parse.hpp" #include "struc_helper.hpp" -bool debashify_replace_bashtest(cmd* in) +bool debashify_bashtest(cmd* in) { if(in->firstarg_string() == "[[") - throw std::runtime_error("Debashify on '[[ ]]' not implemented yet"); + throw std::runtime_error("Cannot debashify '[[ ]]'"); return false; } +bool debashify_declare(cmd* in) +{ + if(in->firstarg_string() == "declare") + throw std::runtime_error("Cannot debashify 'declare'"); + return false; +} + +bool debashify_array_def(cmd* in) +{ + for(auto it: in->var_assigns) + { + if(it.second->size()>0 && it.second->sa[0]->type == _obj::subarg_string && it.second->sa[0]->generate(0) == "(") + throw std::runtime_error("Cannot debashify VAR=() variable arrays"); + } + return false; +} + +bool debashify_herestring(pipeline* pl) +{ + return false; +} + // replace &>, &>> and >&: // add 2>&1 as redirect -bool debashify_replace_combined_redirects(block* in) +bool debashify_combined_redirects(block* in) { bool has_replaced=false; @@ -46,7 +68,7 @@ bool debashify_replace_combined_redirects(block* in) // replace <<< and // <<< : TODO -bool debashify_replace_extended_redirects(pipeline* in) +bool debashify_extended_redirects(pipeline* in) { return false; } @@ -70,7 +92,7 @@ TO: CMD "$fifoN" wait "$jobN" */ -bool debashify_replace_procsub(list* lst) +bool debashify_procsub(list* lst) { bool has_replaced=false; for(uint32_t li=0; licls.size(); li++) @@ -88,7 +110,7 @@ bool debashify_replace_procsub(list* lst) { for(auto ait: t->args->args) { - if(ait->sa.size() == 1 && ait->sa[0]->type == _obj::subarg_procsub) + if(ait->size() == 1 && ait->sa[0]->type == _obj::subarg_procsub) { procsub_subarg* st = dynamic_cast(ait->sa[0]); affected_args.push_back( std::make_pair(ait, st->is_output) ); @@ -135,8 +157,8 @@ bool debashify_replace_procsub(list* lst) // replace the arg delete affected_args[i].first->sa[0]; affected_args[i].first->sa[0] = new string_subarg("\""); - affected_args[i].first->sa.push_back( new variable_subarg(strf("__lxshfifo%u", i)) ); - affected_args[i].first->sa.push_back( new string_subarg("\"") ); + affected_args[i].first->add( new variable_subarg(strf("__lxshfifo%u", i)) ); + affected_args[i].first->add( new string_subarg("\"") ); } lst->insert(li, *lst_insert ); li+= lst_insert->size(); @@ -162,45 +184,47 @@ bool r_debashify(_obj* o, bool* need_random_func) { case _obj::_list: { list* t = dynamic_cast(o); - if(debashify_replace_procsub(t)) + if(debashify_procsub(t)) *need_random_func = true; } break; - case _obj::block_subshell: { - subshell* t = dynamic_cast(o); - debashify_replace_combined_redirects(t); - } break; - case _obj::block_brace: { - brace* t = dynamic_cast(o); - debashify_replace_combined_redirects(t); - } break; - case _obj::block_main: { - shmain* t = dynamic_cast(o); - debashify_replace_combined_redirects(t); - } break; case _obj::block_cmd: { cmd* t = dynamic_cast(o); - debashify_replace_combined_redirects(t); - debashify_replace_bashtest(t); + debashify_combined_redirects(t); + debashify_bashtest(t); + debashify_declare(t); + debashify_array_def(t); + } break; + case _obj::block_subshell: { + subshell* t = dynamic_cast(o); + debashify_combined_redirects(t); + } break; + case _obj::block_brace: { + brace* t = dynamic_cast(o); + debashify_combined_redirects(t); + } break; + case _obj::block_main: { + shmain* t = dynamic_cast(o); + debashify_combined_redirects(t); } break; case _obj::block_function: { function* t = dynamic_cast(o); - debashify_replace_combined_redirects(t); + debashify_combined_redirects(t); } break; case _obj::block_case: { case_block* t = dynamic_cast(o); - debashify_replace_combined_redirects(t); + debashify_combined_redirects(t); } break; case _obj::block_if: { if_block* t = dynamic_cast(o); - debashify_replace_combined_redirects(t); + debashify_combined_redirects(t); } break; case _obj::block_while: { while_block* t = dynamic_cast(o); - debashify_replace_combined_redirects(t); + debashify_combined_redirects(t); } break; case _obj::block_for: { for_block* t = dynamic_cast(o); - debashify_replace_combined_redirects(t); + debashify_combined_redirects(t); } break; default: break; } diff --git a/src/parse.cpp b/src/parse.cpp index 4a9e710..d96b9c8 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -249,10 +249,10 @@ std::pair parse_arg(const char* in, uint32_t size, uint32_t star // add previous subarg std::string tmpstr=std::string(in+j, i-j); if(tmpstr!="") - ret->sa.push_back(new string_subarg(tmpstr)); + ret->add(new string_subarg(tmpstr)); // get arithmetic auto r=parse_arithmetic(in, size, i+3); - ret->sa.push_back(r.first); + ret->add(r.first); j = i = r.second; } else if( word_eq("$(", in, size, i) ) // substitution @@ -260,10 +260,10 @@ std::pair parse_arg(const char* in, uint32_t size, uint32_t star // add previous subarg std::string tmpstr=std::string(in+j, i-j); if(tmpstr!="") - ret->sa.push_back(new string_subarg(tmpstr)); + ret->add(new string_subarg(tmpstr)); // get subshell auto r=parse_subshell(in, size, i+2); - ret->sa.push_back(new subshell_subarg(r.first, true)); + ret->add(new subshell_subarg(r.first, true)); j = i = r.second; } else if( word_eq("${", in, size, i) ) // variable manipulation @@ -271,10 +271,10 @@ std::pair parse_arg(const char* in, uint32_t size, uint32_t star // add previous subarg std::string tmpstr=std::string(in+j, i-j); if(tmpstr!="") - ret->sa.push_back(new string_subarg(tmpstr)); + ret->add(new string_subarg(tmpstr)); // get manipulation auto r=parse_manipulation(in, size, i+2); - ret->sa.push_back(r.first); + ret->add(r.first); j = i = r.second; } else if( in[i] == '$' ) @@ -285,9 +285,9 @@ std::pair parse_arg(const char* in, uint32_t size, uint32_t star // add previous subarg std::string tmpstr=std::string(in+j, i-j); if(tmpstr!="") - ret->sa.push_back(new string_subarg(tmpstr)); + ret->add(new string_subarg(tmpstr)); // add varname - ret->sa.push_back(new variable_subarg(r.first)); + ret->add(new variable_subarg(r.first)); j = i = r.second; } else @@ -316,10 +316,10 @@ std::pair parse_arg(const char* in, uint32_t size, uint32_t star // add previous subarg std::string tmpstr=std::string(in+j, i-j); if(tmpstr!="") - ret->sa.push_back(new string_subarg(tmpstr)); + ret->add(new string_subarg(tmpstr)); // get arithmetic auto r=parse_arithmetic(in, size, i+3); - ret->sa.push_back(r.first); + ret->add(r.first); j = i = r.second; } else if( word_eq("$(", in, size, i) ) // substitution @@ -327,10 +327,10 @@ std::pair parse_arg(const char* in, uint32_t size, uint32_t star // add previous subarg std::string tmpstr=std::string(in+j, i-j); if(tmpstr!="") - ret->sa.push_back(new string_subarg(tmpstr)); + ret->add(new string_subarg(tmpstr)); // get subshell auto r=parse_subshell(in, size, i+2); - ret->sa.push_back(new subshell_subarg(r.first, false)); + ret->add(new subshell_subarg(r.first, false)); j = i = r.second; } else if( word_eq("${", in, size, i) ) // variable manipulation @@ -338,10 +338,10 @@ std::pair parse_arg(const char* in, uint32_t size, uint32_t star // add previous subarg std::string tmpstr=std::string(in+j, i-j); if(tmpstr!="") - ret->sa.push_back(new string_subarg(tmpstr)); + ret->add(new string_subarg(tmpstr)); // get manipulation auto r=parse_manipulation(in, size, i+2); - ret->sa.push_back(r.first); + ret->add(r.first); j = i = r.second; } else if( in[i] == '$' ) @@ -352,9 +352,9 @@ std::pair parse_arg(const char* in, uint32_t size, uint32_t star // add previous subarg std::string tmpstr=std::string(in+j, i-j); if(tmpstr!="") - ret->sa.push_back(new string_subarg(tmpstr)); + ret->add(new string_subarg(tmpstr)); // add varname - ret->sa.push_back(new variable_subarg(r.first)); + ret->add(new variable_subarg(r.first)); j = i = r.second; } else @@ -367,7 +367,7 @@ std::pair parse_arg(const char* in, uint32_t size, uint32_t star // add string subarg std::string val=std::string(in+j, i-j); if(val != "") - ret->sa.push_back(new string_subarg(val)); + ret->add(new string_subarg(val)); #ifndef NO_PARSE_CATCH } @@ -498,15 +498,11 @@ std::pair parse_redirect(const char* in, uint32_t size, uin else { i = size; - // maybe at end of file with no \n - // if(strstr(in+size-delimitor.size(), std::string("\n"+delimitor).c_str())!=NULL) - // i = size-delimitor.size(); - // else // not found: end of file } std::string tmpparse=std::string(in+j, i-j); auto pval = parse_arg(tmpparse.c_str(), tmpparse.size(), 0, NULL); ret->target = pval.first; - ret->target->sa.insert(ret->target->sa.begin(), new string_subarg(delimitor+"\n")); + ret->target->insert(0, new string_subarg(delimitor+"\n")); } else { @@ -559,7 +555,7 @@ std::pair parse_arglist(const char* in, uint32_t size, uint3 if(ret == nullptr) ret = new arglist; auto ps = parse_subshell(in, size, i); - ret->args.push_back(new arg(new procsub_subarg(is_output, ps.first))); + ret->add(new arg(new procsub_subarg(is_output, ps.first))); i=ps.second; } else if(redirs!=nullptr) @@ -579,7 +575,7 @@ std::pair parse_arglist(const char* in, uint32_t size, uint3 if(ret == nullptr) ret = new arglist; auto pp=parse_arg(in, size, i); - ret->args.push_back(pp.first); + ret->add(pp.first); i = pp.second; } i = skip_chars(in, size, i, SPACES); @@ -712,7 +708,7 @@ std::pair parse_list_until(const char* in, uint32_t size, uint3 while(in[i] != end_c) { auto pp=parse_condlist(in, size, i); - ret->cls.push_back(pp.first); + ret->add(pp.first); i=pp.second; if(i < size) @@ -775,7 +771,7 @@ std::pair parse_list_until(const char* in, uint32_t size, uint3 } // do a parse auto pp=parse_condlist(in, size, i); - ret->cls.push_back(pp.first); + ret->add(pp.first); i=pp.second; if(i parse_list_until(const char* in, uint32 break; // do a parse auto pp=parse_condlist(in, size, i); - ret->cls.push_back(pp.first); + ret->add(pp.first); i=pp.second; if(in[i] == '#') ; // skip here @@ -1065,7 +1061,7 @@ std::pair parse_case(const char* in, uint32_t size, uint3 { pa = parse_arg(in, size, i); cc->first.push_back(pa.first); - if(pa.first->sa.size() <= 0) + if(pa.first->size() <= 0) throw PARSE_ERROR("Empty case value", i); i=skip_unread(in, size, pa.second); if(i>=size) diff --git a/src/processing.cpp b/src/processing.cpp index bb35a69..cfd0e8b 100644 --- a/src/processing.cpp +++ b/src/processing.cpp @@ -13,6 +13,10 @@ std::regex re_fct_exclude; const std::regex regex_null; +// globals + +const std::vector argvar_cmds = { "export", "unset", "local", "read", "readonly", "declare" }; + // Object maps countmap_t m_vars, m_vardefs, m_varcalls; @@ -21,6 +25,7 @@ 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() @@ -153,7 +158,10 @@ std::string get_varname(arg* in) bool cmd_is_argvar(std::string const& in) { - return in == "export" || in == "unset" || in == "local" || in == "read"; + for(auto it: argvar_cmds) + if(in == it) + return true; + return false; } bool cmd::is_argvar() diff --git a/src/resolve.cpp b/src/resolve.cpp index 49ea432..760ba8e 100644 --- a/src/resolve.cpp +++ b/src/resolve.cpp @@ -229,7 +229,7 @@ std::pair< std::vector , bool > resolve_arg(arg* in, shmain* parent, bool arg* ta=nullptr; bool has_resolved=false; uint32_t j=0; - for(uint32_t i=0 ; isa.size() ; i++) + for(uint32_t i=0 ; isize() ; i++) { if(in->sa[i]->type != _obj::subarg_subshell) // skip if not subshell continue; @@ -289,14 +289,14 @@ std::pair< std::vector , bool > resolve_arg(arg* in, shmain* parent, bool if(ta == nullptr) ta = new arg; ta->sa.insert(ta->sa.end(), in->sa.begin()+j, in->sa.begin()+i); - ta->sa.push_back(new string_subarg(strargs[i])); + ta->add(new string_subarg(strargs[i])); j=i+1; delete in->sa[i]; for(uint32_t li=1 ; lisa.push_back(new string_subarg(strargs[li])); + ta->add(new string_subarg(strargs[li])); } } // end pack @@ -353,7 +353,7 @@ bool r_resolve(_obj* o, shmain* parent) case _obj::_arglist : { auto t = dynamic_cast(o); - for(uint32_t i=0 ; iargs.size() ; i++) + for(uint32_t i=0 ; isize() ; i++) { auto r=resolve_arg(t->args[i], parent); if(r.first.size()>0) diff --git a/src/struc_helper.cpp b/src/struc_helper.cpp index fbb09db..cd169e1 100644 --- a/src/struc_helper.cpp +++ b/src/struc_helper.cpp @@ -94,21 +94,21 @@ cmd* condlist::first_cmd() cmd* brace::single_cmd() { - if( lst->size() == 1 && // only one condlist - (*lst)[0]->pls.size() == 1 && // only one pipeline - (*lst)[0]->pls[0]->cmds.size() == 1 && // only one block - (*lst)[0]->pls[0]->cmds[0]->type == _obj::block_cmd) // block is a command - return dynamic_cast((*lst)[0]->pls[0]->cmds[0]); // return command + if( lst->cls.size() == 1 && // only one condlist + lst->cls[0]->pls.size() == 1 && // only one pipeline + lst->cls[0]->pls[0]->cmds.size() == 1 && // only one block + lst->cls[0]->pls[0]->cmds[0]->type == _obj::block_cmd) // block is a command + return dynamic_cast(lst->cls[0]->pls[0]->cmds[0]); // return command return nullptr; } cmd* subshell::single_cmd() { - if( lst->size() == 1 && // only one condlist - (*lst)[0]->pls.size() == 1 && // only one pipeline - (*lst)[0]->pls[0]->cmds.size() == 1 && // only one block - (*lst)[0]->pls[0]->cmds[0]->type == _obj::block_cmd) // block is a command - return dynamic_cast((*lst)[0]->pls[0]->cmds[0]); // return command + if( lst->cls.size() == 1 && // only one condlist + lst->cls[0]->pls.size() == 1 && // only one pipeline + lst->cls[0]->pls[0]->cmds.size() == 1 && // only one block + lst->cls[0]->pls[0]->cmds[0]->type == _obj::block_cmd) // block is a command + return dynamic_cast(lst->cls[0]->pls[0]->cmds[0]); // return command return nullptr; } @@ -144,12 +144,30 @@ void condlist::prune_first_cmd() // add/extend +void arg::insert(uint32_t i, subarg* val) +{ + sa.insert(sa.begin()+i, val); +} +void arg::insert(uint32_t i, arg const& a) +{ + sa.insert(sa.begin()+i, a.sa.begin(), a.sa.end()); +} + +void arglist::insert(uint32_t i, arg* val) +{ + args.insert(args.begin()+i, val); +} +void arglist::insert(uint32_t i, arglist const& lst) +{ + args.insert(args.begin()+i, lst.args.begin(), lst.args.end()); +} + void cmd::add(arg* in) { if(args==nullptr) args = new arglist; - args->push_back(in); + args->add(in); } void condlist::add(pipeline* pl, bool or_op)