minify single-block braces and subshells

This commit is contained in:
zawwz 2021-07-24 08:35:55 +02:00
parent 4c984bdc39
commit 8c63b9a35e
6 changed files with 106 additions and 6 deletions

View file

@ -70,6 +70,7 @@ void list_fcts(_obj* in, std::regex const& exclude);
void list_cmds(_obj* in, std::regex const& exclude);
// recursives
bool r_has_env_set(_obj* in, bool* result);
bool r_get_unsets(_obj* in, set_t* unsets);
bool r_get_var(_obj* in, countmap_t* defmap, countmap_t* callmap);
bool r_get_cmd(_obj* in, countmap_t* all_cmds);
@ -81,6 +82,7 @@ bool r_delete_var(_obj* in, set_t* vars);
std::set<std::string> find_lxsh_commands(shmain* sh);
void add_unset_variables(shmain* sh, std::regex const& exclude);
bool has_env_set(_obj* in);
void string_processors(_obj* in);

View file

@ -400,6 +400,9 @@ public:
bool is_argvar();
std::vector<subarg*> subarg_vars();
// returns true if command performs env var changes
bool has_var_assign();
arglist* args;
std::string generate(int ind, generate_context* ctx);

View file

@ -180,12 +180,6 @@ int main(int argc, char* argv[])
list_fcts(sh, re_fct_exclude);
else if(options["list-cmd"])
list_cmds(sh, regex_null);
#ifdef DEBUG_MODE
else if(options['J'])
{
std::cout << gen_json_struc(sh) << std::endl;
}
#endif
// output
else
{
@ -217,6 +211,14 @@ int main(int argc, char* argv[])
if(options["unset-var"])
add_unset_variables( sh, re_var_exclude );
#ifdef DEBUG_MODE
if(options['J'])
{
std::cout << gen_json_struc(sh) << std::endl;
goto end;
}
#endif
if(options['o']) // file output
{
std::string destfile=options['o'];
@ -257,6 +259,7 @@ int main(int argc, char* argv[])
std::cerr << e.what() << std::endl;
return ERR_RUNTIME;
}
end:
delete sh;

View file

@ -436,7 +436,65 @@ bool r_minify_empty_manip(_obj* in)
return true;
}
block* do_one_minify_single_block(block* in)
{
block* ret=nullptr;
list* l=nullptr;
if(in->type == _obj::block_brace)
l = dynamic_cast<brace*>(in)->lst;
else if(in->type == _obj::block_subshell)
l = dynamic_cast<subshell*>(in)->lst;
if(l == nullptr)
return nullptr;
// not a single cmd/block: not applicable
if(l->cls.size() != 1 || l->cls[0]->pls.size() != 1 || l->cls[0]->pls[0]->cmds.size() != 1)
return nullptr;
ret = l->cls[0]->pls[0]->cmds[0];
// if is a subshell and has some env set: don't remove it
if(in->type == _obj::block_subshell && has_env_set(in))
return nullptr;
return ret;
}
bool r_minify_single_block(_obj* in)
{
switch(in->type)
{
case _obj::_pipeline: {
pipeline* t = dynamic_cast<pipeline*>(in);
for(uint32_t i=0; i<t->cmds.size(); i++)
{
block* ret = do_one_minify_single_block(t->cmds[i]);
if(ret != nullptr) {
// concatenate redirects
for(uint32_t i=0; i<t->cmds[i]->redirs.size(); i++)
ret->redirs.insert(ret->redirs.begin()+i, ret->redirs[i]);
// deindex
t->cmds[i]->redirs.resize(0);
if(t->cmds[i]->type == _obj::block_brace)
dynamic_cast<brace*>(t->cmds[i])->lst->cls[0]->pls[0] = nullptr;
else if(t->cmds[i]->type == _obj::block_subshell)
dynamic_cast<subshell*>(t->cmds[i])->lst->cls[0]->pls[0] = nullptr;
// replace value
delete t->cmds[i];
t->cmds[i] = ret;
}
}
}; break;
default: break;
}
return true;
}
void minify_generic(_obj* in)
{
recurse(r_minify_empty_manip, in);
recurse(r_minify_single_block, in);
}

View file

@ -265,8 +265,33 @@ void add_unset_variables(shmain* sh, std::regex const& exclude)
}
}
bool has_env_set(_obj* in) {
bool r=false;
recurse(r_has_env_set, in, &r);
return r;
}
/** RECURSIVES **/
// CHECK //
bool r_has_env_set(_obj* in, bool* result)
{
switch(in->type)
{
case _obj::block_subshell: {
return false;
}; break;
case _obj::block_cmd: {
cmd* t = dynamic_cast<cmd*>(in);
if(t->has_var_assign())
*result = true;
}
default: break;
}
return true;
}
// GET //
bool r_get_var(_obj* in, countmap_t* defmap, countmap_t* callmap)

View file

@ -138,6 +138,15 @@ bool possibly_expands(arglist* in)
// property getters
bool cmd::has_var_assign()
{
if(this->args->size() == 0)
{
return this->var_assigns.size()>0;
}
return this->is_argvar();
}
size_t cmd::arglist_size()
{
if(args==nullptr)