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
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
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)
|
||||
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"])
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -3,3 +3,5 @@
|
|||
{ echo tata ; echo a; } | sed 's|a|toto|g'
|
||||
|
||||
echo a | { grep a && echo b; }
|
||||
|
||||
{ { echo tata ; } }
|
||||
|
|
|
|||
|
|
@ -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
1
test/err/brace.sh
Normal file
|
|
@ -0,0 +1 @@
|
|||
{ ; }
|
||||
Loading…
Reference in a new issue