implement separated variables on assigns and cmdvars

This commit is contained in:
zawz 2021-06-29 15:17:59 +02:00
parent 38845e8652
commit e7d868de9e
9 changed files with 93 additions and 44 deletions

View file

@ -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);

View file

@ -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...);

View file

@ -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<std::pair<variable*,arg*>> cmd_var_assigns;
// check if cmd is this (ex: unset)
bool is(std::string const& in);

View file

@ -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; i<c1->var_assigns.size(); i++)
for(uint32_t i=0; i<c1->cmd_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;

View file

@ -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)
{

View file

@ -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")
} );

View file

@ -1174,7 +1174,7 @@ std::pair<function*, parse_context> 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<std::pair<variable*,arg*>>* ret=&in->var_assigns;
if(cmdassign)
ret=&in->cmd_var_assigns;
while(ctx.i<ctx.size && !is_in(ctx[ctx.i], ARGLIST_END))
{
auto vp=parse_var(ctx, false, true);
@ -1245,7 +1249,7 @@ parse_context parse_cmd_varassigns(cmd* ret, parse_context ctx, bool cmdassign=f
ctx=pp.second;
}
ta->insert(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<cmd*, parse_context> 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<cmd*, parse_context> 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<cmd*, parse_context> 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++;

View file

@ -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; j<c->cmd_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<std::string> bb;
for(auto it: t->cmd_var_assigns)
{
std::vector<std::pair<std::string,std::string>> 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<std::string> tvec;
for(auto it: t->redirs)

View file

@ -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);