fix(parse): fix parse of sequential braces

This commit is contained in:
zawz 2022-04-08 15:38:11 +02:00
parent 0903cf41a1
commit f93447e7dc
8 changed files with 31 additions and 16 deletions

View file

@ -109,7 +109,7 @@ std::pair<arg_t*, parse_context> parse_arg(parse_context ct, const char* end=ARG
// redirect parser
std::pair<redirect_t*, parse_context> parse_redirect(parse_context ct);
// arglist parser
std::pair<arglist_t*, parse_context> parse_arglist(parse_context ct, bool hard_error=false, std::vector<redirect_t*>* redirs=nullptr);
std::pair<arglist_t*, parse_context> parse_arglist(parse_context ct, bool hard_error=false, std::vector<redirect_t*>* redirs=nullptr, bool stop_on_brace=false);
// block parsers
std::pair<block_t*, parse_context> parse_block(parse_context ct);
std::pair<cmd_t*, parse_context> parse_cmd(parse_context ct);

View file

@ -233,6 +233,8 @@ public:
std::vector<std::string> strargs(uint32_t start);
// get first argument as string
std::string first_arg_string();
// potentially expands into more arguments than its size
bool can_expand();

View file

@ -236,17 +236,18 @@ int exec_process(std::string const& runtime, std::vector<std::string> const& arg
if(mkfifo(fifopath.c_str(), 0700)<0)
throw std::runtime_error("Cannot create fifo "+fifopath);
for(uint32_t i=0; i<strargs.size(); i++)
runargs.push_back((char*) strargs[i].c_str());
runargs.push_back((char*) fifopath.c_str());
for(uint32_t i=0; i<args.size(); i++)
runargs.push_back((char*) args[i].c_str());
runargs.push_back(NULL);
pid_t pid=0;
FILE* ffd=0;
try
{
for(uint32_t i=0; i<strargs.size(); i++)
runargs.push_back((char*) strargs[i].c_str());
runargs.push_back((char*) fifopath.c_str());
for(uint32_t i=0; i<args.size(); i++)
runargs.push_back((char*) args[i].c_str());
runargs.push_back(NULL);
pid = forkexec(runargs[0], runargs.data());
ffd = fopen(fifopath.c_str(), "w");
if(options["debashify"])

View file

@ -823,7 +823,7 @@ std::pair<redirect_t*, parse_context> parse_redirect(parse_context ctx)
// must start at a read char
// first char has to be read
// ends at either &|;\n#()
std::pair<arglist_t*, parse_context> parse_arglist(parse_context ctx, bool hard_error, std::vector<redirect_t*>* redirs)
std::pair<arglist_t*, parse_context> parse_arglist(parse_context ctx, bool hard_error, std::vector<redirect_t*>* redirs, bool stop_on_brace)
{
arglist_t* ret = nullptr;
@ -895,10 +895,12 @@ std::pair<arglist_t*, parse_context> parse_arglist(parse_context ctx, bool hard_
}
else
{
argparse:
argparse: ;
auto pp=parse_arg(ctx);
if(stop_on_brace && pp.first!=nullptr && pp.first->string() == "}")
return std::make_pair(ret, ctx);
if(ret == nullptr)
ret = new arglist_t;
auto pp=parse_arg(ctx);
ret->add(pp.first);
ctx = pp.second;
}
@ -941,7 +943,7 @@ std::pair<pipeline_t*, parse_context> parse_pipeline(parse_context ctx)
ret->add(pp.first);
ctx = pp.second;
ctx.i = skip_chars(ctx, SPACES);
if( ctx.i>=ctx.size || is_in(ctx[ctx.i], PIPELINE_END) || word_eq("||", ctx) )
if( ctx.i>=ctx.size || is_in(ctx[ctx.i], PIPELINE_END) || word_eq("||", ctx) || ctx[ctx.i] == '}' )
return std::make_pair(ret, ctx);
else if( ctx[ctx.i] != '|' )
{
@ -976,7 +978,7 @@ std::pair<condlist_t*, parse_context> parse_condlist(parse_context ctx)
auto pp=parse_pipeline(ctx);
ret->add(pp.first, optype);
ctx = pp.second;
if(ctx.i>=ctx.size || is_in(ctx[ctx.i], CONTROL_END) || is_in(ctx[ctx.i], COMMAND_SEPARATOR)) // end here exactly: used for control later
if(ctx.i>=ctx.size || is_in(ctx[ctx.i], CONTROL_END) || is_in(ctx[ctx.i], COMMAND_SEPARATOR) || ctx[ctx.i] == '}') // end here exactly: used for control later
{
return std::make_pair(ret, ctx);
}
@ -1738,7 +1740,7 @@ std::pair<block_t*, parse_context> parse_block(parse_context ctx)
{
uint32_t j=skip_chars(ctx, SPACES);
ctx.i=j;
auto pp=parse_arglist(ctx, false, &ret->redirs); // in case of redirects
auto pp=parse_arglist(ctx, false, &ret->redirs, true); // in case of redirects
if(pp.first != nullptr)
{
delete pp.first;

View file

@ -227,10 +227,17 @@ std::string arg_t::string()
std::string arg_t::first_sa_string()
{
if(sa.size() <=0 || sa[0]->type != _obj::subarg_string)
return "";
return "";
return dynamic_cast<subarg_string_t*>(sa[0])->val;
}
std::string arglist_t::first_arg_string()
{
if(args.size()<=0 || args[0] == nullptr)
return "";
return args[0]->string();
}
bool arg_t::can_expand()
{
for(auto it: sa)

View file

@ -3,3 +3,5 @@
{ echo tata ; echo a; } | sed 's|a|toto|g'
echo a | { grep a && echo b; }
{ { echo tata ; } }

View file

@ -47,4 +47,4 @@ echo ${!TATA}
for I in A B C ; do
echo "$I"
done > >(grep A)
done 2>&1 > >(grep A)

1
test/err/brace.sh Normal file
View file

@ -0,0 +1 @@
{ ; }