From 4ff253a36471afd89b13289884abb55157e08935 Mon Sep 17 00:00:00 2001 From: zawz Date: Sat, 14 Aug 2021 13:09:45 +0200 Subject: [PATCH] implement small optimization on arg parse --- include/parse.hpp | 12 ++++++-- src/parse.cpp | 70 ++++++++++++++++++++++++++++------------------- 2 files changed, 52 insertions(+), 30 deletions(-) diff --git a/include/parse.hpp b/include/parse.hpp index cce2f05..a0981c3 100644 --- a/include/parse.hpp +++ b/include/parse.hpp @@ -26,7 +26,15 @@ #define SPECIAL_VARS "!#*@$?" // bash specific -#define ARRAY_ARG_END " \t\n;#()&|<>]" +#define ARRAY_ARG_END " \t\n;#()&|<>]" +// optimizations +#define ARG_OPTIMIZE_NULL "$\\`" +#define ARG_OPTIMIZE_MANIP "$\\`}" +#define ARG_OPTIMIZE_DEFARR "$\\`)" +#define ARG_OPTIMIZE_BASHTEST "$\\`] \t\n" +#define ARG_OPTIMIZE_ARG "$\\` \t\n;#()&|<>\"'" +#define ARG_OPTIMIZE_ARRAY "$\\`\t\n&|}[]\"'" +#define ARG_OPTIMIZE_ALL "$\\` \t\n;#()&|<>}]\"'" // structs @@ -100,7 +108,7 @@ std::pair parse_var(parse_context ct, bool specialvars std::pair parse_arithmetic(parse_context ct); std::pair parse_manipulation(parse_context ct); // arg parser -std::pair parse_arg(parse_context ct, const char* end=ARG_END, const char* unexpected=ARGLIST_END, bool doquote=true); +std::pair parse_arg(parse_context ct, const char* end=ARG_END, const char* unexpected=ARGLIST_END, bool doquote=true, const char* optimize=ARG_OPTIMIZE_ARG); // redirect parser std::pair parse_redirect(parse_context ct); // arglist parser diff --git a/src/parse.cpp b/src/parse.cpp index 6ac2e57..5307843 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -231,7 +231,7 @@ std::pair parse_var(parse_context ctx, bool specialvar if(ctx.bash && array && ctx[ctx.i]=='[') { ctx.i++; - auto pp=parse_arg(ctx, ARRAY_ARG_END); + auto pp=parse_arg(ctx, ARRAY_ARG_END, ARGLIST_END, true, ARG_OPTIMIZE_ARRAY); ret->index=pp.first; ctx = pp.second; if(ctx[ctx.i] != ']') @@ -409,7 +409,7 @@ std::pair parse_manipulation(parse_context ctx) } else if(ctx[ctx.i] != '}') { - auto pa = parse_arg(ctx, "}", NULL, false); + auto pa = parse_arg(ctx, "}", NULL, false, ARG_OPTIMIZE_MANIP); ret->manip=pa.first; ctx = pa.second; } @@ -418,14 +418,13 @@ std::pair parse_manipulation(parse_context ctx) return std::make_pair(ret, ctx); } -parse_context do_one_subarg_step(arg* ret, parse_context ctx, uint32_t& j, bool is_quoted) +inline parse_context do_one_subarg_step(arg* ret, parse_context ctx, uint32_t& j, bool is_quoted) { if( ctx[ctx.i] == '`' ) { // add previous subarg - std::string tmpstr=std::string(ctx.data+j, ctx.i-j); - if(tmpstr!="") - ret->add(tmpstr); + if(ctx.i-j>0) + ret->add(std::string(ctx.data+j, ctx.i-j)); ctx.i++; uint32_t k=skip_until(ctx, "`"); @@ -451,9 +450,8 @@ parse_context do_one_subarg_step(arg* ret, parse_context ctx, uint32_t& j, bool else if( word_eq("$((", ctx) ) // arithmetic operation { // add previous subarg - std::string tmpstr=std::string(ctx.data+j, ctx.i-j); - if(tmpstr!="") - ret->add(tmpstr); + if(ctx.i-j>0) + ret->add(std::string(ctx.data+j, ctx.i-j)); // get arithmetic ctx.i+=3; auto r=parse_arithmetic(ctx); @@ -474,9 +472,8 @@ parse_context do_one_subarg_step(arg* ret, parse_context ctx, uint32_t& j, bool else if( word_eq("$(", ctx) ) // substitution { // add previous subarg - std::string tmpstr=std::string(ctx.data+j, ctx.i-j); - if(tmpstr!="") - ret->add(tmpstr); + if(ctx.i-j>0) + ret->add(std::string(ctx.data+j, ctx.i-j)); // get subshell ctx.i+=2; auto r=parse_subshell(ctx); @@ -487,9 +484,8 @@ parse_context do_one_subarg_step(arg* ret, parse_context ctx, uint32_t& j, bool else if( word_eq("${", ctx) ) // variable manipulation { // add previous subarg - std::string tmpstr=std::string(ctx.data+j, ctx.i-j); - if(tmpstr!="") - ret->add(tmpstr); + if(ctx.i-j>0) + ret->add(std::string(ctx.data+j, ctx.i-j)); // get manipulation ctx.i+=2; auto r=parse_manipulation(ctx); @@ -505,9 +501,8 @@ parse_context do_one_subarg_step(arg* ret, parse_context ctx, uint32_t& j, bool if(r.first !=nullptr) { // add previous subarg - std::string tmpstr=std::string(ctx.data+j, ctx.i-j); - if(tmpstr!="") - ret->add(tmpstr); + if(ctx.i-j>0) + ret->add(std::string(ctx.data+j, ctx.i-j)); // add var ret->add(new variable_subarg(r.first, is_quoted)); ctx = r.second; @@ -521,10 +516,30 @@ parse_context do_one_subarg_step(arg* ret, parse_context ctx, uint32_t& j, bool return ctx; } +uint64_t find_any(parse_context const& ctx, const char* chars, uint32_t nchar) { + uint64_t lowest=ctx.size; + uint64_t trank=0; + for(uint32_t i=0; i parse_arg(parse_context ctx, const char* end, const char* unexpected, bool doquote) +std::pair parse_arg(parse_context ctx, const char* end, const char* unexpected, bool doquote, const char* optimize) { arg* ret = new arg; // j : start of subarg , q = start of quote @@ -535,9 +550,9 @@ std::pair parse_arg(parse_context ctx, const char* end, con parse_error( unexpected_token(ctx[ctx.i]), ctx); } - while(ctx.i") && ctx[ctx.i+1]=='&') // special case for <& and >& + if(ctx.i+1')) // special case for <& and >& { ctx.i += 2; } @@ -548,9 +563,8 @@ std::pair parse_arg(parse_context ctx, const char* end, con break; if(ctx[ctx.i] == '\n') // \ on \n : skip this char { - std::string tmpstr=std::string(ctx.data+j, ctx.i-1-j); - if(tmpstr!="") - ret->add(tmpstr); + if(ctx.i-1-j>0) + ret->add(std::string(ctx.data+j, ctx.i-1-j)); ctx.i++; j=ctx.i; } @@ -623,7 +637,7 @@ parse_context parse_heredocument(parse_context ctx) // std::string tmpparse=std::string(ctx.data+j, ctx.i-j); parse_context newctx = make_context(ctx, j); newctx.size = ctx.i; - auto pval = parse_arg(newctx , NULL, NULL, false); + auto pval = parse_arg(newctx , NULL, NULL, false, ARG_OPTIMIZE_NULL); ctx.i = pval.second.i; ctx.has_errored = pval.second.has_errored; ctx.here_document->here_document = pval.first; @@ -792,8 +806,8 @@ std::pair parse_arglist(parse_context ctx, bool hard_er while(true) { if(ret == nullptr) - ret = new arglist; - auto pp=parse_arg(ctx, SEPARATORS, NULL); + ret = new arglist; + auto pp=parse_arg(ctx, SEPARATORS, NULL, true, ARG_OPTIMIZE_BASHTEST); ret->add(pp.first); ctx = pp.second; ctx.i = skip_chars(ctx, SEPARATORS); @@ -1231,7 +1245,7 @@ parse_context parse_cmd_varassigns(cmd* in, parse_context ctx, bool cmdassign=fa parse_error("Unallowed special assign", ctx); } ctx.i++; - auto pp=parse_arg(ctx, ")"); + auto pp=parse_arg(ctx, ")", ARG_OPTIMIZE_DEFARR); ta=pp.first; ta->insert(0,"("); ta->add(")");