From 36dfd9266e20e2f6a83205c02848215ac3706bac Mon Sep 17 00:00:00 2001 From: zawwz Date: Wed, 6 Jan 2021 12:15:31 +0100 Subject: [PATCH] Implement <() bash process substitution --- include/recursive.hpp | 6 ++++++ include/struc.hpp | 24 +++++++++++++++++++++--- src/debashify.cpp | 3 +-- src/generate.cpp | 8 ++++++++ src/parse.cpp | 21 +++++++++++++++------ 5 files changed, 51 insertions(+), 11 deletions(-) diff --git a/include/recursive.hpp b/include/recursive.hpp index 604005c..7462f9c 100644 --- a/include/recursive.hpp +++ b/include/recursive.hpp @@ -193,6 +193,12 @@ void recurse(bool (&fct)(_obj*, Args...), _obj* o, Args... args) recurse(fct, t->sbsh, args...); break; } + case _obj::subarg_procsub : + { + procsub_subarg* t = dynamic_cast(o); + recurse(fct, t->sbsh, args...); + break; + } default: break; //do nothing } diff --git a/include/struc.hpp b/include/struc.hpp index 16ba85f..ff574bd 100644 --- a/include/struc.hpp +++ b/include/struc.hpp @@ -54,8 +54,12 @@ arg: subarg: can be one of - string -- block: subshell (substitution) +- subshell (command substitution) - arithmetic +- variable +- variable manipulation +- procsub (bash specific process substitution) + > NOTE: MUST be the only subarg in the arg */ @@ -81,9 +85,9 @@ class _obj { public: enum _objtype { - subarg_string, subarg_variable, subarg_subshell, subarg_arithmetic, subarg_manipulation, + subarg_string, subarg_variable, subarg_subshell, subarg_arithmetic, subarg_manipulation, subarg_procsub, _redirect, - _arg, + _arg, arg_procsub, _arglist, _pipeline, _condlist, @@ -108,6 +112,7 @@ class arg : public _obj public: arg() { type=_obj::_arg; } arg(std::string const& str) { type=_obj::_arg; this->setstring(str);} + arg(subarg* in) { type=_obj::_arg; sa.push_back(in); } ~arg() { for(auto it: sa) delete it; } void setstring(std::string const& str); @@ -477,5 +482,18 @@ public: std::string generate(int ind); }; +class procsub_subarg : public subarg +{ +public: + procsub_subarg() { type=_obj::subarg_procsub; sbsh=nullptr; is_output=false; } + procsub_subarg(bool output, subshell* in) { type=_obj::subarg_procsub; sbsh=in; is_output=output; } + ~procsub_subarg() { if(sbsh!=nullptr) delete sbsh; } + + bool is_output; + subshell* sbsh; + + std::string generate(int ind); +}; + #endif //STRUC_HPP diff --git a/src/debashify.cpp b/src/debashify.cpp index 41fbe01..b97076a 100644 --- a/src/debashify.cpp +++ b/src/debashify.cpp @@ -5,7 +5,7 @@ bool debashify_replace_bashtest(cmd* in) { if(in->firstarg_string() == "[[") - throw std::runtime_error("Debashify on '[[' not implemented yet"); + throw std::runtime_error("Debashify on '[[ ]]' not implemented yet"); return false; } @@ -14,7 +14,6 @@ bool debashify_replace_combined_redirects(block* in) { bool has_replaced=false; - for(uint32_t i=0; iredirs.size() ; i++) { if(in->redirs[i]->op == "&>" || in->redirs[i]->op == "&>>" || in->redirs[i]->op == ">&") diff --git a/src/generate.cpp b/src/generate.cpp index 3355b91..cce8f24 100644 --- a/src/generate.cpp +++ b/src/generate.cpp @@ -350,6 +350,14 @@ std::string manipulation_subarg::generate(int ind) return "${" + varname + manip->generate(ind) + "}"; } +std::string procsub_subarg::generate(int ind) +{ + if(is_output) + return '>' + sbsh->generate(ind); + else + return '<' + sbsh->generate(ind); +} + // TEMPLATE // std::string thing::generate(int ind) diff --git a/src/parse.cpp b/src/parse.cpp index 6de3eb4..cb44197 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -542,7 +542,17 @@ std::pair parse_arglist(const char* in, uint32_t size, uint3 } while(i') && in[i+1] == '(' ) // bash specific <() + { + bool is_output = in[i] == '>'; + i+=2; + if(ret == nullptr) + ret = new arglist; + auto ps = parse_subshell(in, size, i); + ret->args.push_back(new arg(new procsub_subarg(is_output, ps.first))); + i=ps.second+1; + } + else if(redirs!=nullptr) { auto pr = parse_redirect(in, size, i); if(pr.first != nullptr) @@ -555,7 +565,7 @@ std::pair parse_arglist(const char* in, uint32_t size, uint3 } else { -argparse: + argparse: if(ret == nullptr) ret = new arglist; auto pp=parse_arg(in, size, i); @@ -564,10 +574,9 @@ argparse: } i = skip_chars(in, size, i, SPACES); if(word_eq("&>", in, size, i)) - // throw PARSE_ERROR("Unsupported &>", i); - continue; + continue; // &> has to be managed in redirects if(word_eq("|&", in, size, i)) - throw PARSE_ERROR("Unsupported |&, use '2>&1 |' instead", i); + throw PARSE_ERROR("Unsupported '|&', use '2>&1 |' instead", i); if(i>=size) return std::make_pair(ret, i); if( is_in(in[i], SPECIAL_TOKENS) ) @@ -1119,7 +1128,7 @@ std::pair parse_for(const char* in, uint32_t size, uint32_ if(wp.first == "in") { i=skip_chars(in, size, wp.second, SPACES); - auto pp = parse_arglist(in, size, i); + auto pp = parse_arglist(in, size, i, false); ret->iter = pp.first; i = pp.second; }