fix issue on <() parsing + add debug NO_PARSE_CATCH

This commit is contained in:
zawwz 2021-01-08 11:07:20 +01:00
parent 2a86e06551
commit 576ce0c4ed
3 changed files with 85 additions and 3 deletions

View file

@ -18,7 +18,7 @@ CXXFLAGS= -I$(IDIR) -Wall -pedantic -std=c++17
ifeq ($(DEBUG),true)
# debugging flags
CC=clang++
CXXFLAGS += -g -pg
CXXFLAGS += -g -pg -D NO_PARSE_CATCH
else
# release flags
CXXFLAGS += -Ofast

View file

@ -204,6 +204,7 @@ int main(int argc, char* argv[])
std::cout << sh->generate(g_shebang, 0);
}
}
#ifndef NO_PARSE_CATCH
catch(ztd::format_error& e)
{
if(tsh != nullptr)
@ -212,6 +213,7 @@ int main(int argc, char* argv[])
printFormatError(e);
return 100;
}
#endif
catch(std::runtime_error& e)
{
if(tsh != nullptr)

View file

@ -155,8 +155,10 @@ std::pair<arithmetic_subarg*, uint32_t> parse_arithmetic(const char* in, uint32_
arithmetic_subarg* ret = new arithmetic_subarg;
uint32_t i=start;
#ifndef NO_PARSE_CATCH
try
{
#endif
auto pp=parse_subshell(in, size, i);
i=pp.second;
delete pp.first;
@ -166,12 +168,14 @@ std::pair<arithmetic_subarg*, uint32_t> parse_arithmetic(const char* in, uint32_
}
ret->val = std::string(in+start, i-start-1);
i++;
#ifndef NO_PARSE_CATCH
}
catch(ztd::format_error& e)
{
delete ret;
throw e;
}
#endif
return std::make_pair(ret, i);
}
@ -209,8 +213,10 @@ std::pair<arg*, uint32_t> parse_arg(const char* in, uint32_t size, uint32_t star
// j : start of subarg , q = start of quote
uint32_t i=start,j=start,q=start;
#ifndef NO_PARSE_CATCH
try
{
#endif
if(unexpected != NULL && is_in(in[i], unexpected))
throw PARSE_ERROR( strf("Unexpected token '%c'", in[i]) , i);
@ -363,12 +369,14 @@ std::pair<arg*, uint32_t> parse_arg(const char* in, uint32_t size, uint32_t star
if(val != "")
ret->sa.push_back(new string_subarg(val));
#ifndef NO_PARSE_CATCH
}
catch(ztd::format_error& e)
{
delete ret;
throw e;
}
#endif
return std::make_pair(ret, i);
}
@ -447,8 +455,10 @@ std::pair<redirect*, uint32_t> parse_redirect(const char* in, uint32_t size, uin
if(is_redirect)
{
redirect* ret=nullptr;
#ifndef NO_PARSE_CATCH
try
{
#endif
ret = new redirect;
ret->op = std::string(in+start, i-start);
if(needs_arg)
@ -505,6 +515,7 @@ std::pair<redirect*, uint32_t> parse_redirect(const char* in, uint32_t size, uin
i=pa.second;
}
}
#ifndef NO_PARSE_CATCH
}
catch(ztd::format_error& e)
{
@ -512,6 +523,7 @@ std::pair<redirect*, uint32_t> parse_redirect(const char* in, uint32_t size, uin
delete ret;
throw e;
}
#endif
return std::make_pair(ret, i);
}
else
@ -527,8 +539,10 @@ std::pair<arglist*, uint32_t> parse_arglist(const char* in, uint32_t size, uint3
uint32_t i=start;
arglist* ret = nullptr;
#ifndef NO_PARSE_CATCH
try
{
#endif
if(is_in(in[i], SPECIAL_TOKENS) && !word_eq("&>", in, size, i))
{
if(hard_error)
@ -546,7 +560,7 @@ std::pair<arglist*, uint32_t> parse_arglist(const char* in, uint32_t size, uint3
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;
i=ps.second;
}
else if(redirs!=nullptr)
{
@ -578,6 +592,7 @@ std::pair<arglist*, uint32_t> parse_arglist(const char* in, uint32_t size, uint3
if( is_in(in[i], SPECIAL_TOKENS) )
return std::make_pair(ret, i);
}
#ifndef NO_PARSE_CATCH
}
catch(ztd::format_error& e)
{
@ -585,6 +600,7 @@ std::pair<arglist*, uint32_t> parse_arglist(const char* in, uint32_t size, uint3
delete ret;
throw e;
}
#endif
return std::make_pair(ret, i);
}
@ -596,8 +612,11 @@ std::pair<pipeline*, uint32_t> parse_pipeline(const char* in, uint32_t size, uin
{
uint32_t i=start;
pipeline* ret = new pipeline;
#ifndef NO_PARSE_CATCH
try
{
#endif
if(in[i] == '!' && i+1<size && is_in(in[i+1], SPACES))
{
ret->negated = true;
@ -614,12 +633,14 @@ std::pair<pipeline*, uint32_t> parse_pipeline(const char* in, uint32_t size, uin
throw PARSE_ERROR( strf("Unexpected token: '%c'", in[i] ), i);
i++;
}
#ifndef NO_PARSE_CATCH
}
catch(ztd::format_error& e)
{
delete ret;
throw e;
}
#endif
return std::make_pair(ret, i);
}
@ -631,8 +652,11 @@ std::pair<condlist*, uint32_t> parse_condlist(const char* in, uint32_t size, uin
{
uint32_t i = skip_unread(in, size, start);
condlist* ret = new condlist;
#ifndef NO_PARSE_CATCH
try
{
#endif
bool optype=AND_OP;
while(i<size)
{
@ -665,12 +689,14 @@ std::pair<condlist*, uint32_t> parse_condlist(const char* in, uint32_t size, uin
if(i>=size)
throw PARSE_ERROR( "Unexpected end of file", i );
}
#ifndef NO_PARSE_CATCH
}
catch(ztd::format_error& e)
{
delete ret;
throw e;
}
#endif
return std::make_pair(ret, i);
}
@ -678,8 +704,11 @@ std::pair<list*, uint32_t> parse_list_until(const char* in, uint32_t size, uint3
{
list* ret = new list;
uint32_t i=skip_unread(in, size, start);
#ifndef NO_PARSE_CATCH
try
{
#endif
while(in[i] != end_c)
{
auto pp=parse_condlist(in, size, i);
@ -713,12 +742,14 @@ std::pair<list*, uint32_t> parse_list_until(const char* in, uint32_t size, uint3
break;
}
}
#ifndef NO_PARSE_CATCH
}
catch(ztd::format_error& e)
{
delete ret;
throw e;
}
#endif
return std::make_pair(ret, i);
}
@ -726,8 +757,11 @@ std::pair<list*, uint32_t> parse_list_until(const char* in, uint32_t size, uint3
{
list* ret = new list;
uint32_t i=skip_unread(in, size, start);
#ifndef NO_PARSE_CATCH
try
{
#endif
std::string old_expect=g_expecting;
g_expecting=end_word;
while(true)
@ -762,12 +796,14 @@ std::pair<list*, uint32_t> parse_list_until(const char* in, uint32_t size, uint3
}
}
g_expecting=old_expect;
#ifndef NO_PARSE_CATCH
}
catch(ztd::format_error& e)
{
delete ret;
throw e;
}
#endif
return std::make_pair(ret, i);
}
@ -777,8 +813,11 @@ std::tuple<list*, uint32_t, std::string> parse_list_until(const char* in, uint32
list* ret = new list;
uint32_t i=skip_unread(in, size, start);;
std::string found_end_word;
#ifndef NO_PARSE_CATCH
try
{
#endif
std::string old_expect=g_expecting;
g_expecting=end_words[0];
bool stop=false;
@ -825,12 +864,14 @@ std::tuple<list*, uint32_t, std::string> parse_list_until(const char* in, uint32
}
}
g_expecting=old_expect;
#ifndef NO_PARSE_CATCH
}
catch(ztd::format_error& e)
{
delete ret;
throw e;
}
#endif
return std::make_tuple(ret, i, found_end_word);
}
@ -842,21 +883,24 @@ std::pair<subshell*, uint32_t> parse_subshell(const char* in, uint32_t size, uin
uint32_t i = skip_unread(in, size, start);
subshell* ret = new subshell;
#ifndef NO_PARSE_CATCH
try
{
#endif
auto pp=parse_list_until(in, size, start, ')');
ret->lst=pp.first;
i=pp.second;
if(ret->lst->size()<=0)
throw PARSE_ERROR("Subshell is empty", start-1);
i++;
#ifndef NO_PARSE_CATCH
}
catch(ztd::format_error& e)
{
delete ret;
throw e;
}
#endif
return std::make_pair(ret,i);
}
@ -869,20 +913,24 @@ std::pair<brace*, uint32_t> parse_brace(const char* in, uint32_t size, uint32_t
uint32_t i = skip_unread(in, size, start);
brace* ret = new brace;
#ifndef NO_PARSE_CATCH
try
{
#endif
auto pp=parse_list_until(in, size, start, '}');
ret->lst=pp.first;
i=pp.second;
if(ret->lst->size()<=0)
throw PARSE_ERROR("Brace block is empty", start-1);
i++;
#ifndef NO_PARSE_CATCH
}
catch(ztd::format_error& e)
{
delete ret;
throw e;
}
#endif
return std::make_pair(ret,i);
}
@ -895,8 +943,10 @@ std::pair<function*, uint32_t> parse_function(const char* in, uint32_t size, uin
uint32_t i=start;
function* ret = new function;
#ifndef NO_PARSE_CATCH
try
{
#endif
i=skip_unread(in, size, i);
if(in[i] != '{')
throw PARSE_ERROR( strf("Expecting { after %s", after) , i);
@ -909,12 +959,14 @@ std::pair<function*, uint32_t> parse_function(const char* in, uint32_t size, uin
ret->lst=pp.first;
i=pp.second;
i++;
#ifndef NO_PARSE_CATCH
}
catch(ztd::format_error& e)
{
delete ret;
throw e;
}
#endif
return std::make_pair(ret, i);
}
@ -925,8 +977,10 @@ std::pair<cmd*, uint32_t> parse_cmd(const char* in, uint32_t size, uint32_t star
cmd* ret = new cmd;
uint32_t i=start;
#ifndef NO_PARSE_CATCH
try
{
#endif
while(true) // parse var assigns
{
auto wp=get_word(in, size, i, VARNAME_END);
@ -960,12 +1014,14 @@ std::pair<cmd*, uint32_t> parse_cmd(const char* in, uint32_t size, uint32_t star
else if(ret->var_assigns.size() <= 0)
throw PARSE_ERROR( strf("Unexpected token: '%c'", in[i]), i );
#ifndef NO_PARSE_CATCH
}
catch(ztd::format_error& e)
{
delete ret;
throw e;
}
#endif
return std::make_pair(ret, i);
}
@ -978,8 +1034,10 @@ std::pair<case_block*, uint32_t> parse_case(const char* in, uint32_t size, uint3
uint32_t i=skip_chars(in, size, start, SPACES);;
case_block* ret = new case_block;
#ifndef NO_PARSE_CATCH
try
{
#endif
// get the treated argument
auto pa = parse_arg(in, size, i);
ret->carg = pa.first;
@ -1042,12 +1100,14 @@ std::pair<case_block*, uint32_t> parse_case(const char* in, uint32_t size, uint3
if(i>=size)
throw PARSE_ERROR("Expecting 'esac'", i);
i+=4;
#ifndef NO_PARSE_CATCH
}
catch(ztd::format_error& e)
{
if(ret != nullptr) delete ret;
throw e;
}
#endif
return std::make_pair(ret, i);
}
@ -1057,8 +1117,10 @@ std::pair<if_block*, uint32_t> parse_if(const char* in, uint32_t size, uint32_t
if_block* ret = new if_block;
uint32_t i=start;
#ifndef NO_PARSE_CATCH
try
{
#endif
while(true)
{
std::string word;
@ -1093,12 +1155,14 @@ std::pair<if_block*, uint32_t> parse_if(const char* in, uint32_t size, uint32_t
}
#ifndef NO_PARSE_CATCH
}
catch(ztd::format_error& e)
{
delete ret;
throw e;
}
#endif
return std::make_pair(ret, i);
}
@ -1108,8 +1172,10 @@ std::pair<for_block*, uint32_t> parse_for(const char* in, uint32_t size, uint32_
for_block* ret = new for_block;
uint32_t i=skip_chars(in, size, start, SPACES);
#ifndef NO_PARSE_CATCH
try
{
#endif
auto wp = get_word(in, size, i, ARG_END);
if(!valid_name(wp.first))
@ -1146,12 +1212,14 @@ std::pair<for_block*, uint32_t> parse_for(const char* in, uint32_t size, uint32_
auto lp = parse_list_until(in, size, i, "done");
ret->ops=lp.first;
i=lp.second;
#ifndef NO_PARSE_CATCH
}
catch(ztd::format_error& e)
{
delete ret;
throw e;
}
#endif
return std::make_pair(ret, i);
}
@ -1161,8 +1229,10 @@ std::pair<while_block*, uint32_t> parse_while(const char* in, uint32_t size, uin
while_block* ret = new while_block;
uint32_t i=start;
#ifndef NO_PARSE_CATCH
try
{
#endif
// cond
auto pp=parse_list_until(in, size, i, "do");
ret->cond = pp.first;
@ -1177,12 +1247,14 @@ std::pair<while_block*, uint32_t> parse_while(const char* in, uint32_t size, uin
i = lp.second;
if(ret->ops->size() <= 0)
throw PARSE_ERROR("while is empty", i);
#ifndef NO_PARSE_CATCH
}
catch(ztd::format_error& e)
{
delete ret;
throw e;
}
#endif
return std::make_pair(ret, i);
}
@ -1193,8 +1265,10 @@ std::pair<block*, uint32_t> parse_block(const char* in, uint32_t size, uint32_t
uint32_t i = skip_chars(in, size, start, SEPARATORS);
block* ret = nullptr;
#ifndef NO_PARSE_CATCH
try
{
#endif
if(i>=size)
throw PARSE_ERROR("Unexpected end of file", i);
if( in[i] == '(' ) //subshell
@ -1299,12 +1373,14 @@ std::pair<block*, uint32_t> parse_block(const char* in, uint32_t size, uint32_t
}
i=pp.second;
}
#ifndef NO_PARSE_CATCH
}
catch(ztd::format_error& e)
{
if(ret != nullptr) delete ret;
throw e;
}
#endif
return std::make_pair(ret,i);
}
@ -1314,8 +1390,10 @@ shmain* parse_text(const char* in, uint32_t size, std::string const& filename)
{
shmain* ret = new shmain();
uint32_t i=0;
#ifndef NO_PARSE_CATCH
try
{
#endif
ret->filename=filename;
// get shebang
if(word_eq("#!", in, size, 0))
@ -1331,12 +1409,14 @@ shmain* parse_text(const char* in, uint32_t size, std::string const& filename)
auto pp=parse_list_until(in, size, i, 0);
ret->lst=pp.first;
i=pp.second;
#ifndef NO_PARSE_CATCH
}
catch(ztd::format_error& e)
{
delete ret;
throw ztd::format_error(e.what(), filename, e.data(), e.where());
}
#endif
return ret;
}