From 2ffe4ddf2f3d4d4ba30ba2c125e5831fdb89b425 Mon Sep 17 00:00:00 2001 From: zawwz Date: Wed, 20 Jan 2021 11:49:32 +0100 Subject: [PATCH] implement internal variable structure --- include/parse.hpp | 6 +++- include/recursive.hpp | 24 ++++++++++++++++ include/struc.hpp | 51 ++++++++++++++++++++++++--------- src/debashify.cpp | 2 +- src/generate.cpp | 18 +++++++++--- src/minimize.cpp | 38 +++++-------------------- src/parse.cpp | 66 +++++++++++++++++++++++++++++-------------- src/processing.cpp | 37 +++++++++--------------- 8 files changed, 148 insertions(+), 94 deletions(-) diff --git a/include/parse.hpp b/include/parse.hpp index fc3b29f..083e82a 100644 --- a/include/parse.hpp +++ b/include/parse.hpp @@ -23,6 +23,10 @@ #define SPECIAL_VARS "!#*@$?" +// bash specific +#define ARRAY_ARG_END " \t\n;#()&|<>]" + + std::string import_file(std::string const& path); shmain* parse_text(const char* in, uint32_t size, std::string const& filename=""); @@ -37,7 +41,7 @@ std::pair parse_list_until(const char* in, uint32_t size, uint3 std::pair parse_list_until(const char* in, uint32_t size, uint32_t start, std::string const& end_word); std::tuple parse_list_until(const char* in, uint32_t size, uint32_t start, std::vector const& end_words, const char* expecting=NULL); // name -std::pair parse_varname(const char* in, uint32_t size, uint32_t start, bool specialvars=true); +std::pair parse_var(const char* in, uint32_t size, uint32_t start, bool specialvars=true, bool array=false); // subarg parsers std::pair parse_arithmetic(const char* in, uint32_t size, uint32_t start); diff --git a/include/recursive.hpp b/include/recursive.hpp index a76139a..776d2e1 100644 --- a/include/recursive.hpp +++ b/include/recursive.hpp @@ -19,6 +19,12 @@ void recurse(bool (&fct)(_obj*, Args...), _obj* o, Args... args) // recursive calls switch(o->type) { + case _obj::_variable : + { + variable* t = dynamic_cast(o); + recurse(fct, t->index, args...); + break; + } case _obj::_redirect : { redirect* t = dynamic_cast(o); @@ -115,7 +121,10 @@ void recurse(bool (&fct)(_obj*, Args...), _obj* o, Args... args) cmd* t = dynamic_cast(o); recurse(fct, t->args, args...); for(auto it: t->var_assigns) + { + recurse(fct, it.first, args...); recurse(fct, it.second, args...); + } for(auto it: t->redirs) recurse(fct, it, args...); @@ -164,6 +173,8 @@ void recurse(bool (&fct)(_obj*, Args...), _obj* o, Args... args) case _obj::block_for : { for_block* t = dynamic_cast(o); + // variable + recurse(fct, t->var, args...); // iterations recurse(fct, t->iter, args...); // for block @@ -187,6 +198,12 @@ void recurse(bool (&fct)(_obj*, Args...), _obj* o, Args... args) break; } + case _obj::subarg_variable : + { + variable_subarg* t = dynamic_cast(o); + recurse(fct, t->var, args...); + break; + } case _obj::subarg_subshell : { subshell_subarg* t = dynamic_cast(o); @@ -196,6 +213,7 @@ void recurse(bool (&fct)(_obj*, Args...), _obj* o, Args... args) case _obj::subarg_manipulation : { manipulation_subarg* t = dynamic_cast(o); + recurse(fct, t->var, args...); recurse(fct, t->manip, args...); break; } @@ -211,6 +229,12 @@ void recurse(bool (&fct)(_obj*, Args...), _obj* o, Args... args) recurse(fct, t->arith, args...); break; } + case _obj::arithmetic_variable : + { + variable_arithmetic* t = dynamic_cast(o); + recurse(fct, t->var, args...); + break; + } case _obj::arithmetic_subshell : { subshell_arithmetic* t = dynamic_cast(o); diff --git a/include/struc.hpp b/include/struc.hpp index 2e7b761..632bc7d 100644 --- a/include/struc.hpp +++ b/include/struc.hpp @@ -84,6 +84,7 @@ class _obj public: enum _objtype { subarg_string, subarg_variable, subarg_subshell, subarg_arithmetic, subarg_manipulation, subarg_procsub, + _variable, _redirect, _arg, arg_procsub, _arglist, @@ -141,6 +142,21 @@ public: std::string generate(int ind); }; +class variable : public _obj +{ +public: + variable(std::string const& in="", arg* i=nullptr, bool def=false) { type=_obj::_variable; varname=in; index=i; definition=def; } + ~variable() { + if(index!=nullptr) delete index; + } + + std::string varname; + bool definition; + arg* index; // for bash specific + + std::string generate(int ind); +}; + // arglist class arglist : public _obj @@ -288,7 +304,7 @@ public: // preceding var assigns - std::vector> var_assigns; + std::vector> var_assigns; // check if cmd is this (ex: unset) bool is(std::string const& in); @@ -408,13 +424,14 @@ public: class for_block : public block { public: - for_block(std::string const& name="", arglist* args=nullptr, list* lst=nullptr) { type=_obj::block_for; varname=name; iter=args; ops=lst; } + for_block(variable* in=nullptr, arglist* args=nullptr, list* lst=nullptr) { type=_obj::block_for; var=in; iter=args; ops=lst; } ~for_block() { if(iter!=nullptr) delete iter; if(ops!=nullptr) delete ops; + if(var!=nullptr) delete var; } - std::string varname; + variable* var; arglist* iter; list* ops; @@ -455,12 +472,14 @@ public: class variable_subarg : public subarg { public: - variable_subarg(std::string const& in="", bool inq=false) { type=_obj::subarg_variable; varname=in; quoted=inq; } - ~variable_subarg() {;} + variable_subarg(variable* in=nullptr, bool inq=false) { type=_obj::subarg_variable; var=in; quoted=inq; } + ~variable_subarg() { + if(var!=nullptr) delete var; + } - std::string varname; + variable* var; - std::string generate(int ind) { return "$" + varname; } + std::string generate(int ind) { return "$" + var->generate(ind); } }; class arithmetic_subarg : public subarg @@ -490,11 +509,14 @@ public: class manipulation_subarg : public subarg { public: - manipulation_subarg(std::string varname="", arg* in=nullptr, bool inq=false) { type=_obj::subarg_manipulation; size=false; manip=in; quoted=inq; } - ~manipulation_subarg() { if(manip!=nullptr) delete manip; } + manipulation_subarg(variable* vr=nullptr, arg* mn=nullptr, bool inq=false) { type=_obj::subarg_manipulation; size=false; var=vr; manip=mn; quoted=inq; } + ~manipulation_subarg() { + if(manip!=nullptr) delete manip; + if(var!=nullptr) delete var; + } bool size; - std::string varname; + variable* var; arg* manip; std::string generate(int ind); @@ -569,11 +591,14 @@ public: class variable_arithmetic : public arithmetic { public: - variable_arithmetic(std::string const& in) { type=_obj::arithmetic_variable; varname=in; } + variable_arithmetic(variable* in=nullptr) { type=_obj::arithmetic_variable; var=in; } + ~variable_arithmetic() { + if(var!=nullptr) delete var; + } - std::string varname; + variable* var; - std::string generate(int ind) { return varname; } + std::string generate(int ind) { return var->generate(ind); } }; #endif //STRUC_HPP diff --git a/src/debashify.cpp b/src/debashify.cpp index a837ca3..f98aecf 100644 --- a/src/debashify.cpp +++ b/src/debashify.cpp @@ -167,7 +167,7 @@ bool debashify_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->add( new variable_subarg(strf("__lxshfifo%u", i)) ); + affected_args[i].first->add( new variable_subarg( new variable(strf("__lxshfifo%u", i)) ) ); affected_args[i].first->add( new string_subarg("\"") ); } lst->insert(li, *lst_insert ); diff --git a/src/generate.cpp b/src/generate.cpp index 7ea9416..0d4cf08 100644 --- a/src/generate.cpp +++ b/src/generate.cpp @@ -177,7 +177,7 @@ std::string for_block::generate(int ind) { std::string ret; - ret += "for "+varname; + ret += "for "+var->generate(ind); if(iter != nullptr) ret += " in " + iter->generate(ind); ret += '\n'; @@ -314,7 +314,7 @@ std::string cmd::generate(int ind) std::string ret; // var assigns for(auto it: var_assigns) - ret += it.first + '=' + it.second->generate(ind) + ' '; + ret += it.first->generate(ind) + '=' + it.second->generate(ind) + ' '; if(args!=nullptr && args->size()>0) { @@ -350,9 +350,9 @@ std::string subshell_subarg::generate(int ind) std::string manipulation_subarg::generate(int ind) { if(size) - return "${#" + varname + "}"; + return "${#" + var->generate(ind) + "}"; else - return "${" + varname + manip->generate(ind) + "}"; + return "${" + var->generate(ind) + manip->generate(ind) + "}"; } std::string procsub_subarg::generate(int ind) @@ -412,6 +412,16 @@ std::string subshell_arithmetic::generate(int ind) return '$' + sbsh->generate(ind); } +std::string variable::generate(int ind) +{ + if(index!=nullptr) + { + return varname + '[' + index->generate(ind) + ']'; + } + else + return varname; +} + // TEMPLATE // std::string thing::generate(int ind) diff --git a/src/minimize.cpp b/src/minimize.cpp index 2c064c0..4682a44 100644 --- a/src/minimize.cpp +++ b/src/minimize.cpp @@ -56,49 +56,25 @@ bool r_replace_var(_obj* in, strmap_t* varmap) { switch(in->type) { - case _obj::arithmetic_variable: { - variable_arithmetic* t = dynamic_cast(in); + case _obj::_variable: { + variable* t = dynamic_cast(in); auto el=varmap->find(t->varname); if(el!=varmap->end()) t->varname = el->second; }; break; - case _obj::subarg_variable: { - variable_subarg* t = dynamic_cast(in); - auto el=varmap->find(t->varname); - if(el!=varmap->end()) - t->varname = el->second; - }; break; - case _obj::subarg_manipulation: { - manipulation_subarg* t = dynamic_cast(in); - auto el=varmap->find(t->varname); - if(el!=varmap->end()) - t->varname = el->second; - }; break; - case _obj::block_for: { - for_block* t = dynamic_cast(in); - auto it=varmap->find(t->varname); - if(it!=varmap->end()) - t->varname = it->second; - }; break; case _obj::block_cmd: { cmd* t = dynamic_cast(in); - for(auto it=t->var_assigns.begin() ; it!=t->var_assigns.end() ; it++) - { - auto el=varmap->find(it->first); - if(el!=varmap->end()) - it->first = el->second; - } for(auto it: t->subarg_vars()) { - string_subarg* t = dynamic_cast(it); - auto el=varmap->find(get_varname(t->val)); + string_subarg* tss = dynamic_cast(it); + auto el=varmap->find(get_varname(tss->val)); if(el!=varmap->end()) { - size_t tpos=t->val.find('='); + size_t tpos=tss->val.find('='); if(tpos == std::string::npos) - t->val = el->second; + tss->val = el->second; else - t->val = el->second + t->val.substr(tpos); + tss->val = el->second + tss->val.substr(tpos); } } }; break; diff --git a/src/parse.cpp b/src/parse.cpp index 731642a..1165d71 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -127,22 +127,36 @@ uint32_t skip_unread(const char* in, uint32_t size, uint32_t start) // parse fcts -std::pair parse_varname(const char* in, uint32_t size, uint32_t start, bool specialvars) +std::pair parse_var(const char* in, uint32_t size, uint32_t start, bool specialvars, bool array) { uint32_t i=start; - std::string ret; + variable* ret=nullptr; + std::string varname; // special vars if(specialvars && (is_in(in[i], SPECIAL_VARS) || (in[i]>='0' && in[i]<='1')) ) { - ret=in[i]; + varname=in[i]; i++; } else // varname { while(iindex=pp.first; + i = pp.second; + if(in[i] != ']') + throw PARSE_ERROR( "Expecting ']'", i ); + i++; + } } return std::make_pair(ret, i); @@ -186,6 +200,7 @@ std::pair parse_arithmetic(const char* in, uint32_t size, } else { + variable_arithmetic* ttvar=nullptr; // for categorizing definitions if(in[i]=='-' || is_num(in[i])) { uint32_t j=i; @@ -215,8 +230,9 @@ std::pair parse_arithmetic(const char* in, uint32_t size, specialvars=true; i++; } - auto pp = parse_varname(in, size, i, specialvars); - ret = new variable_arithmetic(pp.first); + auto pp = parse_var(in, size, i, specialvars, true); + ttvar = new variable_arithmetic(pp.first); + ret = ttvar; i=pp.second; } @@ -234,6 +250,9 @@ std::pair parse_arithmetic(const char* in, uint32_t size, i = skip_chars(in, size, i, SEPARATORS); } + if(po.first == "=" && ttvar!=nullptr) // categorize as var definition + ttvar->var->definition=true; + if(i >= size) throw PARSE_ERROR( "Unexpected end of file, expecting '))'", i ); if(in[i] != ')') @@ -262,10 +281,10 @@ std::pair parse_manipulation(const char* in, uin i++; } - auto p=parse_varname(in, size, i); - if(p.second == i) + auto p=parse_var(in, size, i, true, true); + if(p.first == nullptr) throw PARSE_ERROR( "Bad variable name", i ); - ret->varname=p.first; + ret->var=p.first; i = p.second; auto pa = parse_arg(in, size, i, "}", NULL, false); @@ -357,14 +376,14 @@ std::pair parse_arg(const char* in, uint32_t size, uint32_t star } else if( in[i] == '$' ) { - auto r=parse_varname(in, size, i+1); - if(r.second > i+1) + auto r=parse_var(in, size, i+1); + if(r.first !=nullptr) { // add previous subarg std::string tmpstr=std::string(in+j, i-j); if(tmpstr!="") ret->add(new string_subarg(tmpstr)); - // add varname + // add var ret->add(new variable_subarg(r.first, true)); j = i = r.second; } @@ -428,14 +447,14 @@ std::pair parse_arg(const char* in, uint32_t size, uint32_t star } else if( in[i] == '$' ) { - auto r=parse_varname(in, size, i+1); - if(r.second > i+1) + auto r=parse_var(in, size, i+1); + if(r.first != nullptr) { // add previous subarg std::string tmpstr=std::string(in+j, i-j); if(tmpstr!="") ret->add(new string_subarg(tmpstr)); - // add varname + // add var ret->add(new variable_subarg(r.first)); j = i = r.second; } @@ -1061,10 +1080,11 @@ std::pair parse_cmd(const char* in, uint32_t size, uint32_t star #endif while(true) // parse var assigns { - auto wp=get_word(in, size, i, VARNAME_END); - if(wp.seconddefinition=true; + i=vp.second+1; arg* ta; if( is_in(in[i], ARG_END) ) // no value : give empty value { @@ -1076,11 +1096,15 @@ std::pair parse_cmd(const char* in, uint32_t size, uint32_t star ta=pp.first; i=pp.second; } - ret->var_assigns.push_back(std::make_pair(wp.first, ta)); + ret->var_assigns.push_back(std::make_pair(vp.first, ta)); i=skip_chars(in, size, i, " \t"); } else + { + if(vp.first != nullptr) + delete vp.first; break; + } } if(!is_in(in[i], SPECIAL_TOKENS)) @@ -1258,7 +1282,7 @@ std::pair parse_for(const char* in, uint32_t size, uint32_ if(!valid_name(wp.first)) throw PARSE_ERROR( strf("Bad identifier in for clause: '%s'", wp.first.c_str()), i ); - ret->varname = wp.first; + ret->var = new variable(wp.first, nullptr, true); i=skip_chars(in, size, wp.second, SPACES); // in @@ -1482,7 +1506,7 @@ shmain* parse_text(const char* in, uint32_t size, std::string const& filename) i = skip_unread(in, size, i); // do bash reading std::string binshebang = basename(ret->shebang); - g_bash = binshebang == "bash" || binshebang == "lxsh" || options["debashify"]; + g_bash = binshebang == "bash" || binshebang == "lxsh"; // parse all commands auto pp=parse_list_until(in, size, i, 0); ret->lst=pp.first; diff --git a/src/processing.cpp b/src/processing.cpp index dc244bf..c9ebff4 100644 --- a/src/processing.cpp +++ b/src/processing.cpp @@ -263,31 +263,21 @@ bool r_get_var(_obj* in, countmap_t* defmap, countmap_t* callmap) { switch(in->type) { - case _obj::subarg_variable: { - variable_subarg* t = dynamic_cast(in); - if(!callmap->insert( std::make_pair(t->varname, 1) ).second) - (*callmap)[t->varname]++; - }; break; - case _obj::arithmetic_variable: { - variable_arithmetic* t = dynamic_cast(in); - if(!callmap->insert( std::make_pair(t->varname, 1) ).second) - (*callmap)[t->varname]++; - }; break; - case _obj::subarg_manipulation: { - manipulation_subarg* t = dynamic_cast(in); - if(!callmap->insert( std::make_pair(t->varname, 1) ).second) - (*callmap)[t->varname]++; - }; break; - case _obj::block_for: { - for_block* t = dynamic_cast(in); - if(!defmap->insert( std::make_pair(t->varname, 1) ).second) - (*defmap)[t->varname]++; + case _obj::_variable: { + variable* t = dynamic_cast(in); + if(t->definition) + { + if(!defmap->insert( std::make_pair(t->varname, 1) ).second) + (*defmap)[t->varname]++; + } + else + { + if(!callmap->insert( std::make_pair(t->varname, 1) ).second) + (*callmap)[t->varname]++; + } }; break; case _obj::block_cmd: { cmd* t = dynamic_cast(in); - for(auto it: t->var_assigns) - if(!defmap->insert( std::make_pair(it.first, 1) ).second) - (*defmap)[it.first]++; if(t->is_argvar()) { for(uint32_t i=1; iargs->size(); i++) @@ -395,8 +385,9 @@ bool r_delete_var(_obj* in, set_t* vars) for(uint32_t j=0; jvar_assigns.size(); j++) { - if( vars->find(c->var_assigns[j].first) != vars->end() ) + if( vars->find(c->var_assigns[j].first->varname) != vars->end() ) { + delete c->var_assigns[j].first; delete c->var_assigns[j].second; c->var_assigns.erase(c->var_assigns.begin()+j); j--;