Implement <() bash process substitution

This commit is contained in:
zawwz 2021-01-06 12:15:31 +01:00
parent c199969b63
commit 36dfd9266e
5 changed files with 51 additions and 11 deletions

View file

@ -193,6 +193,12 @@ void recurse(bool (&fct)(_obj*, Args...), _obj* o, Args... args)
recurse(fct, t->sbsh, args...); recurse(fct, t->sbsh, args...);
break; break;
} }
case _obj::subarg_procsub :
{
procsub_subarg* t = dynamic_cast<procsub_subarg*>(o);
recurse(fct, t->sbsh, args...);
break;
}
default: break; //do nothing default: break; //do nothing
} }

View file

@ -54,8 +54,12 @@ arg:
subarg: can be one of subarg: can be one of
- string - string
- block: subshell (substitution) - subshell (command substitution)
- arithmetic - 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: public:
enum _objtype { 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, _redirect,
_arg, _arg, arg_procsub,
_arglist, _arglist,
_pipeline, _pipeline,
_condlist, _condlist,
@ -108,6 +112,7 @@ class arg : public _obj
public: public:
arg() { type=_obj::_arg; } arg() { type=_obj::_arg; }
arg(std::string const& str) { type=_obj::_arg; this->setstring(str);} 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; } ~arg() { for(auto it: sa) delete it; }
void setstring(std::string const& str); void setstring(std::string const& str);
@ -477,5 +482,18 @@ public:
std::string generate(int ind); 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 #endif //STRUC_HPP

View file

@ -5,7 +5,7 @@
bool debashify_replace_bashtest(cmd* in) bool debashify_replace_bashtest(cmd* in)
{ {
if(in->firstarg_string() == "[[") if(in->firstarg_string() == "[[")
throw std::runtime_error("Debashify on '[[' not implemented yet"); throw std::runtime_error("Debashify on '[[ ]]' not implemented yet");
return false; return false;
} }
@ -14,7 +14,6 @@ bool debashify_replace_combined_redirects(block* in)
{ {
bool has_replaced=false; bool has_replaced=false;
for(uint32_t i=0; i<in->redirs.size() ; i++) for(uint32_t i=0; i<in->redirs.size() ; i++)
{ {
if(in->redirs[i]->op == "&>" || in->redirs[i]->op == "&>>" || in->redirs[i]->op == ">&") if(in->redirs[i]->op == "&>" || in->redirs[i]->op == "&>>" || in->redirs[i]->op == ">&")

View file

@ -350,6 +350,14 @@ std::string manipulation_subarg::generate(int ind)
return "${" + varname + manip->generate(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 // TEMPLATE
// std::string thing::generate(int ind) // std::string thing::generate(int ind)

View file

@ -542,7 +542,17 @@ std::pair<arglist*, uint32_t> parse_arglist(const char* in, uint32_t size, uint3
} }
while(i<size) while(i<size)
{ {
if(redirs!=nullptr) if(i+1 < size && (in[i] == '<' || in[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); auto pr = parse_redirect(in, size, i);
if(pr.first != nullptr) if(pr.first != nullptr)
@ -555,7 +565,7 @@ std::pair<arglist*, uint32_t> parse_arglist(const char* in, uint32_t size, uint3
} }
else else
{ {
argparse: argparse:
if(ret == nullptr) if(ret == nullptr)
ret = new arglist; ret = new arglist;
auto pp=parse_arg(in, size, i); auto pp=parse_arg(in, size, i);
@ -564,10 +574,9 @@ argparse:
} }
i = skip_chars(in, size, i, SPACES); i = skip_chars(in, size, i, SPACES);
if(word_eq("&>", in, size, i)) if(word_eq("&>", in, size, i))
// throw PARSE_ERROR("Unsupported &>", i); continue; // &> has to be managed in redirects
continue;
if(word_eq("|&", in, size, i)) 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) if(i>=size)
return std::make_pair(ret, i); return std::make_pair(ret, i);
if( is_in(in[i], SPECIAL_TOKENS) ) if( is_in(in[i], SPECIAL_TOKENS) )
@ -1119,7 +1128,7 @@ std::pair<for_block*, uint32_t> parse_for(const char* in, uint32_t size, uint32_
if(wp.first == "in") if(wp.first == "in")
{ {
i=skip_chars(in, size, wp.second, SPACES); 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; ret->iter = pp.first;
i = pp.second; i = pp.second;
} }