Loading lib/awk/awk.cpp +54 −53 Changes for lib/awk/awk.cpp: 54 added lines, 53 removed lines. Original line number Diff line number Diff line Loading @@ -41,6 +41,59 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <locale.h> namespace fresh { namespace awk { // 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; } // AWK's own number literals/output are specified as always period-decimal, // independent of the process locale -- but fresh's shell (fresh.cpp) calls // setlocale(LC_ALL,"") at startup for its own (legitimate) reasons, and a Loading Loading @@ -930,7 +983,7 @@ static std::vector<std::string> splitByFS(const std::string &s,const std::string if(s.empty()) out.clear(); }else{ try{ const std::regex &re=compileRegex(fs); std::regex re(awkEre(fs),std::regex::extended); size_t start=0; std::sregex_iterator it(s.begin(),s.end(),re), end; if(s.empty()){ /* no fields */ } Loading Loading @@ -1121,58 +1174,6 @@ 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; Loading Loading
lib/awk/awk.cpp +54 −53 Changes for lib/awk/awk.cpp: 54 added lines, 53 removed lines. Original line number Diff line number Diff line Loading @@ -41,6 +41,59 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <locale.h> namespace fresh { namespace awk { // 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; } // AWK's own number literals/output are specified as always period-decimal, // independent of the process locale -- but fresh's shell (fresh.cpp) calls // setlocale(LC_ALL,"") at startup for its own (legitimate) reasons, and a Loading Loading @@ -930,7 +983,7 @@ static std::vector<std::string> splitByFS(const std::string &s,const std::string if(s.empty()) out.clear(); }else{ try{ const std::regex &re=compileRegex(fs); std::regex re(awkEre(fs),std::regex::extended); size_t start=0; std::sregex_iterator it(s.begin(),s.end(),re), end; if(s.empty()){ /* no fields */ } Loading Loading @@ -1121,58 +1174,6 @@ 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; Loading