2005/5/9

     
 

acdkorbidl.cpp

artefaktur
// -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:nil -*- 
//
// Copyright (C) 2000-2005 by Roger Rene Kommer / artefaktur, Kassel, Germany.
// 
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License (LGPL).
// 
// 
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the 
// License ACDK-FreeLicense document enclosed in the distribution
// for more for more details.
// This file is part of the Artefaktur Component Development Kit:
//                         ACDK
// 
// Please refer to
// - http://www.acdk.de
// - http://www.artefaktur.com
// - http://acdk.sourceforge.net
// for more information.
// 
// $Header: /cvsroot/acdk/acdk/acdkx_orb/src/acdkx/orb/idl/acdkorbidl.cpp,v 1.10 2005/02/05 10:45:40 kommer Exp $
#include <acdk.h>
#include <acdk/lang/CmdLineParser.h>
#include <acdk/lang/System.h>
#include <acdk/lang/ClassLoader.h>

#include <acdk/lang/reflect/Unit.h>
#include <acdk/io/FileWriter.h>
#include <acdk/io/PrintWriter.h>
#include <acdk/util/StringTokenizer.h>
#include <algorithm>
#include <stdlib.h> 
#include <search.h>


namespace acdkx {
namespace orb {
namespace idl {

USING_CLASS(::acdk::lang::reflect::, Unit);
USING_CLASS(::acdk::lang::reflect::, Field);

USING_CLASS(::acdk::io::, PrintWriter);
using namespace ::acdk::lang::dmi;


using ::acdk::lang::sys::core_vector;

class AcdkOrbIdl
: extends acdk::lang::Object
{
public :
  RPrintWriter _out;
  /// contains the forward interface declarations
  core_vector<const ClazzInfo*> _interfaceTypeDefs;
  core_vector<const ClazzInfo*> _arrayTypeDefs;
  core_vector<const ClazzInfo*> _knownTypes;
  bool _noFields;
  bool _suppressDublicatedMethods;
  RString _filename;
  bool _onlyExplicitClasses;
  bool _onlyKnownClasses;
  RString _className;
  AcdkOrbIdl()
  : _out()
  , _noFields(false)
  , _suppressDublicatedMethods(true)
  , _onlyExplicitClasses(false)
  , _onlyKnownClasses(false)
  {
  }
  static int acdkmain(RStringArray args);
  void writeUnits(IN(RStringArray) units);
  void writeClasses(IN(RClassArray) classes);
  void writeClass(StringBuffer& sb, IN(RClass) cls);
  void writeStruct(StringBuffer& sb,IN(RClass) cls);
  void writeException(StringBuffer& sb, IN(RClass) cls);
  /// @return true if any constructor/ static methods are written.
  bool writeClassFactory(StringBuffer& sb, IN(RClass) cls);
  void writeForwardDeclarations(StringBuffer& sb);
  void addInterfaceTypeDefs(const ClazzInfo* ci);
  void addArrayTypeDefs(const ClazzInfo* ci);
  bool writeMethod(StringBuffer& sb, const ClazzInfo* ci, const ClazzMethodInfo* mi, int flags);
  void writeMethodArg(StringBuffer& sb, const ClazzInfo* ci, const ClazzMethodInfo* mi, const ClazzMethodArgInfo* ai);
  bool writeField(StringBuffer& sb, const ClazzInfo* ci, const ClazzFieldInfo* fi, int flags);
  
  // returns the type name without attributes
  RString getTypeName(const ClazzInfo* ci);
  RString getReturnType(const ClazzInfo* ci);
  void writeFileHeader();
  void writeFileFooter();
  RString getIncludeGuard();
  static RString objectName(const ClazzInfo* ci);
  static RString fqObjectName(const ClazzInfo* ci);
  static RString paramName(const char* name);
  static bool isException(const ClazzInfo* ci)
  {
    if (ci == Object::clazzInfo())
      return false;
    return Throwable::clazzInfo()->assignableFrom(ci );
  }
  bool isCompatible(const ClazzInfo* ci, const ClazzMethodInfo* mi);
  bool isKnown(const ClazzInfo* ci);
};

//static 
RString 
AcdkOrbIdl::objectName(const ClazzInfo* ci)
{
  if (strcmp(ci->ns, "acdk/lang") == 0 &&
      strcmp(ci->name, "acdk::lang::Object") == 0)
      return "AObject";
  return ci->name;
}

bool 
AcdkOrbIdl::isKnown(const ClazzInfo* ci)
{
  return _knownTypes.find(ci) != _knownTypes.end();
}

//static 
RString 
AcdkOrbIdl::fqObjectName(const ClazzInfo* ci)
{
  if (ci->ns == 0 || *ci->ns == 0)
    return objectName(ci);
  return RString(ci->ns)->replace("/", "::") + "::" + objectName(ci);
}
//static 
RString 
AcdkOrbIdl::paramName(const char* name)
{
  if (strcmp(name, "out") == 0)
    return "out_";
  if (strcmp(name, "in") == 0)
    return "in_";
  if (strcmp(name, "inout") == 0)
    return "inout_";
  if (strcmp(name, "attribute") == 0)
    return "attribute_";
  if (strcmp(name, "exception") == 0)
    return "exception_";
  return name; 
}

void 
AcdkOrbIdl::addInterfaceTypeDefs(const ClazzInfo* ci)
{
  for (int i = 0; i < _interfaceTypeDefs.size(); ++i)
  {
    if (_interfaceTypeDefs[i] == ci)
      return;
  }
  _interfaceTypeDefs.push_back(ci);
}

void 
AcdkOrbIdl::addArrayTypeDefs(const ClazzInfo* ci)
{
  for (int i = 0; i < _arrayTypeDefs.size(); ++i)
  {
    if (_arrayTypeDefs[i] == ci)
      return;
  }
  _arrayTypeDefs.push_back(ci);
}


RString 
AcdkOrbIdl::getTypeName(const ClazzInfo* ci)
{
  if (ci == ClazzInfo::getCharClazz())
    return "char";
  if (ci == ClazzInfo::getByteClazz())
    return "octet";
  if (ci == ClazzInfo::getShortClazz())
    return "short";
  if (ci == ClazzInfo::getIntClazz())
    return "long";
  if (ci == ClazzInfo::getLongClazz())
    return "longlong";
  if (ci == ClazzInfo::getFloatClazz())
    return "float";
  if (ci == ClazzInfo::getDoubleClazz())
    return "double";
  if (ci == ClazzInfo::getBoolClazz())
    return "boolean";
  if (ci == ClazzInfo::getVoidClazz())
    return "void";
  if (ci == String::clazzInfo())
  {
    addInterfaceTypeDefs(ci);
    return "string";
  }
  if (ci->isArray() == true)
  {
    if (ci->userInfo == 0)
    {
      return "unknownArray";
    }
    addArrayTypeDefs(ci);
    return getTypeName(reinterpret_cast<const ClazzInfo*>(ci->userInfo)) + "Array";
  } else {
    
    addInterfaceTypeDefs(ci);
    return fqObjectName(ci);
  }
}

RString 
AcdkOrbIdl::getReturnType(const ClazzInfo* ci)
{
  return getTypeName(ci);
}

void 
AcdkOrbIdl::writeMethodArg(StringBuffer& sb, const ClazzInfo* ci, const ClazzMethodInfo* mi, const ClazzMethodArgInfo* ai)
{
  if (ai->flags & MiAiOut)
  {
    if (ai->flags & MiAiIn)
      sb << "inout ";
    else
      sb << "out ";
  }  
  else //if (ai->flags == 0 || ai->flags & MiAiIn)
    sb << "in ";
  sb << getTypeName(ai->type) << " " << paramName(ai->name);

}

inline
const char* getLabel(const ClazzMethodInfo* mi)
{
  return mi->altlabel != 0 ? mi->altlabel : mi->name;
}

bool isMethodDefinedInSuper(const ClazzInfo* ci, const char* label);
bool hasMethod(const ClazzInfo* ci, const char* label)
{
  for (int i = 0; ci->methods[i] != 0; ++i)
  {
    if (strcmp(label, getLabel(ci->methods[i])) == 0)
      return true;
  }
  return isMethodDefinedInSuper(ci, label);
}

bool
isMethodDefinedInSuper(const ClazzInfo* ci, const char* label)
{
  for (int i = 0; ci->interfaces[i] != 0; ++i)
  {
    if (hasMethod(ci->interfaces[i]->type, label) == true)
      return true;
  }
  return false;
}

bool
AcdkOrbIdl::isCompatible(const ClazzInfo* ci, const ClazzMethodInfo* mi)
{
  for (int i = 0; mi->methodArgs[i] != 0; ++i)
  {
    if (isException(mi->methodArgs[i]->type) == true)
    {
      System::err->println(RString("Method ") + ci->name + "::" + mi->name + " has exception as parameter");
      return false;
    }
  }
  return true;
}

RString 
AcdkOrbIdl::getIncludeGuard()
{
  if (_filename == Nil)
    return Nil;
  return _filename->replace('.', '_');
}

void 
AcdkOrbIdl::writeFileHeader()
{
  _out->print("// generated by acdkorbidl\n\n");
  RString inclguard = getIncludeGuard();
  if (inclguard == Nil)
    return;
  _out->print("#ifndef " + inclguard + "\n#define " + inclguard + "\n\n");
}

void 
AcdkOrbIdl::writeFileFooter()
{
  RString inclguard = getIncludeGuard();
  if (inclguard == Nil)
    return;
  _out->print("#endif // " + inclguard + "\n");
}

bool 
AcdkOrbIdl::writeMethod(StringBuffer& sb, const ClazzInfo* ci, const ClazzMethodInfo* mi, int flags)
{
  if ((mi->flags & MiPublic) == false)
    return false;
  if (isCompatible(ci, mi) == false)
    return false;
  if (_suppressDublicatedMethods == true && 
      isMethodDefinedInSuper(ci, getLabel(mi)) == true)
    return false;
  if (flags & MiStatic)
  {
    if ((mi->flags & MiMiConstructor)  == false &&
        (mi->flags & MiStatic) == false)
      return false;
  }
  else
  {
    if ((mi->flags & MiMiConstructor) ||
        (mi->flags & MiStatic))
      return false;
  }
  if (strcmp(mi->name, "getClass") == 0)
    return false;

  if (mi->altlabel != 0)
    sb << "\n  // orginal method name: " << (char*)mi->name << "\n  ";
  sb << "  ";
  sb << getReturnType(mi->returnType) << " ";
  if (flags & MiStatic && (mi->flags & MiMiConstructor))
    sb << "createCor";
  sb << (char*)getLabel(mi) << "(";
  
  for (int i = 0; mi->methodArgs[i] != 0; ++i)
  {
    if (i != 0)
      sb << ", ";
    writeMethodArg(sb, ci, mi, mi->methodArgs[i]);
  }
  sb << ");\n";
  return true;
}

int compareNames(const ClazzInfo* fci, const ClazzInfo* sci)
{
  if (strcmp(fci->ns, sci->ns) < 0)
    return -1;
  return strcmp(fci->name, sci->name); 
}

int compare(const void* fe, const void* se)
{
  const ClazzInfo** fci = (const ClazzInfo**)fe;
  const ClazzInfo** sci = (const ClazzInfo**)se;
  return compareNames(*fci, *sci);

}

void
writeBaseArrayDeclarations(StringBuffer& sb)
{
  sb << "#include <acdk_base.idl>\n";
  return;
  /*
  sb << "typedef unsigned long longlong;\n"
     << "typedef sequence<boolean> booleanArray;\n"
     << "typedef sequence<octet> octetArray;\n"
     << "typedef sequence<char> charArray;\n"
     << "typedef sequence<short> shortArray;\n"
     << "typedef sequence<long> longArray;\n"
     << "typedef sequence<longlong> longlongArray;\n"
     << "typedef sequence<float> floatArray;\n"
     << "typedef sequence<double> doubleArray;\n"
     << "typedef sequence<string> stringArray;\n"
     << "typedef sequence<stringArray> stringArrayArray;\n"
     ;
     */
}

RString getNsIdentifier(const ClazzInfo* ci)
{
  if (ci == 0 || ci->ns == 0 || *ci->ns == 0)
    return "";
  return RString(ci->ns)->replace('/', '_');
}

void 
AcdkOrbIdl::writeForwardDeclarations(StringBuffer& sb)
{
  writeBaseArrayDeclarations(sb);
  qsort((void*)_interfaceTypeDefs.begin(), _interfaceTypeDefs.end() - _interfaceTypeDefs.begin(), sizeof(_interfaceTypeDefs.begin()), compare);
  const ClazzInfo* lastUnitCi = 0;
  StringBuffer indent;
  for (int i = 0; i < _interfaceTypeDefs.size(); ++i)
  {
    const ClazzInfo* ci = _interfaceTypeDefs[i];
    if (_onlyKnownClasses == true && isKnown(ci) == false)
      continue;
    if (isException(ci) == true)
      continue;
    if (ci == String::clazzInfo())
      continue;

    if (lastUnitCi == 0 || strcmp(lastUnitCi->ns, ci->ns) != 0)
    {
      if (lastUnitCi != 0)
      {
        RStringArray nsa = acdk::util::StringTokenizer(lastUnitCi->ns, "/").allToken();
        for (int j = 0; j < nsa->length(); ++j)
        {
          indent.set(indent.toString()->substr(2));
          sb << indent.toString() << "}; // module " << nsa[j] << "\n";
        }
      }
      
      RStringArray nsa = acdk::util::StringTokenizer(ci->ns, "/").allToken();
      for (int j = 0; j < nsa->length(); ++j)
      {
        sb << indent.toString() << "module " << nsa[j] << "{\n";
        indent << "  ";
      }
      lastUnitCi = ci;
    }
    sb << indent.toString() << "interface " << objectName(ci) << ";\n";
    RString guard = getNsIdentifier(lastUnitCi) + "_" + objectName(ci);
    sb << "#ifndef " << guard << "\n"
      << "#define " << guard << "\n";
    sb << indent.toString() << "typedef sequence<" << objectName(ci) << "> " 
      << objectName(ci) << "Array;\n";
    sb << indent.toString() << "typedef sequence<" << objectName(ci) << "Array> " 
      << objectName(ci) << "ArrayArray;\n";
    sb << "#endif // " << guard << "\n";
    
  }
  if (lastUnitCi != 0)
  {
    RStringArray nsa = acdk::util::StringTokenizer(lastUnitCi->ns, "/").allToken();
    for (int j = 0; j < nsa->length(); ++j)
    {
      sb << "}; // module " << nsa[j] << "\n";
    }
  }
}

bool
AcdkOrbIdl::writeField(StringBuffer& sb, const ClazzInfo* ci, const ClazzFieldInfo* fi, int flags)
{
  if (_noFields == true)
    return false;
  if ((fi->flags & MiPublic) == false)
    return false;
  if ((flags & MiStatic) && ((fi->flags & MiStatic) == false))
    return false;
  if (((flags & MiStatic) == false) && (fi->flags & MiStatic))
    return false;
  if (isException(fi->type) == true)
    return false;
  sb << "  attribute " << getReturnType(fi->type) << " " << paramName(fi->name) << ";\n";
  return true;
}

void 
AcdkOrbIdl::writeException(StringBuffer& sb, IN(RClass) cls)
{
  const ClazzInfo* clazz = cls->objectClazzInfo();
  sb << "\nexception " << cls->getClassName() << "\n{\n";
  RFieldArray fa = cls->getFields();
  for (int i = 0; i < fa->length(); ++i)
  {
    const ClazzFieldInfo* fi = fa[i]->clazzField();
    sb << "  " << getReturnType(fi->type) << " " << paramName(fi->name) << ";\n";
  }
  sb << "};\n";
}

void
AcdkOrbIdl::writeStruct(StringBuffer& sb, IN(RClass) cls)
{
  const ClazzInfo* clazz = cls->objectClazzInfo();
  sb << "struct " << objectName(clazz) << "\n{\n";
  RFieldArray fa = cls->getFields();
  for (int i = 0; i < fa->length(); ++i)
  {
    const ClazzFieldInfo* fi = fa[i]->clazzField();
    sb << "  " << getReturnType(fi->type) << " " << paramName(fi->name) << ";\n";
  }
  sb << "};\n\n";

}

void 
AcdkOrbIdl::writeClass(StringBuffer& sb, IN(RClass) cls)
{
  const ClazzInfo* clazz = cls->objectClazzInfo();
  if (clazz == String::clazzInfo())
    return;

  if (isException(clazz) == true)
  {
    writeException(sb, cls);
    return;
  }
  if (cls->hasMetaAttribute("acdkx_orb_StructType") == true)
  {
    writeStruct(sb, cls);
    return;
  }
  if (_onlyExplicitClasses == true && 
      cls->hasMetaAttribute("acdkx_orb_ClassType") == false)
  {
    return;
  }
  sb << "interface " << objectName(clazz);
  RClass super = cls->getSuperclass();
  bool first = true;
  /*
  if (super != Nil)
  {
    sb << ": ";
    sb <<  super->getName()->replace("/", "::");
    first = false;
  }*/
  RClassArray ifaces = cls->getInterfaces();
  int i;
  for (i = 0; i < ifaces->length(); ++i)
  {
    const ClazzInfo* sci = ifaces[i]->objectClazzInfo();
    if (_onlyKnownClasses == true && isKnown(sci) == false)
      continue;
    if (first == true)
      sb << "\n: ";
    else
      sb << "\n, ";
    
    addInterfaceTypeDefs(sci);
    sb << fqObjectName(sci);
    first = false;
  }
  sb << "\n{\n";
    
  for (i = 0; clazz->fields[i] != 0; ++i)
  {
    writeField(sb, clazz, clazz->fields[i], 0);
  }
  for (i = 0; clazz->methods[i] != 0; ++i)
  {
    writeMethod(sb, clazz, clazz->methods[i], 0);
  }
  sb << "};\n\n";
}

bool isSuperOf(const ClazzInfo* super, const ClazzInfo* deriv)
{
  if (super == deriv)
    return true;
  /*if (super->interfaces[0] == 0)
    return true;
    */
  for (int i = 0; deriv->interfaces[i] != 0; ++i)
  {
    if (isSuperOf(super, deriv->interfaces[i]->type) == true)
      return true;
  }
  return false;
}

int compareClassDeps(IN(RClass) c1, IN(RClass) c2)
{
  const ClazzInfo* clazz1 = c1->objectClazzInfo();
  const ClazzInfo* clazz2 = c2->objectClazzInfo();
  if (AcdkOrbIdl::isException(clazz1) == true)
  {
    if (AcdkOrbIdl::isException(clazz2) == false)
      return -1;
  } 
  else if (AcdkOrbIdl::isException(clazz2) == true)
  {
    return 1;
  }
  if (clazz1 == clazz2)
    return 0;
  if (isSuperOf(clazz1, clazz2) == true)
      return -1;
    if (isSuperOf(clazz2, clazz1) == true)
      return 1;
    return 0;
}

inline
int compareClassDeps(const void* c1, const void* c2) 
{
  return compareClassDeps((*(RClass*)c1), (*(RClass*)c2));
}

void swap(IN(RClassArray) ca, int i, int j)
{
  RClass tcls = ca[i];
  RClass scls = ca[j];
  ca[i] = ca[j];
  ca[j] = tcls;
}

void sortDependencies(INOUT(RClassArray) classes)
{
  bool changed = false;
  do {
    changed = false;
   for (int i = 0; i < classes->length(); ++i)
   {
     for (int j = 0; j < classes->length(); ++j)
     {
       if (compareClassDeps(classes[i], classes[j]) > 0 && i < j)
       {
         swap(classes, i, j);
         //System::out->println("// Swap: " + classes[i]->getName() + " <-> " + classes[j]->getName());
         changed = true;
       }
     }
   }
  } while (changed == true);
  
}

bool 
AcdkOrbIdl::writeClassFactory(StringBuffer& sb, IN(RClass) cls)
{
  const ClazzInfo* clazz = cls->objectClazzInfo();
  if (clazz == String::clazzInfo())
    return false;
  if (isException(clazz) == true)
    return false;
  bool ret = false;
  int i;
  sb << "interface " << objectName(clazz) << "CorFactory";
  /*
  RClass super = cls->getSuperclass();
  bool first = true;
  RClassArray ifaces = cls->getInterfaces();
  
  for (i = 0; i < ifaces->length(); ++i)
  {
    if (first == true)
      sb << "\n: ";
    else
      sb << "\n, ";
    const ClazzInfo* sci = ifaces[i]->objectClazzInfo();
    //addInterfaceTypeDefs(sci);
    sb << fqObjectName(sci) << "CorFactory";
    first = false;
  }*/
  sb << "\n{\n";
    
  for (i = 0; clazz->fields[i] != 0; ++i)
  {
    ret |= writeField(sb, clazz, clazz->fields[i], MiStatic);
  }
  for (i = 0; clazz->methods[i] != 0; ++i)
  {
    ret |= writeMethod(sb, clazz, clazz->methods[i], MiStatic);
  }
  sb << "};\n\n";
  return ret;
}

void 
AcdkOrbIdl::writeClasses(IN(RClassArray) classes)
{
  
  StringBuffer sb;
  
  RStringArray nsa = Nil;
  
  RUnit lunit = Nil;
  int i;
  for (i = 0; i < classes->length(); ++i)
  {
    RClass cls = classes[i];
    if (lunit == Nil || cls->getUnit()->equals(&lunit) == false)
    {
      if (nsa != Nil)
      {
        for (int j = nsa->length() - 1; j >= 0; --j)
        {
          sb << "}; // module " << nsa[j] << "\n";  
        }
      }
      lunit = cls->getUnit();
      nsa = acdk::util::StringTokenizer(lunit->getName(), "/").allToken();    
      for (int j = 0; j < nsa->length(); ++j)
      {
        sb << "module " << nsa[j] << " {\n";  
      }
    }
    writeClass(sb, classes[i]);
    StringBuffer sb2;
    bool berg = writeClassFactory(sb2, classes[i]);
    if (berg)
      sb << sb2.toString();
  }
  if (nsa != Nil)
  {
    for (int j = nsa->length() - 1; j >= 0; --j)
    {
      sb << "}; // module " << nsa[j] << "\n";  
    }
  }
  {
    StringBuffer sbf; 
    // print forward declarations
    writeForwardDeclarations(sbf);
    _out->print(sbf.toString());
  }
  
  _out->print(sb.toString());
  
}

void 
AcdkOrbIdl::writeUnits(IN(RStringArray) unitnames)
{
  RClassArray classes = new ClassArray(0);
  RUnitArray units = new UnitArray(0);
  writeFileHeader();
  for (int i = 0; i < unitnames->length(); ++i)
  {
    RUnit unit = ClassLoader::getSystemClassLoader()->loadUnit(unitnames[i]);
    RString unitincl = "acdkx_orb_UnitInclude";
    acdk::lang::dmi::RMetaAttribute ma;
    for (int j = 1; ma = unit->getMetaAttribute(unitincl + j); ++j)
    {
      _out->print("#include <" + RString(ma->value) + ">\n");
    }
    units->append(unit);
    if (_className != Nil)
    {
      RClassArray clsar = unit->getClasses();
      for (int j = 0; j < clsar->length(); ++j)
        if (_className->equals(clsar[j]->getName()) == true)
          classes->append(clsar[j]);
    }
    else
      classes->concat(unit->getClasses());
  }
  sortDependencies(classes);
  writeClasses(classes);
  writeFileFooter();
}

void help()
{
  System::out->println(
    "acdkorbidl [options]\n"
    "  with options:\n"
    "  -o|--output <filename>   where to write output\n"
    "  -u|--unit <unitname>     unit to include\n"
    "  --no-fields              no attributes\n"
    "  -k|--only-known          generate only known declared corba-interface\n"
    "  -x|--only-explict        generate only explicit declared corba-interface\n"
    "  -c|--classname <classname> generate IDL for a single class (example acdk/text/RegExp)\n"
    );
}

#define INCR_PARAM(msg) \
++i; \
if (i >= args->length())  \
{ \
  System::out->println("option need value: " msg); \
  help(); \
  return 1; \
} \
value = args[i]

//static 
int 
AcdkOrbIdl::acdkmain(RStringArray args)
{
  try {
    
  AcdkOrbIdl oidl;
  //oidl._out = System::out;
  RStringArray units = new StringArray(0);
  for (int i = 0; i < args->length(); ++i)
  {
    RString param = args[i];
    RString value;
    if (param->equals("--output") || param->equals("-o"))
    {
      INCR_PARAM("-o");
      oidl._out = new PrintWriter(new acdk::io::FileWriter(value));
      oidl._filename = value;
    }
    else if (param->equals("-u") || param->equals("--unit"))
    {
      INCR_PARAM("-u");
      units->append(value);
    }
    else if (param->equals("--no-fields") == true)
    {
      oidl._noFields = true;
    }
    else if (param->equals("-x") == true || param->equals("--only-explict") == true)
    {
      oidl._onlyExplicitClasses = true;
    }
    else if (param->equals("-k") == true || param->equals("--only-known") == true)
    {
      oidl._onlyKnownClasses = true;
    } 
    else if (param->equals("-c") == true || param->equals("--classname") == true)
    {
      INCR_PARAM("-c");
      oidl._className = args[i];
    }
  }

  if (oidl._out == Nil)
    oidl._out = System::out;
  oidl.writeUnits(units);

  } 
  catch (RThrowable ex)
  {
    System::err->println(ex->getMessage());
  }
  return 0;
}

} //namespace idl 
} // namespace orb 
} //namespace acdkx 
    int 
main(int argc, char* argv[], char** envptr)
{

  return acdk::lang::System::main(acdkx::orb::idl::AcdkOrbIdl::acdkmain, argc, argv, envptr);
}