diff --git a/include/processing.hpp b/include/processing.hpp index 26ab7d6..e00c832 100644 --- a/include/processing.hpp +++ b/include/processing.hpp @@ -44,7 +44,9 @@ void fctmap_get(_obj* in, std::regex const& exclude); void cmdmap_get(_obj* in, std::regex const& exclude); /** util functions **/ +#ifdef DEBUG_MODE std::string gen_json_struc(_obj* in); +#endif // gen regexes std::regex var_exclude_regex(std::string const& in, bool include_reserved); diff --git a/include/recursive.hpp b/include/recursive.hpp index d06d7b5..baacd97 100644 --- a/include/recursive.hpp +++ b/include/recursive.hpp @@ -126,6 +126,11 @@ void recurse(bool (&fct)(_obj*, Args...), _obj* o, Args... args) recurse(fct, it.first, args...); recurse(fct, it.second, args...); } + for(auto it: t->cmd_var_assigns) + { + recurse(fct, it.first, args...); + recurse(fct, it.second, args...); + } for(auto it: t->redirs) recurse(fct, it, args...); diff --git a/include/struc.hpp b/include/struc.hpp index dabb156..0f8e258 100644 --- a/include/struc.hpp +++ b/include/struc.hpp @@ -371,6 +371,10 @@ public: delete it.first; delete it.second; } + for(auto it: cmd_var_assigns) { + delete it.first; + delete it.second; + } } static const std::string empty_string; @@ -387,6 +391,8 @@ public: // is a cmdvar type bool is_cmdvar; + // var assigns on cmdvar + std::vector> cmd_var_assigns; // check if cmd is this (ex: unset) bool is(std::string const& in); diff --git a/src/debashify.cpp b/src/debashify.cpp index f74562f..c35c5e3 100644 --- a/src/debashify.cpp +++ b/src/debashify.cpp @@ -135,9 +135,9 @@ void warn(std::string const& in) std::string get_declare_opt(cmd* in) { - if(in->var_assigns[0].second!=nullptr) + if(in->cmd_var_assigns[0].second!=nullptr) { - return in->var_assigns[0].second->string(); + return in->cmd_var_assigns[0].second->string(); } return ""; } @@ -307,19 +307,19 @@ bool debashify_readonly(list* in) { has_found=true; c1->is_cmdvar=false; - for(uint32_t i=0; ivar_assigns.size(); i++) + for(uint32_t i=0; icmd_var_assigns.size(); i++) { - if(c1->var_assigns[i].first == nullptr || c1->var_assigns[i].second == nullptr) + if(c1->cmd_var_assigns[i].first == nullptr || c1->cmd_var_assigns[i].second == nullptr) { - if(c1->var_assigns[i].first != nullptr) - delete c1->var_assigns[i].first; - if(c1->var_assigns[i].second != nullptr) - delete c1->var_assigns[i].second; - c1->var_assigns.erase(c1->var_assigns.begin()+i); + if(c1->cmd_var_assigns[i].first != nullptr) + delete c1->cmd_var_assigns[i].first; + if(c1->cmd_var_assigns[i].second != nullptr) + delete c1->cmd_var_assigns[i].second; + c1->cmd_var_assigns.erase(c1->cmd_var_assigns.begin()+i); i--; } } - if(c1->var_assigns.size() == 0) + if(c1->cmd_var_assigns.size() == 0) { delete in->cls[i]; in->cls.erase(in->cls.begin()+i); @@ -329,6 +329,8 @@ bool debashify_readonly(list* in) { delete c1->args; c1->args = new arglist; + c1->var_assigns=c1->cmd_var_assigns; + c1->cmd_var_assigns.resize(0); } } } @@ -351,7 +353,7 @@ bool debashify_declare(list* in, debashify_params* params) std::string const& op = get_declare_opt(c1); if(op == "-a") { - for(auto it: c1->var_assigns) + for(auto it: c1->cmd_var_assigns) { if(it.first != nullptr) params->arrays[it.first->varname] = false; @@ -359,7 +361,7 @@ bool debashify_declare(list* in, debashify_params* params) } else if(op == "-A") { - for(auto it: c1->var_assigns) + for(auto it: c1->cmd_var_assigns) { if(it.first != nullptr) params->arrays[it.first->varname] = true; diff --git a/src/generate.cpp b/src/generate.cpp index a999afb..2971093 100644 --- a/src/generate.cpp +++ b/src/generate.cpp @@ -333,22 +333,6 @@ std::string cmd::generate(int ind, generate_context* ctx) { std::string ret; - // is a varassign cmd - if(is_cmdvar) - { - ret += args->generate(ind) + ' '; - for(auto it: var_assigns) - { - if(it.first != nullptr) - ret += it.first->generate(ind); - if(it.second != nullptr) - ret += it.second->generate(ind); - ret += ' '; - } - ret.pop_back(); - return ret; - } - bool has_args=false; // pre-cmd var assigns @@ -362,6 +346,22 @@ std::string cmd::generate(int ind, generate_context* ctx) ret += ' '; } + // is a varassign cmd + if(is_cmdvar) + { + ret += args->generate(ind) + ' '; + for(auto it: cmd_var_assigns) + { + if(it.first != nullptr) + ret += it.first->generate(ind); + if(it.second != nullptr) + ret += it.second->generate(ind); + ret += ' '; + } + ret.pop_back(); + return ret; + } + // cmd itself if(args!=nullptr && args->size()>0) { diff --git a/src/options.cpp b/src/options.cpp index b46885a..25418c3 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -37,7 +37,7 @@ ztd::option_set options( { ztd::option("remove-unused", false, "Remove unused functions and variables"), ztd::option("list-cmd", false, "List all commands invoked in the script"), ztd::option("\r [Variable processing]"), - ztd::option("exclude-var", true, "List of matching regex to ignore for variable processing, separated by comma", "list"), + ztd::option("exclude-var", true, "List of matching regex to ignore for variable processing, separated by spaces", "list"), ztd::option("no-exclude-reserved",false, "Don't exclude reserved variables"), ztd::option("minify-var", false, "Minify variable names"), ztd::option("list-var", false, "List all variables set and invoked in the script"), @@ -45,7 +45,7 @@ ztd::option_set options( { ztd::option("list-var-call", false, "List all variables invoked in the script"), ztd::option("unset-var", false, "Add 'unset' to all variables at the start of the script to avoid environment interference"), ztd::option("\r [Function processing]"), - ztd::option("exclude-fct", true, "List of matching regex to ignore for function processing, separated by comma", "list"), + ztd::option("exclude-fct", true, "List of matching regex to ignore for function processing, separated by spaces", "list"), ztd::option("minify-fct", false, "Minify function names"), ztd::option("list-fct", false, "List all functions defined in the script") } ); diff --git a/src/parse.cpp b/src/parse.cpp index 52cb04f..13d88cb 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -1174,7 +1174,7 @@ std::pair parse_function(parse_context ctx, const char } // parse only var assigns -parse_context parse_cmd_varassigns(cmd* ret, parse_context ctx, bool cmdassign=false, std::string const& cmd="") +parse_context parse_cmd_varassigns(cmd* in, parse_context ctx, bool cmdassign=false, std::string const& cmd="") { bool forbid_assign=false; bool forbid_special=false; @@ -1183,6 +1183,10 @@ parse_context parse_cmd_varassigns(cmd* ret, parse_context ctx, bool cmdassign=f if(cmdassign && (forbid_special || cmd == "export") ) forbid_special=true; + std::vector>* ret=&in->var_assigns; + if(cmdassign) + ret=&in->cmd_var_assigns; + while(ctx.iinsert(0, strop); - ret->var_assigns.push_back(std::make_pair(vp.first, ta)); + ret->push_back(std::make_pair(vp.first, ta)); ctx.i=skip_chars(ctx, SPACES); } else @@ -1254,14 +1258,14 @@ parse_context parse_cmd_varassigns(cmd* ret, parse_context ctx, bool cmdassign=f { if(vp.first != nullptr && is_in(newct[newct.i], ARG_END) ) { - ret->var_assigns.push_back(std::make_pair(vp.first, nullptr)); + ret->push_back(std::make_pair(vp.first, nullptr)); ctx=newct; } else { delete vp.first; auto pp=parse_arg(ctx); - ret->var_assigns.push_back(std::make_pair(nullptr, pp.first)); + ret->push_back(std::make_pair(nullptr, pp.first)); ctx=pp.second; } ctx.i=skip_chars(ctx, SPACES); @@ -1281,7 +1285,6 @@ parse_context parse_cmd_varassigns(cmd* ret, parse_context ctx, bool cmdassign=f std::pair parse_cmd(parse_context ctx) { cmd* ret = new cmd; - uint32_t start=ctx.i; ctx = parse_cmd_varassigns(ret, ctx); @@ -1292,10 +1295,6 @@ std::pair parse_cmd(parse_context ctx) { parse_error("bash specific: "+wp.first, ctx); } - if(ret->var_assigns.size()>0) - { - parse_error("Unallowed preceding variables on "+wp.first, ctx, start); - } ret->args = new arglist; ret->args->add(new arg(wp.first)); @@ -1305,14 +1304,13 @@ std::pair parse_cmd(parse_context ctx) ctx = parse_cmd_varassigns(ret, ctx, true, wp.first); } - - if(!is_in(ctx[ctx.i], ARGLIST_END)) + else if(!is_in(ctx[ctx.i], ARGLIST_END)) { auto pp=parse_arglist(ctx, true, &ret->redirs); ret->args = pp.first; ctx = pp.second; } - else if(ret->var_assigns.size() <= 0) + else if( ret->var_assigns.size() <= 0 ) { parse_error( unexpected_token(ctx[ctx.i]), ctx ); ctx.i++; diff --git a/src/processing.cpp b/src/processing.cpp index 0d25e21..217e98a 100644 --- a/src/processing.cpp +++ b/src/processing.cpp @@ -250,7 +250,7 @@ void add_unset_variables(shmain* sh, std::regex const& exclude) unset_cmd->is_cmdvar=true; for(auto it: m_vars) { - unset_cmd->var_assigns.push_back(std::make_pair(new variable(it.first), nullptr)); + unset_cmd->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); @@ -296,6 +296,11 @@ bool r_get_unsets(_obj* in, set_t* unsets) if(it.first != nullptr) unsets->insert(it.first->varname); } + for(auto it: t->cmd_var_assigns) + { + if(it.first != nullptr) + unsets->insert(it.first->varname); + } } }; break; default: break; @@ -391,6 +396,22 @@ bool r_delete_var(_obj* in, set_t* vars) if(has_deleted && c->var_assigns.size()<=0 && (c->arglist_size()<=0 || c->is_cmdvar) ) to_delete=true; + for(uint32_t j=0; jcmd_var_assigns.size(); j++) + { + if( c->cmd_var_assigns[j].first != nullptr && vars->find(c->cmd_var_assigns[j].first->varname) != vars->end() ) + { + if(c->cmd_var_assigns[j].first != nullptr) + delete c->cmd_var_assigns[j].first; + if(c->cmd_var_assigns[j].second != nullptr) + delete c->cmd_var_assigns[j].second; + c->cmd_var_assigns.erase(c->cmd_var_assigns.begin()+j); + has_deleted=true; + j--; + } + } + if(has_deleted && c->cmd_var_assigns.size()<=0 && (c->arglist_size()<=0 || c->is_cmdvar) ) + to_delete=true; + } if(to_delete) { @@ -482,6 +503,8 @@ void string_processors(_obj* in) /** JSON **/ +#ifdef DEBUG_MODE + std::string quote_string(std::string const& in) { return '"' + stringReplace(in, "\"", "\\\"") + '"'; @@ -519,7 +542,6 @@ std::string boolstring(bool in) return "false"; } -#ifdef DEBUG_MODE std::string gen_json_struc(_obj* o) { if(o==nullptr) @@ -681,6 +703,15 @@ std::string gen_json_struc(_obj* o) aa.push_back(gen_json(ttvec)); } vec.push_back(std::make_pair( quote_string("var_assigns"), gen_json(aa))); + std::vector bb; + for(auto it: t->cmd_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)) ); + bb.push_back(gen_json(ttvec)); + } + vec.push_back(std::make_pair( quote_string("cmd_var_assigns"), gen_json(bb))); std::vector tvec; for(auto it: t->redirs) diff --git a/src/resolve.cpp b/src/resolve.cpp index 1858337..4249cef 100644 --- a/src/resolve.cpp +++ b/src/resolve.cpp @@ -403,6 +403,11 @@ bool r_resolve(_obj* o, parse_context* ct) resolve_arg(it.second, *ct, true); // force quoted resolve(it.second, ct); } + for(auto it: t->cmd_var_assigns) // var assigns + { + resolve_arg(it.second, *ct, true); // force quoted + resolve(it.second, ct); + } for(auto it: t->redirs) resolve(it, ct); resolve(t->args, ct);