2005/5/9

     
 

acdkmc.cpp

artefaktur

// -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:nil -*- 
//
// Copyright (C) 1999-2000 by Roger Rene Kommer, artefaktur
// Projekt: ACDK
// 
// $Header: /cvsroot/acdk/acdk/acdk_core/src/acdk/tools/acdkmc/acdkmc.cpp,v 1.33 2005/03/08 12:45:39 kommer Exp $

// ACDK Class Modul Compiler
#include "ClassInfo.h"

#include <acdk/security/security.h>
#include <acdk/util/Collections.h>
#include <acdk/io/ObjectReader.h>
#include <acdk/io/AbstractFilterWriter.h>
#include <acdk/io/BufferedWriter.h>
#include <acdk/util/logging/ConsoleConsumer.h>
#include <acdk/util/logging/SimpleFormatter.h>
#include <acdk/locale/Encoding.h>



namespace acdk {
namespace tools {
namespace acdkmc {

using namespace std;

using namespace acdk::lang;
using namespace acdk::lang::reflect;
using namespace acdk::io;
using namespace acdk::util;
using namespace acdk::security;
using namespace acdk::tools::mc;

int 
ClassModulCompiler::generate()
{
  RFile dir = new File(_path);
  if (dir->isDirectory() == true) 
  {
    RString fdir = dir->getCanonicalPath();
    RString adir = dir->getAbsolutePath();
    RStringArray files = dir->list(new GlobFilenameFilter("*.h"));
    for (int i = 0; i < files->length(); i++) 
    {
      RModuleInfo cm = new ModuleInfo(File::concat(dir->getAbsolutePath(), files[i]));
      if (cm->parse())
        _modules->add((acdk::lang::Object)cm);
    }
  } else {
    RModuleInfo cm = new ModuleInfo(dir->getAbsolutePath());
    if (cm->parse())
      _modules->add((acdk::lang::Object)cm);
  }
  return 0;
}


void 
ClassModulCompiler::writeModuleHeaderIncludes(IN(RPrintWriter) out, IN(RPrintWriter) stubout)
{
  //RString lastname;
  RIterator it = _modules->iterator();
  while (it->hasNext() == true) 
  {
    RModuleInfo cm = RModuleInfo(it->next());
    cm->writeModuleHeaderInclude(out, stubout);
    //lastname = cm->name;
  }
  out->print("#include <acdk/lang/dmi/ClazzInfoInternals.h>\n");
  /*
  if (stubout != Nil && MetaCompiler::getMetaCompiler()->dummyExportForExternalMIWritten == false)
  {
    MetaCompiler::getMetaCompiler()->dummyExportForExternalMIWritten = true;
    out->print("\n#if defined(ACDK_OS_WIN32)\n// force to create an import lib on windows platforms\nvoid __declspec(dllexport) " + lastname + "_dummyExportFunc() {}\n#endif\n\n");
  }
  */
}

void 
ClassModulCompiler::dump(IN(RPrintWriter) out, IN(RString) ind)
{
  RIterator it = _modules->iterator();
  while (it->hasNext() == true) 
  {
    RModuleInfo cm = RModuleInfo(it->next());
    cm->dump(out, ind + " ");
  }
}

void 
ClassModulCompiler::addModuleAttrCode(IN(RString) code)
{
  acdk::tools::mc::RCodeAttribute ca = MetaCompiler::getMetaCompiler()->readParseCodeAttribute(code);
  RIterator it = _modules->iterator();
  while (it->hasNext() == true) 
  {
    RModuleInfo cm = RModuleInfo(it->next());
    cm->addCodeAttribute(ca);
  }
}

bool 
ClassModulCompiler::checkContext() 
{
  setbaseFileName();
  bool berg = true;
  RIterator it = _units->iterator();
  while (it->hasNext() == true) 
  {
    RUnitInfo ui = RUnitInfo(it->next());
    berg = ui->invokeCodeAttributes() && berg;
  }
  it = _modules->iterator();
  while (it->hasNext() == true) 
  {
    RModuleInfo cm = RModuleInfo(it->next());
    berg = cm->checkContext() && berg;
    berg = cm->invokeCodeAttributes() && berg;
  }
  return berg;
}

void
ClassModulCompiler::writeClsInfoCPPHeader(IN(RPrintWriter) out)
{
  out->println(
  "// Generated by ACDK Metacompiler, \n"
  "// Copyrighted by Roger Rene Kommer, artefaktur\n"
"// \n"
"// Dont edit this file manually\n"
"// \n"
"#include <acdk.h>\n\n"
//"#include <acdk/lang/dmi/MetaAttribute.h>\n"
//"#ifndef ACDK_NOMETAINFO\n\n"
);
  
}

class CountedWriter
: extends ::acdk::io::AbstractFilterWriter
{
  int _count;
public:
  CountedWriter(RWriter out)
  : ::acdk::io::AbstractFilterWriter(out)
  , _count(0)
  {
  }
  foreign virtual void write(byte c)
  {
    _out->write(c);
    ++_count;
  }
  foreign virtual void write(const byte* cstr, int offset, int len)
  {
    _out->write(cstr, offset, len);
    _count += len;
  }
  foreign virtual void write(IN(RbyteArray) ch, int offset = 0, int len = -1)
  {
    if (len == -1)
      len = ch->length() - offset;
    write(ch, offset, len);
    _count += len;
  }
  int byteWritten() { return _count; }
};

void
ClassModulCompiler::setbaseFileName()
{
  RFile file = new File(_path);
  RString outfile;
  if (file->isDirectory() == true) 
  {
    RString pfile = file->getName();
    _baseOutname = File::concat(file->getAbsolutePath(), pfile);
    
  } 
  else 
  {
    RString pfile = file->getName(); 
    _baseOutname = File::concat(file->getParentFile()->getAbsolutePath(), pfile->substr(0, pfile->lastIndexOf(".")));
  }
}

void 
ClassModulCompiler::writeClassInfo()
{
  {
    RIterator it = _modules->iterator();
    bool hasMetaInfo = false;
    while (it->hasNext() == true) {
      RModuleInfo cm = RModuleInfo(it->next());
      if (cm->hasMetaInfo() == true) 
      {
        hasMetaInfo = true;
        break;
      }
      
    }
    if (hasMetaInfo == false)
      return;
  }
  RFile file = new File(_path);
  RString outfile;
  RPrintWriter stubpout;
  if (file->isDirectory() == true) 
  {
    RString pfile = file->getName();
    if (MetaCompiler::generateProxies == true)
    {
      _baseStupOutname = File::concat(file->getAbsolutePath(), pfile);
      RFile extmifile = new File(file, pfile + "_dmiproxy");
      if (extmifile->exists() == false)
        extmifile->mkdir();
      file = extmifile;
      _baseOutname = File::concat(extmifile->getAbsolutePath(), pfile);
      outfile = _baseOutname + "_dmiproxy";
    }
    else if (MetaCompiler::externalMetaInfo == true)
    {
      _baseStupOutname = File::concat(file->getAbsolutePath(), pfile);
      RFile extmifile = new File(file, pfile + "_metainf");
      if (extmifile->exists() == false)
        extmifile->mkdir();
      RString stuboutfilename = _baseStupOutname + "_metainf_base.cpp";
      stubpout = new PrintWriter(new BufferedWriter(new FileWriter(stuboutfilename), 100000), acdk::locale::Encoding::getAsciiEncoding()->getEncoder());

      file = extmifile;
      _baseOutname = File::concat(extmifile->getAbsolutePath(), pfile);
      outfile = _baseOutname + "_metainf_ext";
    }
    else
    {
      _baseOutname = File::concat(file->getAbsolutePath(), pfile);
      outfile = _baseOutname + "_clazzinfo";
    }
  } 
  else 
  {
    RString pfile = file->getName(); 
    _baseOutname = File::concat(file->getParentFile()->getAbsolutePath(), pfile->substr(0, pfile->lastIndexOf(".")));
    RStringBuffer sb  = new StringBuffer(file->getAbsolutePath());
    int pos = sb->toString()->lastIndexOf('.');
    if (pos == -1)
      return;
    sb->replace(pos, sb->length() - 1, "_clazzinfo");
    outfile = sb->toString();
  }
  
  RIterator it = _modules->iterator();
  for (int count = 0;
       it->hasNext() == true;
       ++count)
  {
    writeClassInfo(outfile, stubpout, it, count);
  }
       /*
    if (hasOrbDefinitions())
    writeExtIdl(outfile->replace("_clazzinfo", ".idl"));
    */
}

void 
ClassModulCompiler::writeClassInfo(RString outfile, RPrintWriter stubpout, IN(RIterator) it, int count)
{

  
  if (count > 0)
    outfile = outfile + String::valueOf(count) + ".cpp";
  else
    outfile = outfile + ".cpp";
  

  RFile file = new File(_path);
  RString purefilename = file->getName();
  int pos;
  if ((pos = purefilename->lastIndexOf('/')) != -1)
    purefilename = purefilename->substring(0, pos - 1);

  FileWriter fout(outfile);
  BufferedWriter bufout(&fout, 100000);
  CountedWriter cw(&bufout);
  PrintWriter pout(&cw, acdk::locale::Encoding::getAsciiEncoding()->getEncoder());
  pout.setFlushOnNewLine(false);
  //RPrintWriter out = new PrintWriter(new FileWriter(outfile));
  
  
  
  if (stubpout != Nil && MetaCompiler::getMetaCompiler()->baseMetaInfoHeaderWritten == false)
  {
    writeClsInfoCPPHeader(stubpout);
  }
  writeClsInfoCPPHeader(&pout);
  
  if (file->isDirectory() == true) 
  { 
    pout.print("#include \"");
    if (stubpout != Nil || MetaCompiler::generateProxies)
    {
      pout.print("../");
    }
    pout.println(purefilename + ".h\"");
  } 
  else 
  {
    pout.print("#include \"");
    pout.println(purefilename + "\"");
  }
  
  
  writeModuleHeaderIncludes(&pout, stubpout);
  

  MetaCompiler::getMetaCompiler()->baseMetaInfoHeaderWritten = true;
  if (MetaCompiler::generateProxies == false)
    writeUnitDefinitions(&pout);

  //RIterator it = _modules->iterator();
  while (it->hasNext() == true) 
  {
    RModuleInfo cm = RModuleInfo(it->next());
    cm->writeClsInfoCPP(&pout, stubpout, all_inModules == true);
    if (cw.byteWritten() > 500000)
      break;
  }
  if (stubpout != Nil && MetaCompiler::getMetaCompiler()->dummyExportForExternalMIWritten == false)
  {
    MetaCompiler::getMetaCompiler()->dummyExportForExternalMIWritten = true;
    pout.print("\n#if defined(ACDK_OS_WIN32)\n// force to create an import lib on windows platforms\nvoid __declspec(dllexport) " + purefilename + "_dummyExportFunc() {}\n#endif\n\n");
  }
  //pout.print("\n#endif //ACDK_NOMETAINFO\n\n");
  
}


//static 
void 
ClassModulCompiler::help()
{
  System::out->println("acdkmc [options] [moduldirectory|header");
  System::out->println("       options:");
  System::out->println("  --module-attr attrcode");
  //System::err->println("       -m     all in module_clazzinfo.cpp file :");
  System::out->println(System::getSystemCmdLineOps());
}

RClassModulCompiler gClassModulCompiler;
//static 
RClassModulCompiler 
ClassModulCompiler::getClassModuleCompiler()
{
  return gClassModulCompiler;
}


//static 
int 
ClassModulCompiler::go(RStringArray args)
{
  
  try {

    if (args->length() < 2) {
      help();
      return 1;
    }
    StringArray moduleattrs(0);
    int i = 1;
    acdk::util::logging::RLogger rlogger = acdk::util::logging::LogManager::getRootLogger();
    acdk::util::logging::LogManager::MinLevel = acdk::util::logging::LogManager::Threshold 
      = acdk::util::logging::Info;
    rlogger->addConsumer(new acdk::util::logging::ConsoleConsumer(new acdk::util::logging::SimpleFormatter()));
    bool all_inModules = true;
    for (; i < args->length(); i++) {
      if (args[i]->charAt(0) == '-') 
      {
        RString option = args[i]->substring(1);
        if (option->equals("help") == true || option->equals("-help"))
        {
          help();
          
          return 0;
        }
        if (option->equals("m") == true)
        {
          all_inModules = true;
        } 
        else if (option->equals("-module-attr") == true)
        {
          ++i;
          moduleattrs.append(args[i]);
        }
        else if (option->equals("external-mi") == true) // ### delete this
        {
          MetaCompiler::externalMetaInfo = true;
        }
         else if (option->equals("dmi-proxy") == true || option->equals("dmiproxy") == true) 
        {
          MetaCompiler::generateProxies = true;
        }
        else 
        {
          System::err->print("Unknown Option: ");
          System::err->println(args[i]);
          help();
        }
      } else
        break;
    }
    MetaCompiler::externalMetaInfo = true;
    gClassModulCompiler = new ClassModulCompiler(args[i]);
    gClassModulCompiler->all_inModules = all_inModules;
    //gClassModulCompiler->all_inModules = true;
    int erg = gClassModulCompiler->generate();
    if (erg != 0)
      return erg;

    for (i = 0; i < moduleattrs.length(); ++i)
    {
      gClassModulCompiler->addModuleAttrCode(moduleattrs[i]);
    }
    bool berg = gClassModulCompiler->checkContext();
    //### if warning as error return 1 here
    //gClassModulCompiler->dump(System::err, " ");
    /*
    if (gClassModulCompiler->all_inModules == false)
      gClassModulCompiler->writeMIHs();
      */
    gClassModulCompiler->writeClassInfo();
    gClassModulCompiler = Nil;
    return erg;
  } catch (RThrowable ex) {
    System::err->println("Caught Throwable in System::main(): " + ex->getMessage());
    ex->printStackTrace();
    return -1;
  } catch (...) {
    sys::coreout << "Caught unknown Exception in System::main(): " << sys::eofl;
    System::printStackTrace();
    return -1;
  }
}


} // acdkmc
} // tools
} // acdk
int
main(int argc, char* argv[], char** envptr)
{
  int erg = acdk::lang::System::main(::acdk::tools::acdkmc::ClassModulCompiler::go, argc, argv, envptr);
  return erg;  

}