
#ifdef WIN32
#include <direct.h>
#define popen _popen
#define pclose _pclose
#endif

#include "cmt_awk.h"
#include "cmt_system.h"

//------------------------------------------------
Awk::Awk ()
{
  m_condition = ok;
}

//------------------------------------------------
Awk::~Awk ()
{
}

//------------------------------------------------
Awk::condition Awk::run (const cmt_string& text,
                         const cmt_string& pattern)
{
  cmt_string line;
  int pos = 0;
  int max_pos;

  m_line_number = 0;
  m_condition = ok;

  begin ();
  if (m_condition != ok) return (m_condition);

  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)
{
  cmt_string line;
  int pos = 0;
  int max_pos;

  m_line_number = 0;
  m_condition = ok;

  begin ();
  if (m_condition != ok) return (m_condition);

  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::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);
}

