Loading lib/awk/awk.cpp +54 −2 Changes for lib/awk/awk.cpp: 54 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -930,7 +930,7 @@ static std::vector<std::string> splitByFS(const std::string &s,const std::string if(s.empty()) out.clear(); }else{ try{ std::regex re(fs,std::regex::extended); const std::regex &re=compileRegex(fs); size_t start=0; std::sregex_iterator it(s.begin(),s.end(),re), end; if(s.empty()){ /* no fields */ } Loading Loading @@ -1121,11 +1121,63 @@ Value Interp::doCompoundAssign(NodeP n){ return v; } // awk EREs as awks read them: a '{' that doesn't open a valid interval // ({n}, {n,}, {n,m}) and a '}' that doesn't close one are plain // characters (the kernel's orc_hash.sh matches /^struct orc_entry {$/), // where std::regex's extended grammar rejects both. static std::string awkEre(const std::string &pat){ std::string out; out.reserve(pat.size()+8); size_t i=0,n=pat.size(); while(i<n){ char c=pat[i]; if(c=='\\' && i+1<n){ out+=c; out+=pat[i+1]; i+=2; continue; } if(c=='['){ // copy a bracket expression whole: ']' first is literal, and // "[:class:]" parts may contain ']' size_t j=i+1; if(j<n && pat[j]=='^') j++; if(j<n && pat[j]==']') j++; while(j<n && pat[j]!=']'){ if(pat[j]=='[' && j+1<n && (pat[j+1]==':' || pat[j+1]=='.' || pat[j+1]=='=')){ char kind=pat[j+1]; size_t e=pat.find(std::string(1,kind)+"]",j+2); j=(e==std::string::npos) ? n : e+2; continue; } j++; } if(j>=n){ out+="\\["; i++; continue; } // unterminated: literal '[' out.append(pat,i,j-i+1); i=j+1; continue; } if(c=='{'){ size_t j=i+1; bool digits=false; while(j<n && isdigit((unsigned char)pat[j])){ j++; digits=true; } if(digits && j<n && pat[j]==','){ j++; while(j<n && isdigit((unsigned char)pat[j])) j++; } bool interval=digits && j<n && pat[j]=='}' && !out.empty(); if(interval){ out.append(pat,i,j-i+1); i=j+1; continue; } out+="\\{"; i++; continue; } if(c=='}'){ out+="\\}"; i++; continue; } out+=c; i++; } return out; } const std::regex &Interp::compileRegex(const std::string &pat){ auto it=regexCache_.find(pat); if(it!=regexCache_.end()) return it->second; std::regex re; try{ re=std::regex(pat,std::regex::extended); } try{ re=std::regex(awkEre(pat),std::regex::extended); } catch(...){ try{ re=std::regex(pat); }catch(...){ re=std::regex(""); } } return regexCache_.emplace(pat,std::move(re)).first->second; } Loading Loading
lib/awk/awk.cpp +54 −2 Changes for lib/awk/awk.cpp: 54 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -930,7 +930,7 @@ static std::vector<std::string> splitByFS(const std::string &s,const std::string if(s.empty()) out.clear(); }else{ try{ std::regex re(fs,std::regex::extended); const std::regex &re=compileRegex(fs); size_t start=0; std::sregex_iterator it(s.begin(),s.end(),re), end; if(s.empty()){ /* no fields */ } Loading Loading @@ -1121,11 +1121,63 @@ Value Interp::doCompoundAssign(NodeP n){ return v; } // awk EREs as awks read them: a '{' that doesn't open a valid interval // ({n}, {n,}, {n,m}) and a '}' that doesn't close one are plain // characters (the kernel's orc_hash.sh matches /^struct orc_entry {$/), // where std::regex's extended grammar rejects both. static std::string awkEre(const std::string &pat){ std::string out; out.reserve(pat.size()+8); size_t i=0,n=pat.size(); while(i<n){ char c=pat[i]; if(c=='\\' && i+1<n){ out+=c; out+=pat[i+1]; i+=2; continue; } if(c=='['){ // copy a bracket expression whole: ']' first is literal, and // "[:class:]" parts may contain ']' size_t j=i+1; if(j<n && pat[j]=='^') j++; if(j<n && pat[j]==']') j++; while(j<n && pat[j]!=']'){ if(pat[j]=='[' && j+1<n && (pat[j+1]==':' || pat[j+1]=='.' || pat[j+1]=='=')){ char kind=pat[j+1]; size_t e=pat.find(std::string(1,kind)+"]",j+2); j=(e==std::string::npos) ? n : e+2; continue; } j++; } if(j>=n){ out+="\\["; i++; continue; } // unterminated: literal '[' out.append(pat,i,j-i+1); i=j+1; continue; } if(c=='{'){ size_t j=i+1; bool digits=false; while(j<n && isdigit((unsigned char)pat[j])){ j++; digits=true; } if(digits && j<n && pat[j]==','){ j++; while(j<n && isdigit((unsigned char)pat[j])) j++; } bool interval=digits && j<n && pat[j]=='}' && !out.empty(); if(interval){ out.append(pat,i,j-i+1); i=j+1; continue; } out+="\\{"; i++; continue; } if(c=='}'){ out+="\\}"; i++; continue; } out+=c; i++; } return out; } const std::regex &Interp::compileRegex(const std::string &pat){ auto it=regexCache_.find(pat); if(it!=regexCache_.end()) return it->second; std::regex re; try{ re=std::regex(pat,std::regex::extended); } try{ re=std::regex(awkEre(pat),std::regex::extended); } catch(...){ try{ re=std::regex(pat); }catch(...){ re=std::regex(""); } } return regexCache_.emplace(pat,std::move(re)).first->second; } Loading