#include <iostream>
#include <fstream>
#include <string>
#include <cctype>

using namespace std;

int
System(const string & cmd)
{
   cout << cmd << endl << flush;
   int rc = system(cmd.c_str());
   return rc;
}

string
ReadLine(ifstream & fin)
{
   char ch; 
   string line;
   ch = fin.get();
   while(fin) {
      if(ch == '\n')
         break;
      line += ch;
      ch = fin.get();
   }
   return line;
}

void 
Clean(const string & asm_file)
{
   string line,line2;

   ifstream fin(asm_file.c_str(), ios::in);
   ofstream fout("cxx_temp2.asm", ios::out | ios::ate | ios::trunc);

   if(fin && fout) {
      fout << "[BITS 16]" << endl
           << "[ORG 0]" << endl
           << "_start:" << endl
           << "\tmov ax,cs" << endl 
           << "\tmov ds,ax" << endl
           << "\tmov es,ax" << endl
           << "\tpusha" << endl
           << "\tpush sp" << endl
           << "\tpush word 0" << endl
           << "[BITS 32]" << endl
           << "\tpop dword esp" << endl
           << "\tmov ebp,esp" << endl
           << "\tcall main" << endl 
           << "\tnop" << endl
           << "[BITS 16]" << endl
           << "\tpopa" << endl
           << "\tjmp 0x1000:0" << endl
           << "[BITS 32]" << endl << endl << flush;

      fout << "%include \"io.asm\"" << endl << endl << flush;

      line = ReadLine(fin);

      while(fin) {
         if(line.find("extern") != string::npos 
            || line.find("global") != string::npos
            || line.find("noexecute") != string::npos
            || line.find("execute") != string::npos) {
            line = ReadLine(fin);
            continue;
         }

         fout << line << endl << flush;

         line = ReadLine(fin);
/*
         size_t i = line2.find(":");
         size_t j = line.find(":");

         if(i != string::npos && j != string::npos) {
            if(line2.substr(0, i) == line.substr(0, j)) {
               fout << line << endl << flush;
               line = ReadLine(fin);
            }
            else {
               fout << line2 << endl << flush;
            }
         }
         else {
            fout << line2 << endl << flush;
         }
*/
      }
     
      fout.close();
      fin.close();
   }
}

int
main(int argc, char ** argv, char ** envp)
{
   if(argc != 3) {
      cerr << "usage: " << argv[0] << " <input> <output>" << endl;
      exit(1);
   }

   string ifile = argv[1]; 
   string ofile = argv[2];

   if(System("c++ -nostdinc -nostdlib -Wall -std=c++98 " + ifile + " -o a.out") == 0) {
      if(System("./objconv/objconv -fnasm a.out cxx_temp.asm") == 0) {
         Clean("cxx_temp.asm");
         if(System("nasm -f bin cxx_temp2.asm -o " + ofile) == 0) {

         }
      }
   }

   return 0;
}
