From 4c984bdc39f7fb54958ad6baf20c9b337f79ff00 Mon Sep 17 00:00:00 2001 From: zawwz Date: Sat, 24 Jul 2021 08:26:24 +0200 Subject: [PATCH] minify empty variable manipulation --- include/minify.hpp | 2 ++ src/main.cpp | 1 + src/minify.cpp | 59 +++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 56 insertions(+), 6 deletions(-) diff --git a/include/minify.hpp b/include/minify.hpp index 53b6011..124f2b0 100644 --- a/include/minify.hpp +++ b/include/minify.hpp @@ -15,4 +15,6 @@ void delete_unused(_obj* in, std::regex const& var_exclude, std::regex const& fc void minify_quotes(_obj* in); +void minify_generic(_obj* in); + #endif //MINIFY_HPP diff --git a/src/main.cpp b/src/main.cpp index 060c1ba..decb51f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -205,6 +205,7 @@ int main(int argc, char* argv[]) { opt_minify=true; string_processors(sh); + minify_generic(sh); } if(options["minify-quotes"]) minify_quotes(sh); diff --git a/src/minify.cpp b/src/minify.cpp index 6ac8974..a639cb8 100644 --- a/src/minify.cpp +++ b/src/minify.cpp @@ -69,7 +69,7 @@ bool r_replace_var(_obj* in, strmap_t* varmap) return true; } -const char* escaped_char=" \\\t!\"()|&*?~><#"; +const char* singlequote_escape_char=" \\\t!\"()|&*?~><#"; const char* doublequote_escape_char=" \t'|&\\*()?~><#"; uint32_t count_escape_chars(std::string const& in, bool doublequote) { @@ -78,7 +78,7 @@ uint32_t count_escape_chars(std::string const& in, bool doublequote) { if(doublequote && is_in(in[i], doublequote_escape_char)) r++; - else if(!doublequote && is_in(in[i], escaped_char)) + else if(!doublequote && is_in(in[i], singlequote_escape_char)) r++; else if(in[i] == '\n') // \n: can't remove quotes return 2; @@ -170,17 +170,17 @@ void do_one_minify_quotes(string_subarg* in, bool prev_is_var, bool start_quoted for(k=j; k(in); for(uint32_t i=0; isa.size(); i++) { + // iterate subargs if(t->sa[i]->type == _obj::subarg_string) { + // has to be a string string_subarg* ss = dynamic_cast(t->sa[i]); bool prev_is_var=false; if(i>0 && t->sa[i-1]->type == _obj::subarg_variable) { + // previous subarg is a direct variable (removing a quote could change variable name) variable_subarg* vs = dynamic_cast(t->sa[i-1]); if(vs->var != nullptr && vs->var->is_manip == false && vs->var->varname.size()>0 && !(is_in(vs->var->varname[0], SPECIAL_VARS) || is_alpha(vs->var->varname[0]) ) ) prev_is_var=true; @@ -217,6 +220,7 @@ bool r_minify_useless_quotes(_obj* in) } }; break; case _obj::_redirect: { + // for redirects: don't minify quotes on here documents redirect* t = dynamic_cast(in); if(t->here_document != nullptr) { @@ -393,3 +397,46 @@ void delete_unused(_obj* in, std::regex const& var_exclude, std::regex const& fc while(delete_unused_fct(in, fct_exclude) || delete_unused_var(in, var_exclude)); // keep deleting until both no function and no variables were deleted } + + +// minify ${var} to $var +bool r_minify_empty_manip(_obj* in) +{ + switch(in->type) + { + case _obj::_arg: { + arg* t = dynamic_cast(in); + for(uint32_t i=0; isa.size(); i++) + { + if(t->sa[i]->type == _obj::subarg_variable) + { + // has to be a variable + variable_subarg* ss = dynamic_cast(t->sa[i]); + if(ss->var->is_manip) + { + // if is a manip: possibility to skip it + if(i+1sa.size() && t->sa[i+1]->type == _obj::subarg_string) + { + // if next subarg is a string: check its first char + string_subarg* ss = dynamic_cast(t->sa[i+1]); + char c = ss->val[0]; + // if its first would extend the var name: skip + if(is_alphanum(c) || c == '_') + return true; + } + // if has no actual manipulation operation: set it to not manip + if(ss->var->manip == nullptr || ss->var->manip->sa.size() == 0) + ss->var->is_manip = false; + } + } + } + }; break; + default: break; + } + return true; +} + +void minify_generic(_obj* in) +{ + recurse(r_minify_empty_manip, in); +}