fix(parse): fix parse of sequential braces
This commit is contained in:
parent
0903cf41a1
commit
f93447e7dc
8 changed files with 31 additions and 16 deletions
|
|
@ -109,7 +109,7 @@ std::pair<arg_t*, parse_context> parse_arg(parse_context ct, const char* end=ARG
|
||||||
// redirect parser
|
// redirect parser
|
||||||
std::pair<redirect_t*, parse_context> parse_redirect(parse_context ct);
|
std::pair<redirect_t*, parse_context> parse_redirect(parse_context ct);
|
||||||
// arglist parser
|
// 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
|
// block parsers
|
||||||
std::pair<block_t*, parse_context> parse_block(parse_context ct);
|
std::pair<block_t*, parse_context> parse_block(parse_context ct);
|
||||||
std::pair<cmd_t*, parse_context> parse_cmd(parse_context ct);
|
std::pair<cmd_t*, parse_context> parse_cmd(parse_context ct);
|
||||||
|
|
|
||||||
|
|
@ -233,6 +233,8 @@ public:
|
||||||
|
|
||||||
std::vector<std::string> strargs(uint32_t start);
|
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
|
// potentially expands into more arguments than its size
|
||||||
bool can_expand();
|
bool can_expand();
|
||||||
|
|
||||||
|
|
|
||||||
15
src/exec.cpp
15
src/exec.cpp
|
|
@ -236,17 +236,18 @@ int exec_process(std::string const& runtime, std::vector<std::string> const& arg
|
||||||
if(mkfifo(fifopath.c_str(), 0700)<0)
|
if(mkfifo(fifopath.c_str(), 0700)<0)
|
||||||
throw std::runtime_error("Cannot create fifo "+fifopath);
|
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;
|
pid_t pid=0;
|
||||||
FILE* ffd=0;
|
FILE* ffd=0;
|
||||||
try
|
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());
|
pid = forkexec(runargs[0], runargs.data());
|
||||||
ffd = fopen(fifopath.c_str(), "w");
|
ffd = fopen(fifopath.c_str(), "w");
|
||||||
if(options["debashify"])
|
if(options["debashify"])
|
||||||
|
|
|
||||||
|
|
@ -823,7 +823,7 @@ std::pair<redirect_t*, parse_context> parse_redirect(parse_context ctx)
|
||||||
// must start at a read char
|
// must start at a read char
|
||||||
// first char has to be read
|
// first char has to be read
|
||||||
// ends at either &|;\n#()
|
// 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;
|
arglist_t* ret = nullptr;
|
||||||
|
|
||||||
|
|
@ -895,10 +895,12 @@ std::pair<arglist_t*, parse_context> parse_arglist(parse_context ctx, bool hard_
|
||||||
}
|
}
|
||||||
else
|
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)
|
if(ret == nullptr)
|
||||||
ret = new arglist_t;
|
ret = new arglist_t;
|
||||||
auto pp=parse_arg(ctx);
|
|
||||||
ret->add(pp.first);
|
ret->add(pp.first);
|
||||||
ctx = pp.second;
|
ctx = pp.second;
|
||||||
}
|
}
|
||||||
|
|
@ -941,7 +943,7 @@ std::pair<pipeline_t*, parse_context> parse_pipeline(parse_context ctx)
|
||||||
ret->add(pp.first);
|
ret->add(pp.first);
|
||||||
ctx = pp.second;
|
ctx = pp.second;
|
||||||
ctx.i = skip_chars(ctx, SPACES);
|
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);
|
return std::make_pair(ret, ctx);
|
||||||
else if( ctx[ctx.i] != '|' )
|
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);
|
auto pp=parse_pipeline(ctx);
|
||||||
ret->add(pp.first, optype);
|
ret->add(pp.first, optype);
|
||||||
ctx = pp.second;
|
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);
|
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);
|
uint32_t j=skip_chars(ctx, SPACES);
|
||||||
ctx.i=j;
|
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)
|
if(pp.first != nullptr)
|
||||||
{
|
{
|
||||||
delete pp.first;
|
delete pp.first;
|
||||||
|
|
|
||||||
|
|
@ -227,10 +227,17 @@ std::string arg_t::string()
|
||||||
std::string arg_t::first_sa_string()
|
std::string arg_t::first_sa_string()
|
||||||
{
|
{
|
||||||
if(sa.size() <=0 || sa[0]->type != _obj::subarg_string)
|
if(sa.size() <=0 || sa[0]->type != _obj::subarg_string)
|
||||||
return "";
|
return "";
|
||||||
return dynamic_cast<subarg_string_t*>(sa[0])->val;
|
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()
|
bool arg_t::can_expand()
|
||||||
{
|
{
|
||||||
for(auto it: sa)
|
for(auto it: sa)
|
||||||
|
|
|
||||||
|
|
@ -3,3 +3,5 @@
|
||||||
{ echo tata ; echo a; } | sed 's|a|toto|g'
|
{ echo tata ; echo a; } | sed 's|a|toto|g'
|
||||||
|
|
||||||
echo a | { grep a && echo b; }
|
echo a | { grep a && echo b; }
|
||||||
|
|
||||||
|
{ { echo tata ; } }
|
||||||
|
|
|
||||||
|
|
@ -47,4 +47,4 @@ echo ${!TATA}
|
||||||
|
|
||||||
for I in A B C ; do
|
for I in A B C ; do
|
||||||
echo "$I"
|
echo "$I"
|
||||||
done > >(grep A)
|
done 2>&1 > >(grep A)
|
||||||
|
|
|
||||||
1
test/err/brace.sh
Normal file
1
test/err/brace.sh
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
{ ; }
|
||||||
Loading…
Reference in a new issue