diff --git a/include/parse.hpp b/include/parse.hpp index 083e82a..6d02da6 100644 --- a/include/parse.hpp +++ b/include/parse.hpp @@ -26,6 +26,8 @@ // bash specific #define ARRAY_ARG_END " \t\n;#()&|<>]" +extern const std::vector posix_cmdvar; +extern const std::vector bash_cmdvar; std::string import_file(std::string const& path); diff --git a/include/processing.hpp b/include/processing.hpp index 14e8904..083cde3 100644 --- a/include/processing.hpp +++ b/include/processing.hpp @@ -21,9 +21,6 @@ extern std::regex re_var_exclude; extern std::regex re_fct_exclude; extern const std::regex regex_null; -// globals -extern const std::vector argvar_cmds; - // Object maps (optimizations) extern countmap_t m_vars, m_vardefs, m_varcalls; extern countmap_t m_fcts, m_cmds; @@ -46,6 +43,7 @@ void fctmap_get(_obj* in, std::regex const& exclude); void cmdmap_get(_obj* in, std::regex const& exclude); /** util functions **/ +std::string gen_json_struc(_obj* in); // gen regexes std::regex var_exclude_regex(std::string const& in, bool include_reserved); diff --git a/include/struc.hpp b/include/struc.hpp index c4dfc81..da1b95a 100644 --- a/include/struc.hpp +++ b/include/struc.hpp @@ -86,13 +86,13 @@ public: subarg_string, subarg_variable, subarg_subshell, subarg_arithmetic, subarg_manipulation, subarg_procsub, _variable, _redirect, - _arg, arg_procsub, + _arg, _arglist, _pipeline, _condlist, _list, arithmetic_operation, arithmetic_number, arithmetic_variable, arithmetic_parenthesis, arithmetic_subshell, - block_subshell, block_brace, block_main, block_cmd, block_function, block_case, block_if, block_for, block_while, block_until }; + block_subshell, block_brace, block_main, block_cmd, block_function, block_case, block_if, block_for, block_while }; _objtype type; virtual ~_obj() {;} @@ -128,8 +128,10 @@ public: void insert(uint32_t i, subarg* val); void insert(uint32_t i, arg const& a); + void insert(uint32_t i, std::string const& in); inline void add(subarg* in) { sa.push_back(in); } + void add(std::string const& in); inline size_t size() { return sa.size(); } std::vector sa; @@ -288,7 +290,7 @@ public: class cmd : public block { public: - cmd(arglist* in=nullptr) { type=_obj::block_cmd; args=in; } + cmd(arglist* in=nullptr) { type=_obj::block_cmd; args=in; is_cmdvar=false; } ~cmd() { if(args!=nullptr) delete args; for(auto it: var_assigns) { @@ -309,6 +311,9 @@ public: // preceding var assigns std::vector> var_assigns; + // is a cmdvar type + bool is_cmdvar; + // check if cmd is this (ex: unset) bool is(std::string const& in); // for var assigns in special cmds (export, unset, read, local) diff --git a/include/util.hpp b/include/util.hpp index 53f8d21..c183e40 100644 --- a/include/util.hpp +++ b/include/util.hpp @@ -128,6 +128,15 @@ void concat_sets(std::set& a, std::set const& b) } } +template +bool is_in_vector(T el, std::vector vec) +{ + for(auto it: vec) + if(it == el) + return true; + return false; +} + std::set prune_matching(std::set& in, std::regex re); std::string delete_brackets(std::string const& in); diff --git a/src/generate.cpp b/src/generate.cpp index acf9e39..6ecb0d8 100644 --- a/src/generate.cpp +++ b/src/generate.cpp @@ -313,8 +313,29 @@ std::string cmd::generate(int ind) { std::string ret; // var assigns + 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; + } + for(auto it: var_assigns) - ret += it.first->generate(ind) + it.second->generate(ind) + ' '; + { + if(it.first != nullptr) + ret += it.first->generate(ind); + if(it.second != nullptr) + ret += it.second->generate(ind); + ret += ' '; + } if(args!=nullptr && args->size()>0) { diff --git a/src/minimize.cpp b/src/minimize.cpp index 4682a44..b15381d 100644 --- a/src/minimize.cpp +++ b/src/minimize.cpp @@ -62,22 +62,6 @@ bool r_replace_var(_obj* in, strmap_t* varmap) if(el!=varmap->end()) t->varname = el->second; }; break; - case _obj::block_cmd: { - cmd* t = dynamic_cast(in); - for(auto it: t->subarg_vars()) - { - string_subarg* tss = dynamic_cast(it); - auto el=varmap->find(get_varname(tss->val)); - if(el!=varmap->end()) - { - size_t tpos=tss->val.find('='); - if(tpos == std::string::npos) - tss->val = el->second; - else - tss->val = el->second + tss->val.substr(tpos); - } - } - }; break; default: break; } return true; diff --git a/src/parse.cpp b/src/parse.cpp index 675ebee..52aa04f 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -18,6 +18,9 @@ bool g_bash=false; #define PARSE_ERROR(str, i) ztd::format_error(str, "", in, i) // constants +const std::vector posix_cmdvar = { "export", "unset", "local", "read" }; +const std::vector bash_cmdvar = { "readonly", "declare", "typeset" }; + const std::vector arithmetic_precedence_operators = { "!", "~", "+", "-" }; const std::vector arithmetic_operators = { "+", "-", "*", "/", "=", "==", "!=", "&", "|", "^", "<<", ">>", "&&", "||" }; @@ -339,7 +342,7 @@ std::pair parse_arg(const char* in, uint32_t size, uint32_t star // add previous subarg std::string tmpstr=std::string(in+j, i-j); if(tmpstr!="") - ret->add(new string_subarg(tmpstr)); + ret->add(tmpstr); // get arithmetic auto r=parse_arithmetic(in, size, i+3); arithmetic_subarg* tt = new arithmetic_subarg(r.first); @@ -356,7 +359,7 @@ std::pair parse_arg(const char* in, uint32_t size, uint32_t star // add previous subarg std::string tmpstr=std::string(in+j, i-j); if(tmpstr!="") - ret->add(new string_subarg(tmpstr)); + ret->add(tmpstr); // get subshell auto r=parse_subshell(in, size, i+2); ret->add(new subshell_subarg(r.first, true)); @@ -367,7 +370,7 @@ std::pair parse_arg(const char* in, uint32_t size, uint32_t star // add previous subarg std::string tmpstr=std::string(in+j, i-j); if(tmpstr!="") - ret->add(new string_subarg(tmpstr)); + ret->add(tmpstr); // get manipulation auto r=parse_manipulation(in, size, i+2); r.first->quoted=true; @@ -382,7 +385,7 @@ std::pair parse_arg(const char* in, uint32_t size, uint32_t star // add previous subarg std::string tmpstr=std::string(in+j, i-j); if(tmpstr!="") - ret->add(new string_subarg(tmpstr)); + ret->add(tmpstr); // add var ret->add(new variable_subarg(r.first, true)); j = i = r.second; @@ -413,7 +416,7 @@ std::pair parse_arg(const char* in, uint32_t size, uint32_t star // add previous subarg std::string tmpstr=std::string(in+j, i-j); if(tmpstr!="") - ret->add(new string_subarg(tmpstr)); + ret->add(tmpstr); // get arithmetic auto r=parse_arithmetic(in, size, i+3); ret->add(new arithmetic_subarg(r.first)); @@ -428,7 +431,7 @@ std::pair parse_arg(const char* in, uint32_t size, uint32_t star // add previous subarg std::string tmpstr=std::string(in+j, i-j); if(tmpstr!="") - ret->add(new string_subarg(tmpstr)); + ret->add(tmpstr); // get subshell auto r=parse_subshell(in, size, i+2); ret->add(new subshell_subarg(r.first, false)); @@ -439,7 +442,7 @@ std::pair parse_arg(const char* in, uint32_t size, uint32_t star // add previous subarg std::string tmpstr=std::string(in+j, i-j); if(tmpstr!="") - ret->add(new string_subarg(tmpstr)); + ret->add(tmpstr); // get manipulation auto r=parse_manipulation(in, size, i+2); ret->add(r.first); @@ -453,7 +456,7 @@ std::pair parse_arg(const char* in, uint32_t size, uint32_t star // add previous subarg std::string tmpstr=std::string(in+j, i-j); if(tmpstr!="") - ret->add(new string_subarg(tmpstr)); + ret->add(tmpstr); // add var ret->add(new variable_subarg(r.first)); j = i = r.second; @@ -468,7 +471,7 @@ std::pair parse_arg(const char* in, uint32_t size, uint32_t star // add string subarg std::string val=std::string(in+j, i-j); if(val != "") - ret->add(new string_subarg(val)); + ret->add(val); #ifndef NO_PARSE_CATCH } @@ -603,7 +606,7 @@ std::pair parse_redirect(const char* in, uint32_t size, uin std::string tmpparse=std::string(in+j, i-j); auto pval = parse_arg(tmpparse.c_str(), tmpparse.size(), 0, NULL); ret->target = pval.first; - ret->target->insert(0, new string_subarg(delimitor+"\n")); + ret->target->insert(0, delimitor+"\n"); } else { @@ -1099,6 +1102,93 @@ std::pair parse_function(const char* in, uint32_t size, uin return std::make_pair(ret, i); } +// parse only var assigns +uint32_t parse_cmd_varassigns(cmd* ret, const char* in, uint32_t size, uint32_t start, bool cmdassign=false, std::string const& cmd="") +{ + uint32_t i=start; + bool forbid_assign=false; + bool forbid_special=false; + if(cmdassign && (cmd == "read" || cmd == "unset") ) + forbid_assign=true; + if(cmdassign && (forbid_special || cmd == "export") ) + forbid_special=true; + + while(idefinition=true; + if(vp.first != nullptr && vp.secondinsert(0,"("); + ta->add(")"); + i=pp.second+1; + } + else if( is_in(in[i], ARG_END) ) // no value : give empty value + { + ta = new arg; + } + else + { + auto pp=parse_arg(in, size, i); + ta=pp.first; + i=pp.second; + } + ta->insert(0, strop); + ret->var_assigns.push_back(std::make_pair(vp.first, ta)); + i=skip_chars(in, size, i, SPACES); + } + else + { + if(cmdassign) + { + if(vp.first != nullptr && is_in(in[vp.second], ARG_END) ) + { + ret->var_assigns.push_back(std::make_pair(vp.first, nullptr)); + i=vp.second; + } + else + { + delete vp.first; + auto pp=parse_arg(in, size, i); + ret->var_assigns.push_back(std::make_pair(nullptr, pp.first)); + i=pp.second; + } + i=skip_chars(in, size, i, SPACES); + } + else + { + if(vp.first != nullptr) + delete vp.first; + break; + } + } + } + return i; +} + // must start at read char std::pair parse_cmd(const char* in, uint32_t size, uint32_t start) { @@ -1110,42 +1200,22 @@ std::pair parse_cmd(const char* in, uint32_t size, uint32_t star { #endif ; - while(true) // parse var assigns + i=parse_cmd_varassigns(ret, in, size, i); + + auto wp=get_word(in, size, i, ARG_END); + if(is_in_vector(wp.first, posix_cmdvar) || is_in_vector(wp.first, bash_cmdvar)) { - auto vp=parse_var(in, size, i, false, true); - if(vp.first != nullptr && vp.secondinsert(0, new string_subarg("=(") ); - ta->add(new string_subarg(")") ); - i=pp.second+1; - } - else if( is_in(in[i], ARG_END) ) // no value : give empty value - { - ta = new arg("="); - } - else - { - auto pp=parse_arg(in, size, i); - ta=pp.first; - ta->insert(0, new string_subarg("=")); - i=pp.second; - } - 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(!g_bash && is_in_vector(wp.first, bash_cmdvar)) + throw PARSE_ERROR("bash specific: "+wp.first, i); + if(ret->var_assigns.size()>0) + throw PARSE_ERROR("Unallowed preceding variables on "+wp.first, start); + + ret->args = new arglist; + ret->args->add(new arg(wp.first)); + ret->is_cmdvar=true; + i=skip_chars(in, size, wp.second, SPACES); + + i=parse_cmd_varassigns(ret, in, size, i, true, wp.first); } if(!is_in(in[i], SPECIAL_TOKENS)) diff --git a/src/processing.cpp b/src/processing.cpp index c9ebff4..3d8d920 100644 --- a/src/processing.cpp +++ b/src/processing.cpp @@ -13,10 +13,6 @@ std::regex re_fct_exclude; const std::regex regex_null; -// globals - -const std::vector argvar_cmds = { "export", "unset", "local", "read", "readonly", "declare" }; - // Object maps countmap_t m_vars, m_vardefs, m_varcalls; @@ -158,15 +154,12 @@ std::string get_varname(arg* in) bool cmd_is_argvar(std::string const& in) { - for(auto it: argvar_cmds) - if(in == it) - return true; - return false; + return is_in_vector(in, posix_cmdvar) || is_in_vector(in, bash_cmdvar); } bool cmd::is_argvar() { - return cmd_is_argvar(this->firstarg_string()); + return is_cmdvar; } bool cmd::is(std::string const& in) @@ -248,8 +241,11 @@ void add_unset_variables(shmain* sh, std::regex const& exclude) { cmd* unset_cmd = new cmd; unset_cmd->add(new arg("unset")); + unset_cmd->is_cmdvar=true; for(auto it: m_vars) - unset_cmd->add(new arg(it.first)); + { + unset_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); } @@ -276,18 +272,6 @@ bool r_get_var(_obj* in, countmap_t* defmap, countmap_t* callmap) (*callmap)[t->varname]++; } }; break; - case _obj::block_cmd: { - cmd* t = dynamic_cast(in); - if(t->is_argvar()) - { - for(uint32_t i=1; iargs->size(); i++) - { - std::string varname=get_varname(t->args->args[i]); - if( varname != "" && !defmap->insert( std::make_pair(varname, 1) ).second ) - (*defmap)[varname]++; - } - } - }; break; default: break; } return true; @@ -301,9 +285,10 @@ bool r_get_unsets(_obj* in, set_t* unsets) cmd* t = dynamic_cast(in); if(t->is("unset")) { - for(uint32_t i=1; iargs->size(); i++) + for(auto it: t->var_assigns) { - unsets->insert(t->args->args[i]->string()); + if(it.first != nullptr) + unsets->insert(it.first->varname); } } }; break; @@ -379,37 +364,25 @@ bool r_delete_var(_obj* in, set_t* vars) { block* tb = t->cls[i]->first_block(); bool to_delete=false; + bool has_deleted=false; if(tb != nullptr && tb->type == _obj::block_cmd) { cmd* c = dynamic_cast(tb); for(uint32_t j=0; jvar_assigns.size(); j++) { - if( vars->find(c->var_assigns[j].first->varname) != vars->end() ) + if( c->var_assigns[j].first == nullptr || vars->find(c->var_assigns[j].first->varname) != vars->end() ) { - delete c->var_assigns[j].first; - delete c->var_assigns[j].second; + if(c->var_assigns[j].first != nullptr) + delete c->var_assigns[j].first; + if(c->var_assigns[j].second != nullptr) + delete c->var_assigns[j].second; c->var_assigns.erase(c->var_assigns.begin()+j); + has_deleted=true; j--; } } - - if(c->is_argvar()) - { - for(uint32_t j=1; jargs->size(); j++) - { - std::string varname=get_varname(c->args->args[j]); - if( varname != "" && vars->find( varname ) != vars->end() ) - { - delete c->args->args[j]; - c->args->args.erase(c->args->args.begin()+j); - j--; - } - } - if(c->args->size()<=1) - to_delete=true; - } - if(c->var_assigns.size()<=0 && c->arglist_size()<=0) + if(has_deleted && c->var_assigns.size()<=0 && (c->arglist_size()<=0 || c->is_cmdvar) ) to_delete=true; } @@ -425,3 +398,374 @@ bool r_delete_var(_obj* in, set_t* vars) } return true; } + +std::string quote_string(std::string const& in) +{ + return '"' + stringReplace(in, "\"", "\\\"") + '"'; +} + +std::string gen_json(std::vector> const& vec) +{ + std::string ret; + for(auto it: vec) + { + ret += it.first + ":" + it.second + ','; + } + if(ret != "") + ret.pop_back(); + return "{" + ret + "}"; +} + +std::string gen_json(std::vector const& vec) +{ + std::string ret; + for(auto it: vec) + { + ret += it + ','; + } + if(ret != "") + ret.pop_back(); + return "[" + ret + "]"; +} + +std::string boolstring(bool in) +{ + if(in) + return "true"; + else + return "false"; +} + +std::string gen_json_struc(_obj* o) +{ + if(o==nullptr) + return "{}"; + std::vector> vec; + switch(o->type) + { + case _obj::_variable : + { + variable* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("variable") ) ); + vec.push_back(std::make_pair(quote_string("varname"), quote_string(t->varname))); + vec.push_back(std::make_pair(quote_string("definition"), boolstring(t->definition))); + vec.push_back(std::make_pair(quote_string("index"), gen_json_struc(t->index))); + break; + } + case _obj::_redirect : + { + redirect* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("redirect") ) ); + vec.push_back(std::make_pair(quote_string("op"), quote_string(t->op))); + vec.push_back(std::make_pair(quote_string("target"), gen_json_struc(t->target))); + break; + } + case _obj::_arg : + { + arg* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("arg") ) ); + std::vector tvec; + for(auto it: t->sa) + tvec.push_back(gen_json_struc(it)); + vec.push_back(std::make_pair(quote_string("sa"), gen_json(tvec))); + break; + } + case _obj::_arglist : + { + arglist* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("arglist") ) ); + std::vector tvec; + for(auto it: t->args) + tvec.push_back(gen_json_struc(it)); + vec.push_back(std::make_pair(quote_string("args"), gen_json(tvec))); + break; + } + case _obj::_pipeline : + { + pipeline* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("pipeline") ) ); + vec.push_back(std::make_pair(quote_string("negated"), boolstring(t->negated) ) ); + std::vector tvec; + for(auto it: t->cmds) + tvec.push_back(gen_json_struc(it)); + vec.push_back(std::make_pair(quote_string("cmds"), gen_json(tvec))); + break; + } + case _obj::_condlist : + { + condlist* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("condlist") ) ); + vec.push_back(std::make_pair(quote_string("parallel"), boolstring(t->parallel) ) ); + std::vector tvec; + for(auto it: t->pls) + tvec.push_back(gen_json_struc(it)); + vec.push_back(std::make_pair(quote_string("pls"), gen_json(tvec))); + + std::vector ttvec; + for(auto it: t->or_ops) + { + ttvec.push_back(boolstring(it)); + } + vec.push_back(std::make_pair(quote_string("or_ops"), gen_json(ttvec))); + break; + } + case _obj::_list : + { + list* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("list") ) ); + std::vector tvec; + for(auto it: t->cls) + tvec.push_back(gen_json_struc(it)); + vec.push_back(std::make_pair(quote_string("cls"), gen_json(tvec))); + break; + } + case _obj::block_subshell : + { + subshell* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("subshell") ) ); + + vec.push_back(std::make_pair(quote_string("lst"), gen_json_struc(t->lst))); + + std::vector tvec; + for(auto it: t->redirs) + tvec.push_back(gen_json_struc(it)); + vec.push_back(std::make_pair(quote_string("redirs"), gen_json(tvec))); + + break; + } + case _obj::block_brace : + { + brace* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("brace") ) ); + + vec.push_back(std::make_pair(quote_string("lst"), gen_json_struc(t->lst))); + + std::vector tvec; + for(auto it: t->redirs) + tvec.push_back(gen_json_struc(it)); + vec.push_back(std::make_pair(quote_string("redirs"), gen_json(tvec))); + + break; + } + case _obj::block_main : + { + shmain* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("main") ) ); + vec.push_back(std::make_pair(quote_string("shebang"), quote_string(t->shebang) ) ); + + vec.push_back(std::make_pair(quote_string("lst"), gen_json_struc(t->lst))); + + std::vector tvec; + for(auto it: t->redirs) + tvec.push_back(gen_json_struc(it)); + vec.push_back(std::make_pair(quote_string("redirs"), gen_json(tvec))); + + break; + } + case _obj::block_function : + { + function* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("function") ) ); + vec.push_back(std::make_pair(quote_string("name"), quote_string(t->name) ) ); + + vec.push_back(std::make_pair(quote_string("lst"), gen_json_struc(t->lst))); + + std::vector tvec; + for(auto it: t->redirs) + tvec.push_back(gen_json_struc(it)); + vec.push_back(std::make_pair(quote_string("redirs"), gen_json(tvec))); + + break; + } + case _obj::block_cmd : + { + cmd* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("cmd") ) ); + + vec.push_back(std::make_pair(quote_string("args"), gen_json_struc(t->args))); + vec.push_back(std::make_pair(quote_string("is_cmdvar"), boolstring(t->is_cmdvar))); + + std::vector aa; + for(auto it: t->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)) ); + aa.push_back(gen_json(ttvec)); + } + vec.push_back(std::make_pair( quote_string("var_assigns"), gen_json(aa))); + + std::vector tvec; + for(auto it: t->redirs) + tvec.push_back(gen_json_struc(it)); + vec.push_back(std::make_pair(quote_string("redirs"), gen_json(tvec))); + + break; + } + case _obj::block_case : + { + case_block* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("case") ) ); + + vec.push_back(std::make_pair(quote_string("carg"), gen_json_struc(t->carg))); + + // [ {matchers:[], exec:{}} ] + // cases + std::vector tt; + for(auto sc: t->cases) + { + std::vector> onecase; + std::vector matchers; + for(auto it: sc.first) + matchers.push_back(gen_json_struc(it)); + onecase.push_back( std::make_pair(quote_string("matcher"), gen_json(matchers)) ); + onecase.push_back( std::make_pair(quote_string("execution"), gen_json_struc(sc.second)) ); + tt.push_back(gen_json(onecase)); + } + vec.push_back( std::make_pair(quote_string("cases"),gen_json(tt)) ); + + std::vector tvec; + for(auto it: t->redirs) + tvec.push_back(gen_json_struc(it)); + vec.push_back(std::make_pair(quote_string("redirs"), gen_json(tvec))); + + break; + } + case _obj::block_if : + { + if_block* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("if") ) ); + + std::vector condblocks; + // ifs + for(auto sc: t->blocks) + { + std::vector > one_cond; + one_cond.push_back(std::make_pair(quote_string("condition"), gen_json_struc(sc.first) ) ); + one_cond.push_back(std::make_pair(quote_string("execution"), gen_json_struc(sc.second) ) ); + condblocks.push_back(gen_json(one_cond)); + } + vec.push_back( std::make_pair(quote_string("blocks"), gen_json(condblocks)) ); + // else + vec.push_back(std::make_pair(quote_string("else_lst"), gen_json_struc(t->else_lst))); + + std::vector tvec; + for(auto it: t->redirs) + tvec.push_back(gen_json_struc(it)); + vec.push_back(std::make_pair(quote_string("redirs"), gen_json(tvec))); + + break; + } + case _obj::block_for : + { + for_block* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("for") ) ); + vec.push_back(std::make_pair(quote_string("var"), gen_json_struc(t->var))); + vec.push_back(std::make_pair(quote_string("iter"), gen_json_struc(t->iter))); + vec.push_back(std::make_pair(quote_string("ops"), gen_json_struc(t->ops))); + + std::vector tvec; + for(auto it: t->redirs) + tvec.push_back(gen_json_struc(it)); + vec.push_back(std::make_pair(quote_string("redirs"), gen_json(tvec))); + + break; + } + case _obj::block_while : + { + while_block* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("while") ) ); + vec.push_back(std::make_pair(quote_string("cond"), gen_json_struc(t->cond) ) ); + vec.push_back(std::make_pair(quote_string("ops"), gen_json_struc(t->ops) ) ); + + std::vector tvec; + for(auto it: t->redirs) + tvec.push_back(gen_json_struc(it)); + vec.push_back(std::make_pair(quote_string("redirs"), gen_json(tvec))); + + break; + } + case _obj::subarg_variable : + { + variable_subarg* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("subarg_variable") ) ); + vec.push_back(std::make_pair(quote_string("var"), gen_json_struc(t->var) ) ); + break; + } + case _obj::subarg_subshell : + { + subshell_subarg* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("subarg_subshell") ) ); + vec.push_back(std::make_pair(quote_string("sbsh"), gen_json_struc(t->sbsh) ) ); + break; + } + case _obj::subarg_manipulation : + { + manipulation_subarg* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("subarg_manipulation") ) ); + vec.push_back(std::make_pair(quote_string("size"), boolstring(t->size) ) ); + vec.push_back(std::make_pair(quote_string("var"), gen_json_struc(t->var) ) ); + vec.push_back(std::make_pair(quote_string("manip"), gen_json_struc(t->manip) ) ); + break; + } + case _obj::subarg_procsub : + { + procsub_subarg* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("subarg_procsub") ) ); + vec.push_back(std::make_pair(quote_string("is_output"), boolstring(t->is_output) ) ); + vec.push_back(std::make_pair(quote_string("sbsh"), gen_json_struc(t->sbsh) ) ); + break; + } + case _obj::subarg_arithmetic : + { + arithmetic_subarg* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("subarg_arithmetic") ) ); + vec.push_back(std::make_pair(quote_string("arith"), gen_json_struc(t->arith) ) ); + break; + } + case _obj::subarg_string : + { + string_subarg* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("subarg_string") ) ); + vec.push_back(std::make_pair(quote_string("val"), quote_string(t->val) ) ); + break; + } + case _obj::arithmetic_variable : + { + variable_arithmetic* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("arithmetic_variable") ) ); + vec.push_back(std::make_pair(quote_string("var"), gen_json_struc(t->var) ) ); + break; + } + case _obj::arithmetic_subshell : + { + subshell_arithmetic* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("arithmetic_subshell") ) ); + vec.push_back(std::make_pair(quote_string("sbsh"), gen_json_struc(t->sbsh) ) ); + break; + } + case _obj::arithmetic_operation : + { + operation_arithmetic* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("arithmetic_operation") ) ); + vec.push_back(std::make_pair(quote_string("val1"), gen_json_struc(t->val1) ) ); + vec.push_back(std::make_pair(quote_string("val2"), gen_json_struc(t->val2) ) ); + break; + } + case _obj::arithmetic_parenthesis : + { + parenthesis_arithmetic* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("arithmetic_parenthesis") ) ); + vec.push_back(std::make_pair(quote_string("val"), gen_json_struc(t->val) ) ); + break; + } + case _obj::arithmetic_number : + { + number_arithmetic* t = dynamic_cast(o); + vec.push_back(std::make_pair(quote_string("type"), quote_string("arithmetic_number") ) ); + vec.push_back(std::make_pair(quote_string("val"), quote_string(t->val) ) ); + break; + } + } + return gen_json(vec); +} diff --git a/src/resolve.cpp b/src/resolve.cpp index 760ba8e..13dc5be 100644 --- a/src/resolve.cpp +++ b/src/resolve.cpp @@ -226,6 +226,10 @@ std::pair< std::vector , bool > resolve_condlist(condlist* in, shmain std::pair< std::vector , bool > resolve_arg(arg* in, shmain* parent, bool forcequote=false) { std::vector ret; + if(in == nullptr) + { + return std::make_pair(ret, false); + } arg* ta=nullptr; bool has_resolved=false; uint32_t j=0; diff --git a/src/struc_helper.cpp b/src/struc_helper.cpp index 83a0025..676084f 100644 --- a/src/struc_helper.cpp +++ b/src/struc_helper.cpp @@ -215,6 +215,15 @@ void condlist::prune_first_cmd() // add/extend +void arg::insert(uint32_t i, std::string const& in) +{ + this->insert(i, new string_subarg(in)); +} +void arg::add(std::string const& in) +{ + this->add(new string_subarg(in)); +} + void arg::insert(uint32_t i, subarg* val) { sa.insert(sa.begin()+i, val);