#ifdef WIN32 #include #define popen _popen #define pclose _pclose #endif #include "cmt_awk.h" #include "cmt_system.h" class Parser { public: Parser (Awk* awk, const cmt_string pattern, const cmt_regexp* expression) : m_awk(awk), m_pattern (pattern), m_expression (expression) { } Awk::condition parse (const cmt_string& text) { Awk::condition result = Awk::ok; cmt_string line; int pos; int max_pos; pos = 0; max_pos = text.size (); m_accumulator.erase (0); for (pos = 0; pos < max_pos;) { int cr = text.find (pos, "\r\n"); int nl = text.find (pos, '\n'); int first = nl; int length = 1; if (cr != cmt_string::npos) { if (nl == cmt_string::npos) { first = cr; length = 2; } else { first = (nl < cr) ? nl : cr; length = (nl < cr) ? 1 : 2; } } if (first == cmt_string::npos) { text.substr (pos, line); pos = max_pos; } else if (first > pos) { text.substr (pos, first - pos, line); pos = first + length; } else { line.erase (0); pos += length; } //cout << "parse> line=[" << line << "]" << endl; result = parse_line (line); if (result != Awk::ok) break; } return (result); } Awk::condition parse_line (const cmt_string& line) { Awk::condition result = Awk::ok; int length; int nl; int back_slash; cmt_string temp_line = line; if (temp_line.size () == 0) return (result); nl = temp_line.find_last_of ('\n'); if (nl != cmt_string::npos) temp_line.erase (nl); length = temp_line.size (); if (length == 0) return (result); // // We scan the line for handling backslashes. // // o Really terminating backslashes (ie those only followed by spaces/tabs // mean continued line // // bool finished = true; length = temp_line.size (); back_slash = temp_line.find_last_of ('\\'); if (back_slash != cmt_string::npos) { // // This is the last backslash // check if there are only space chars after it // bool at_end = true; for (int i = (back_slash + 1); i < length; i++) { char c = temp_line[i]; if ((c != ' ') && (c != '\t')) { at_end = false; break; } } if (at_end) { temp_line.erase (back_slash); finished = false; } else { // This was not a trailing backslash. finished = true; } } m_accumulator += temp_line; //cout << "parse_line1> accumulator=[" << m_accumulator << "]" << endl; //cout << "parse_line1> finished=[" << finished << "]" << endl; if (!finished) { // We still need to accumulate forthcoming lines // before parsing the resulting text. return (result); } // now filter the accumulated line if (m_accumulator != "") { bool ok = false; if (m_expression != 0) { if (m_expression->match (m_accumulator)) { ok = true; } } else { if ((m_pattern == "") || (m_accumulator.find (m_pattern) != cmt_string::npos)) { ok = true; } } if (ok && (m_awk != 0)) { //cout << "parse_line> accumulator=[" << m_accumulator << "]" << endl; m_awk->filter (m_accumulator); result = m_awk->get_last_condition (); } } m_accumulator.erase (0); return (result); } private: cmt_string m_accumulator; cmt_string m_pattern; const cmt_regexp* m_expression; Awk* m_awk; }; //------------------------------------------------ Awk::Awk () { m_condition = ok; } //------------------------------------------------ Awk::~Awk () { } //------------------------------------------------ Awk::condition Awk::run (const cmt_string& text, const cmt_string& pattern) { m_line_number = 0; m_condition = ok; begin (); if (m_condition != ok) return (m_condition); if (CmtSystem::testenv ("CMTTESTAWK")) { Parser p (this, pattern, 0); m_condition = p.parse (text); if (m_condition != ok) return (m_condition); } else { cmt_string line; int pos = 0; int max_pos; max_pos = text.size (); for (pos = 0; pos < max_pos;) { int cr = text.find (pos, "\r\n"); int nl = text.find (pos, '\n'); // Get the first end-of-line (either lf or cr-lf) int first = nl; if (cr != cmt_string::npos) { if (nl == cmt_string::npos) { first = cr; } else { first = (nl < cr) ? nl : cr; } } if (first == cmt_string::npos) { // This is likely the last line since there is no end-of-line text.substr (pos, line); pos = max_pos; } else if (first > pos) { // The eol was found beyond the current position // (ie. this is a non empty line) text.substr (pos, first - pos, line); pos = first + 1; } else { // an empty line line = ""; pos++; } m_line_number++; if (line != "") { if ((pattern == "") || (line.find (pattern) != cmt_string::npos)) { filter (line); if (m_condition != ok) return (m_condition); } } } } end (); return (m_condition); } //------------------------------------------------ Awk::condition Awk::run (const cmt_string& text, const cmt_regexp& expression) { m_line_number = 0; m_condition = ok; begin (); if (m_condition != ok) return (m_condition); if (CmtSystem::testenv ("CMTTESTAWK")) { Parser p (this, "", &expression); m_condition = p.parse (text); if (m_condition != ok) return (m_condition); } else { cmt_string line; int pos = 0; int max_pos; max_pos = text.size (); for (pos = 0; pos < max_pos;) { int cr = text.find (pos, "\r\n"); int nl = text.find (pos, '\n'); // Get the first end-of-line (either lf or cr-lf) int first = nl; if (cr != cmt_string::npos) { if (nl == cmt_string::npos) { first = cr; } else { first = (nl < cr) ? nl : cr; } } if (first == cmt_string::npos) { // This is likely the last line since there is no end-of-line text.substr (pos, line); pos = max_pos; } else if (first > pos) { // The eol was found beyond the current position // (ie. this is a non empty line) text.substr (pos, first - pos, line); pos = first + 1; } else { // an empty line line = ""; pos++; } m_line_number++; if (line != "") { if (expression.match (line)) { filter (line); if (m_condition != ok) return (m_condition); } } } } end (); return (m_condition); } //------------------------------------------------ void Awk::stop () { m_condition = stopped; } //------------------------------------------------ void Awk::abort () { m_condition = failed; } //------------------------------------------------ void Awk::allow_continuation () { m_continuation_allowed = true; } //------------------------------------------------ Awk::condition Awk::get_last_condition () const { return (m_condition); } //------------------------------------------------ void Awk::begin () { } //------------------------------------------------ void Awk::filter (const cmt_string& line) { //cout << "awk> " << line << endl; } //------------------------------------------------ void Awk::end () { } //------------------------------------------------ Awk::condition FAwk::run (const cmt_string& file_name, const cmt_string& pattern) { if (!CmtSystem::test_file (file_name)) return (failed); CmtSystem::basename (file_name, m_file_name); CmtSystem::dirname (file_name, m_dir_name); cmt_string text; text.read (file_name); return (Awk::run (text, pattern)); } //------------------------------------------------ Awk::condition FAwk::run (const cmt_string& file_name, const cmt_regexp& expression) { if (!CmtSystem::test_file (file_name)) return (failed); CmtSystem::basename (file_name, m_file_name); CmtSystem::dirname (file_name, m_dir_name); cmt_string text; text.read (file_name); return (Awk::run (text, expression)); } //------------------------------------------------ Awk::condition PAwk::run (const cmt_string& command, const cmt_string& pattern) { cmt_string line; m_line_number = 0; m_condition = ok; begin (); if (m_condition != ok) return (m_condition); FILE* f = popen (command.c_str (), "r"); if (f == 0) return (failed); char buffer[8192]; char* ptr; while ((ptr = fgets (buffer, sizeof (buffer), f)) != NULL) { line = ptr; if (line.find ("\n") == cmt_string::npos) { cerr << "#CMT> Warning : Line too long and truncated in PAwk::run for command " << command << endl; } line.replace ("\n", ""); m_line_number++; if (line != "") { if ((pattern == "") || (line.find (pattern) != cmt_string::npos)) { filter (line); if (m_condition != ok) return (m_condition); } } } pclose (f); end (); return (m_condition); } //------------------------------------------------ Awk::condition PAwk::run (const cmt_string& command, const cmt_regexp& expression) { cmt_string line; m_line_number = 0; m_condition = ok; begin (); if (m_condition != ok) return (m_condition); FILE* f = popen (command.c_str (), "r"); if (f == 0) return (failed); char buffer[256]; char* ptr; while ((ptr = fgets (buffer, sizeof (buffer), f)) != NULL) { line = ptr; line.replace ("\n", ""); m_line_number++; if (line != "") { if (expression.match (line)) { filter (line); if (m_condition != ok) return (m_condition); } } } pclose (f); end (); return (m_condition); }