//==================================================================================================
// M e t a _ m o d e l                                                                    Interface
// I n f o r m a t i o n_ e x t r a c t i o n
//                                                                                By Bruno Bachelet
//==================================================================================================
// Copyright (c) 1999-2016
// Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net
//
// This file is part of the B++ Library. This library is free software; you can redistribute it
// and/or modify it under the terms of the GNU Library General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// 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 GNU Library General Public License for more details (http://www.gnu.org).

/*DESCRIPTION*/
/* This modules provides facilities to extract information from C++ or Java source files and
   instantiate the meta-model. */

// File Name //-------------------------------------------------------------------------------------
#line __LINE__ "meta_model/information_extraction.hpp"

// Guardian //--------------------------------------------------------------------------------------
#ifndef guMetaModelInformationExtraction
#define guMetaModelInformationExtraction

// Headers //---------------------------------------------------------------------------------------
#include <bpp/meta_model/structure.hpp> /*INCLUDE*/

namespace bpp {

// Importation/Exportation //-----------------------------------------------------------------------
#ifdef META_MODEL_DLL
 #define dll_export DLL_EXPORT
#else
 #define dll_export DLL_IMPORT
#endif

// Namespaces //------------------------------------------------------------------------------------
#define public_area  metaModelInformationExtraction
#define private_area metaModelInformationExtraction_private

namespace public_area  { /*NAMESPACE*/ using namespace metaModelStructure; }
namespace private_area { using namespace public_area; }

extern_module_name;

// Initialization //--------------------------------------------------------------------------------
#define iniMetaModelInformationExtraction
has_initializer;

// Macrocommands //---------------------------------------------------------------------------------

// Types & Classes //-------------------------------------------------------------------------------
namespace public_area  {}
namespace private_area { class clFolderProcessingDocumentation; }

// Functions Interface //---------------------------------------------------------------------------
namespace public_area {
 function void      buildModuleName(clString &,ctString);
 function void      buildModuleNamespace(clString &,ctString);
 function tyBoolean getModuleInformation(clInStream &,clModuleInformation &);
 inline   void      getModulesInformation(tcString,clModuleInformationX &,tyBoolean=true);
}

namespace private_area {
 function void     getCommentary(clInStream &,clString &);
 function clString getStringI(clInStream &,clString &,tcString);
 function clString getStringII(clInStream &,clString &,tcString);
 function clString getStringIII(clInStream &,clString &,tcString);
 function clString getStringIV(clInStream &,clString &,tcString);
 function void     registerModule(clModuleInformationX &,ctString &,ctString &,ctString &);

 function void getAbstractMethodInformation(clInStream &,clModuleInformation &);
 function void getAttributeInformation(clInStream &,clModuleInformation &);
 function void getAliasInformation(clInStream &,clModuleInformation &);
 function void getClassInformation(clInStream &,clModuleInformation &);
 function void getClassTypeInformation(clInStream &,clModuleInformation &);
 function void getConstantInformation(clInStream &,clModuleInformation &);
 function void getErrorInformation(clInStream &,clModuleInformation &);
 function void getFunctionInformation(clInStream &,clModuleInformation &);
 function void getIncludeInformation(clInStream &,clModuleInformation &);
 function void getMacrocommandInformation(clInStream &,clModuleInformation &);
 function void getMethodInformation(clInStream &,clModuleInformation &);
 function void getNamespaceInformation(clInStream &,clModuleInformation &);
 function void getTypeInformation(clInStream &,clModuleInformation &);
 function void getVariableInformation(clInStream &,clModuleInformation &);
}

// Errors //----------------------------------------------------------------------------------------
namespace public_area {
 /*ERROR*/ extern_error erModuleDescription; /* Problem to interpret a module description. */
 /*ERROR*/ extern_error erIncludeInformation; /* Problem to interpret an include command. */
 /*ERROR*/ extern_error erAliasInformation; /* Problem to interpret an alias command. */
 /*ERROR*/ extern_error erNamespaceInformation; /* Problem to interpret a namespace use. */

 /*ERROR*/ extern_error erMacrocommandInformation;
 /* Problem to interpret a macrocommand definition. */

 /*ERROR*/ extern_error erTypeInformation; /* Problem to interpret a type declaration. */
 /*ERROR*/ extern_error erErrorInformation; /* Problem to interpret an error declaration. */
 /*ERROR*/ extern_error erConstantInformation; /* Problem to interpret a constant declaration. */
 /*ERROR*/ extern_error erVariableInformation; /* Problem to interpret a variable declaration. */
 /*ERROR*/ extern_error erFunctionInformation; /* Problem to interpret a function declaration. */
 /*ERROR*/ extern_error erClassInformation; /* Problem to interpret a class declaration. */

 /*ERROR*/ extern_error erAttributeInformation;
 /* Problem to interpret an attribute declaration. */

 /*ERROR*/ extern_error erMethodInformation; /* Problem to interpret a method declaration. */

 /*ERROR*/ extern_error erClassTypeInformation;
 /* Problem to interpret a type declaration in a class. */
}

// Constants & Variables //-------------------------------------------------------------------------
extern_static_constant(private,tcString,goCodeFileName,?);
extern_static_constant(private,tcString,goHomeFileName,?);
extern_static_constant(private,tcString,goIndexFileName,?);
extern_static_constant(private,tcString,goMenuFileName,?);

extern_static_constant(private,tcString,goAbstractMethodFlag,?);
extern_static_constant(private,tcString,goAliasFlag,?);
extern_static_constant(private,tcString,goAttributeFlag,?);
extern_static_constant(private,tcString,goClassFlag,?);
extern_static_constant(private,tcString,goClassTypeFlag,?);
extern_static_constant(private,tcString,goConstantFlag,?);
extern_static_constant(private,tcString,goDescriptionFlag,?);
extern_static_constant(private,tcString,goDoNotShowFlag,?);
extern_static_constant(private,tcString,goEndAbstractFlag,?);
extern_static_constant(private,tcString,goEndAliasFlag,?);
extern_static_constant(private,tcString,goEndAttributeFlag,?);
extern_static_constant(private,tcString,goEndClassFlag,?);
extern_static_constant(private,tcString,goEndClassTypeFlag,?);
extern_static_constant(private,tcString,goEndCommentaryFlag,?);
extern_static_constant(private,tcString,goEndMethodFlag,?);
extern_static_constant(private,tcString,goEndStructure,?);
extern_static_constant(private,tcString,goErrorFlag,?);
extern_static_constant(private,tcString,goFunctionFlag,?);
extern_static_constant(private,tcString,goIncludeFlag,?);
extern_static_constant(private,tcString,goInterfaceFlag,?);
extern_static_constant(private,tcString,goMacrocommandFlag,?);
extern_static_constant(private,tcString,goMethodFlag,?);
extern_static_constant(private,tcString,goNamespaceFlag,?);
extern_static_constant(private,tcString,goNeedFlag,?);
extern_static_constant(private,tcString,goStartCommentaryFlag,?);
extern_static_constant(private,tcString,goTypeFlag,?);
extern_static_constant(private,tcString,goVariableFlag,?);

// F o l d e r P r o c e s s i n g D o c u m e n t a t i o n  Interface //--------------------------
namespace private_area {
 class clFolderProcessingDocumentation : public clFolderProcessing {
  //-----------------------------------------------------------------------------------------Private
  private_property clString               atModuleName;
  private_property clString               atModulePath;
  private_property tyCardinal             atLevel;
  private_property clModuleInformationX & atModuleInformationX;
  private_property tyBoolean              atDisplayed;
  private_property tyBoolean              atJirk;

  private_property constructor
                   clFolderProcessingDocumentation(const clFolderProcessingDocumentation &);

  private_property clFolderProcessingDocumentation &
                   operator = (const clFolderProcessingDocumentation &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clFolderProcessingDocumentation(clModuleInformationX &,
                                                              tyBoolean=true);

  public_property virtual destructor clFolderProcessingDocumentation(void);

  public_property void startFolder(ctString &);
  public_property void endFolder(ctString &);
  public_property void file(ctString &);
  public_property void unknown(ctString &);
 };
}

// Functions Inline //------------------------------------------------------------------------------
namespace public_area {
 //----------------------------------------------------------------------------GetModulesInformation
 /*FUNCTION*/ /* Extracts information from all the modules in a given folder. */
 inline void getModulesInformation(tcString agFolderName,clModuleInformationX & agInformationX,
                                   tyBoolean agDisplayed) {
  private_area::clFolderProcessingDocumentation lcProcessing(agInformationX,agDisplayed);

  scanFolder(agFolderName,lcProcessing,true);
 }
}

namespace private_area {}

// X X X  Inline //---------------------------------------------------------------------------------
namespace {}

// End //-------------------------------------------------------------------------------------------
}
#undef dll_export
#undef public_area
#undef private_area
#endif
 
//==================================================================================================
// M e t a _ m o d e l                                                               Implementation
// I n f o r m a t i o n _ e x t r a c t i o n
//                                                                                By Bruno Bachelet
//==================================================================================================
// Copyright (c) 1999-2016
// Bruno Bachelet - bruno@nawouak.net
//
// This file is part of the B++ Library. This library is free software you can redistribute it
// and/or modify it under the terms of the GNU Library General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// 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 GNU Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public License along with this
// library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.

// File Name //-------------------------------------------------------------------------------------
#line __LINE__ "meta_model/information_extraction.cpp"

// DLL Belonging //---------------------------------------------------------------------------------
#define META_MODEL_DLL

// Headers //---------------------------------------------------------------------------------------
#include <bpp/meta_model/information_extraction.hpp> /*INTERFACE*/

namespace bpp {

// Namespaces //------------------------------------------------------------------------------------
#define public_area  metaModelInformationExtraction
#define private_area metaModelInformationExtraction_private
#define dll_export   DLL_EXPORT

namespace public_area  {}
namespace private_area {}

static_module_name("Meta_model/Information_extraction");

// Initialization //--------------------------------------------------------------------------------
#undef iniMetaModelInformationExtraction
static_constant(private_area::clInitializer,goInitializer);

// Errors //----------------------------------------------------------------------------------------
namespace public_area {
 static_error erModuleDescription;
 static_error erIncludeInformation;
 static_error erAliasInformation;
 static_error erNamespaceInformation;
 static_error erMacrocommandInformation;
 static_error erTypeInformation;
 static_error erErrorInformation;
 static_error erConstantInformation;
 static_error erVariableInformation;
 static_error erFunctionInformation;
 static_error erClassInformation;
 static_error erAttributeInformation;
 static_error erMethodInformation;
 static_error erClassTypeInformation;
}

// Constants & Variables //-------------------------------------------------------------------------
static_constant(tcString,goCodeFileName);
static_constant(tcString,goHomeFileName);
static_constant(tcString,goIndexFileName);
static_constant(tcString,goMenuFileName);

static_constant(tcString,goAbstractMethodFlag);
static_constant(tcString,goAliasFlag);
static_constant(tcString,goAttributeFlag);
static_constant(tcString,goClassFlag);
static_constant(tcString,goClassTypeFlag);
static_constant(tcString,goConstantFlag);
static_constant(tcString,goDescriptionFlag);
static_constant(tcString,goDoNotShowFlag);
static_constant(tcString,goEndAbstractFlag);
static_constant(tcString,goEndAliasFlag);
static_constant(tcString,goEndAttributeFlag);
static_constant(tcString,goEndClassFlag);
static_constant(tcString,goEndClassTypeFlag);
static_constant(tcString,goEndCommentaryFlag);
static_constant(tcString,goEndMethodFlag);
static_constant(tcString,goEndStructureFlag);
static_constant(tcString,goErrorFlag);
static_constant(tcString,goFunctionFlag);
static_constant(tcString,goIncludeFlag);
static_constant(tcString,goInterfaceFlag);
static_constant(tcString,goMacrocommandFlag);
static_constant(tcString,goMethodFlag);
static_constant(tcString,goNamespaceFlag);
static_constant(tcString,goNeedFlag);
static_constant(tcString,goStartCommentaryFlag);
static_constant(tcString,goTypeFlag);
static_constant(tcString,goVariableFlag);

// Static Members //--------------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// Functions Implementation //----------------------------------------------------------------------
namespace public_area {
 //----------------------------------------------------------------------------------BuildModuleName
 /*FUNCTION*/ /* Builds the name of a module based on its path. */
 function void buildModuleName(clString & agTarget,ctString agSource) {
  tyCharacter lcCharacter     = agSource[0];
  tyBoolean   lcStart         = true;
  tyCardinal  lcSourceCounter = 0;
  tyCardinal  lcTargetCounter = 0;

  agTarget.reserve(agSource.size());

  while (lcCharacter!=end_string) {
   if (lcCharacter=='/') {
    lcStart=true;
    agTarget[lcTargetCounter++]='/';
   }
   else if (lcStart) {
    if (lcCharacter>='a' and lcCharacter<='z')
     agTarget[lcTargetCounter++]=tyCharacter(lcCharacter-'a'+'A');
    else
     agTarget[lcTargetCounter++]=lcCharacter;

    lcStart=false;
   }
   else agTarget[lcTargetCounter++]=lcCharacter;

   lcCharacter=agSource[++lcSourceCounter];
  }

  agTarget[lcTargetCounter]=end_string;
  agTarget.updateSize();
 }
 //-----------------------------------------------------------------------------BuildModuleNamespace
 /*FUNCTION*/ /* Builds the namespace of a module based on its path. */
 function void buildModuleNamespace(clString & agTarget,ctString agSource) {
  tyCharacter lcCharacter     = agSource[0];
  tyBoolean   lcStart         = false;
  tyCardinal  lcSourceCounter = 0;
  tyCardinal  lcTargetCounter = 0;

  agTarget.reserve(agSource.size());

  while (lcCharacter!=end_string) {
   if (lcCharacter=='/' or lcCharacter=='_') {
    lcStart=true;
   }
   else if (lcStart) {
    if (lcCharacter>='a' and lcCharacter<='z')
     agTarget[lcTargetCounter++]=tyCharacter(lcCharacter-'a'+'A');
    else
     agTarget[lcTargetCounter++]=lcCharacter;

    lcStart=false;
   }
   else agTarget[lcTargetCounter++]=lcCharacter;

   lcCharacter=agSource[++lcSourceCounter];
  }

  agTarget[lcTargetCounter]=end_string;
  agTarget.updateSize();
 }
 //-----------------------------------------------------------------------------GetModuleInformation
 /*FUNCTION*/
 /* Extracts module information from a stream. Returns <CODE>false</CODE> if the information of
    the module should not be shown. */
 function tyBoolean getModuleInformation(clInStream & agStream,
                                         clModuleInformation & agInformation) {
  method_name("getModuleInformation");

  clString lcString;
  clString lcDescription;
  clString lcName;
  clString lcTempo;

  agStream >> lcString;

  while (lcString!="") {
   if (lcString==private_area::goDoNotShowFlag) return (false);
   else if (lcString==private_area::goDescriptionFlag)
    private_area::getCommentary(agStream,agInformation.description());
   else if (lcString=="#include")
    private_area::getIncludeInformation(agStream,agInformation);
   else if (lcString==private_area::goNamespaceFlag)
    private_area::getNamespaceInformation(agStream,agInformation);
   else if (lcString==private_area::goAliasFlag)
    private_area::getAliasInformation(agStream,agInformation);
   else if (lcString==private_area::goMacrocommandFlag)
    private_area::getMacrocommandInformation(agStream,agInformation);
   else if (lcString==private_area::goTypeFlag)
    private_area::getTypeInformation(agStream,agInformation);
   else if (lcString==private_area::goErrorFlag)
    private_area::getErrorInformation(agStream,agInformation);
   else if (lcString==private_area::goConstantFlag)
    private_area::getConstantInformation(agStream,agInformation);
   else if (lcString==private_area::goVariableFlag)
    private_area::getVariableInformation(agStream,agInformation);
   else if (lcString==private_area::goFunctionFlag)
    private_area::getFunctionInformation(agStream,agInformation);
   else if (lcString==private_area::goClassFlag)
    private_area::getClassInformation(agStream,agInformation);
   else if (lcString==private_area::goAttributeFlag)
    private_area::getAttributeInformation(agStream,agInformation);
   else if (lcString==private_area::goMethodFlag)
    private_area::getMethodInformation(agStream,agInformation);
   else if (lcString==private_area::goAbstractMethodFlag)
    private_area::getAbstractMethodInformation(agStream,agInformation);
   else if (lcString==private_area::goClassTypeFlag)
    private_area::getClassTypeInformation(agStream,agInformation);

   agStream >> lcString;
  }

  if (agStream.fail()) send_error(erFileReading);
  return (true);
 }
}

namespace private_area {
 //------------------------------------------------------------------------------------GetCommentary
 function void getCommentary(clInStream & agStream,clString & agCommentary) {
  method_name("GetCommentary");

  clString lcString;

  agStream >> lcString;
  if (lcString=="\\") agStream >> lcString;
  if (lcString!=goStartCommentaryFlag) send_error(erStreamReading);
  getStringI(agStream,agCommentary,goEndCommentaryFlag);
 }
 //---------------------------------------------------------------------------------------GetStringI
 function clString getStringI(clInStream & agStream,clString & agString,tcString agEndFormat) {
  method_name("getStringI");

  tyBoolean lcSpace = false;

  clString lcString;

  agString="";
  agStream >> lcString;

  while (lcString!="" and not matched(lcString.data(),agEndFormat)) {
   if (lcString!="\\") {
    if (lcSpace) agString+=" "+lcString;
    else {
     agString+=lcString;
     lcSpace=true;
    }
   }

   agStream >> lcString;
  }

  if (lcString=="" or agStream.fail()) send_error(erStreamReading);
  return (lcString);
 }
 //--------------------------------------------------------------------------------------GetStringII
 function clString getStringII(clInStream & agStream,clString & agString,tcString agEndFormat) {
  method_name("getStringII");

  tyBoolean lcSpace = false;

  clString lcString;

  agString="";
  agStream >> lcString;

  while (lcString!="" and not matched(lcString.data(),agEndFormat)) {
   if (lcString!="\\") {
    if (lcSpace) agString+=" "+lcString;
    else {
     agString+=lcString;
     lcSpace=true;
    }

    if (lastCharacter(agString)==','
        or (lastCharacter(agString)==':' and lcString!=":")) lcSpace=false;
   }

   agStream >> lcString;
  }

  if (lcString=="" or agStream.fail()) send_error(erStreamReading);

  if (lastCharacter(agString)==','
      or (lastCharacter(agString)==':' and lcString!=":")) return (lcString);

  if (lcSpace) return (" "+lcString);
  else return (lcString);
 }
 //-------------------------------------------------------------------------------------GetStringIII
 function clString getStringIII(clInStream & agStream,clString & agString,tcString agEndFormat) {
  method_name("getStringIII");

  tyBoolean lcSpace = false;

  clString lcString;

  agString="";
  agStream >> lcString;

  while (lcString!="" and not matched(lcString.data(),agEndFormat)) {
   if (lcString!="\\") {
    if (lcSpace) agString+=" "+lcString;
    else {
     agString+=lcString;
     lcSpace=true;
    }

    if (lastCharacter(agString)==','
        or (lastCharacter(agString)==':' and lcString!=":")) lcSpace=false;
    else if (lastCharacter(agString)==';' or lcString=="{")
     agString+=standardMaths::string(newLine());
   }

   agStream >> lcString;
  }

  if (lcString=="" or agStream.fail()) send_error(erStreamReading);

  if (lastCharacter(agString)==','
      or (lastCharacter(agString)==':' and lcString!=":")) return (lcString);

  if (lcSpace) return (" "+lcString);
  else return (lcString);
 }
 //--------------------------------------------------------------------------------------GetStringIV
 function clString getStringIV(clInStream & agStream,clString & agString,tcString agEndFormat) {
  method_name("getStringIV");

  tyBoolean lcSpace = false;

  clString lcString;

  agString="";
  agStream >> lcString;

  while (lcString!="" and lcString!=":" and not matched(lcString.data(),agEndFormat)
         and not matched(lcString.data(),private_area::goEndAbstractFlag)) {
   if (lcString!="\\") {
    if (lcSpace) agString+=" "+lcString;
    else {
     agString+=lcString;
     lcSpace=true;
    }

    if (lastCharacter(agString)==','
        or (lastCharacter(agString)==':' and lcString!=":")) lcSpace=false;
   }

   agStream >> lcString;
  }

  if (lcString=="" or agStream.fail()) send_error(erStreamReading);

  if (lastCharacter(agString)==','
      or (lastCharacter(agString)==':' and lcString!=":")) return (lcString);

  if (lcSpace) return (" "+lcString);
  else return (lcString);
 }
 //-----------------------------------------------------------------------------------RegisterModule
 function void registerModule(clModuleInformationX & agModuleInformationX,ctString & agModulePath,
                              ctString & agModuleName,ctString & agShortName) {
  clModuleInformation * lcModuleInformation = new_object(clModuleInformation);

  agModuleInformationX.insert(std_make_pair(agModulePath,lcModuleInformation));
  buildModuleName(lcModuleInformation->name(),agModulePath);
  lcModuleInformation->path()=agModulePath;
  buildModuleNamespace(lcModuleInformation->nameSpace(),agModulePath);

  if (lcModuleInformation->isJava())
   lcModuleInformation->codeTargetFile()=agModuleName+".java";
  else
   lcModuleInformation->codeTargetFile()=agModuleName+goCodeFileName;

  lcModuleInformation->homeTargetFile()=agModuleName+goHomeFileName;
  lcModuleInformation->indexTargetFile()=agModuleName+goIndexFileName;
  lcModuleInformation->menuTargetFile()=agModuleName+goMenuFileName;
  lcModuleInformation->shortName()=agShortName;
  lowerCase(lcModuleInformation->codeTargetFile().data());
  lowerCase(lcModuleInformation->homeTargetFile().data());
  lowerCase(lcModuleInformation->indexTargetFile().data());
  lowerCase(lcModuleInformation->menuTargetFile().data());
 }
 //------------------------------------------------------------------------------GetAliasInformation
 function void getAliasInformation(clInStream & agStream,clModuleInformation & agInformation) {
  method_name("getAliasInformation");

  clEntityInformation lcInfo;
  clString            lcString;

  agStream >> lcString;
  if (lcString!="#define") send_error(erAliasInformation);
  agStream >> lcInfo.name();
  getStringII(agStream,lcInfo.description(),goEndAliasFlag);
  agInformation.aliases().push_back(lcInfo);
 }
 //--------------------------------------------------------------------------GetAttributeInformation
 function void getAttributeInformation(clInStream & agStream,clModuleInformation & agInformation) {
  method_name("getAttributeInformation");

  tyCardinal          lcCounter1;
  tyCardinal          lcCounter2;
  tyCardinal          lcCounter3;
  tyCardinal          lcCounter4;
  clEntityInformation lcInfo;
  clString            lcString1;
  clString            lcString2;

  agStream >> lcInfo.name() >> lcString1;
  if (lcString1!=goEndAttributeFlag) send_error(erAttributeInformation);
  getCommentary(agStream,lcInfo.description());
  lcString2=getStringII(agStream,lcString1,"*;");
  lcString1+=lcString2;

  lcCounter1=0;
  while (lcString1[lcCounter1]!=end_string and lcString1[lcCounter1]!='(') lcCounter1++;
  if (lcCounter1==0) send_error(erAttributeInformation);
  else if (lcString1.part(0,lcCounter1)=="read_only_attribute")
   lcInfo.description()+=" Reading access only.";
  else if (lcString1.part(0,lcCounter1)=="read_write_attribute")
   lcInfo.description()+=" Reading and writing access.";
  else if (lcString1.part(0,lcCounter1)=="read_only_static_attribute")
   lcInfo.description()+=" Reading access only, static attribute.";
  else if (lcString1.part(0,lcCounter1)=="read_write_static_attribute")
   lcInfo.description()+=" Reading and writing access, static attribute.";
  else send_error(erAttributeInformation);

  lcCounter2=lcCounter1;
  while (lcString1[lcCounter2]!=end_string and lcString1[lcCounter2]!=',') lcCounter2++;
  lcCounter4=lcCounter3=lcString1.size();
  while (lcCounter3>0 and lcString1[lcCounter3]!=',') lcCounter3--;

  if (lcString1[lcCounter1]==end_string or lcString1[lcCounter2]==end_string
      or lcCounter4<3+lcCounter3)
   send_error(erAttributeInformation);

  lcString1=lcString1.part(lcCounter1+1,lcCounter2-lcCounter1-1)+" "
            +lcString1.part(lcCounter3+1,lcCounter4-lcCounter3-3)+"()";

  lcInfo.declaration()=lcString1;
  agInformation.attributes().push_back(lcInfo);
 }
 //------------------------------------------------------------------------------GetClassInformation
 function void getClassInformation(clInStream & agStream,clModuleInformation & agInformation) {
  method_name("getClassInformation");

  clEntityInformation lcInfo;
  clString            lcString;

  agStream >> lcInfo.name() >> lcString;
  if (lcString!=goEndClassFlag) send_error(erClassInformation);
  getCommentary(agStream,lcInfo.description());
  getStringII(agStream,lcInfo.declaration(),"{");
  lcInfo.reference()=agInformation.classes().size();
  agInformation.classes().push_back(lcInfo);
 }
 //--------------------------------------------------------------------------GetClassTypeInformation
 function void getClassTypeInformation(clInStream & agStream,clModuleInformation & agInformation) {
  method_name("getClassTypeInformation");

  clEntityInformation lcInfo;
  clString            lcString1;
  clString            lcString2;
  clString            lcString3;

  agStream >> lcInfo.name() >> lcString1;
  if (lcString1!=goEndClassTypeFlag) send_error(erClassTypeInformation);
  getCommentary(agStream,lcInfo.description());
  agStream >> lcString1;
  if (lcString1=="\\") agStream >> lcString1;
  agStream >> lcString1;

  if (lcString1=="typedef") {
   lcString1="type";
   lcString3=getStringII(agStream,lcString2,"*;");
   lcString1+=" "+lcString2+lcString3;
  }
  else if (lcString1=="enumeration") {
   lcString3=getStringI(agStream,lcString2,"*;");
   lcString1+=" "+lcString2+" "+lcString3;
  }
  else if (lcString1=="structure") {
   lcString3=getStringIII(agStream,lcString2,goEndStructureFlag);
   lcString1+=" "+lcString2;
  }
  else if (lcString1=="type_union") {
   lcString3=getStringIII(agStream,lcString2,goEndStructureFlag);
   lcString1+=" "+lcString2;
  }
  else send_error(erClassTypeInformation);

  lcString1.resize(lcString1.size()-1);
  lcInfo.declaration()=lcString1;
  agInformation.classTypes().push_back(lcInfo);
 }
 //---------------------------------------------------------------------------GetConstantInformation
 function void getConstantInformation(clInStream & agStream,clModuleInformation & agInformation) {
  method_name("getConstantInformation");

  tyCardinal          lcCounter1;
  tyCardinal          lcCounter2;
  tyCardinal          lcCounter3;
  clEntityInformation lcInfo;
  clString            lcString1;
  clString            lcString2;

  getCommentary(agStream,lcInfo.description());
  lcString2=getStringII(agStream,lcString1,"*;");
  lcString1+=lcString2;
  lcCounter1=0;
  while (lcString1[lcCounter1]!=end_string and lcString1[lcCounter1]!=',') lcCounter1++;
  if (lcString1[lcCounter1]==end_string) send_error(erConstantInformation);
  lcCounter2=lcCounter1+1;
  while (lcString1[lcCounter2]!=end_string and lcString1[lcCounter2]!=',') lcCounter2++;
  lcCounter3=lcString1.size()-1;
  while (lcCounter3>0 and lcString1[lcCounter3]!=',') lcCounter3--;

  if (lcString1[lcCounter2]==end_string
      or lcCounter3+2>=lcString1.size()) send_error(erConstantInformation);

  lcString1=lcString1.part(lcCounter1+1,lcCounter2-lcCounter1-1)+" "+
            lcString1.part(lcCounter3+1,lcString1.size()-lcCounter3-3);

  if (not agInformation.isJava()) lcString1+="()";
  lcInfo.declaration()=lcString1;
  agInformation.constants().push_back(lcInfo);
 }
 //------------------------------------------------------------------------------GetErrorInformation
 function void getErrorInformation(clInStream & agStream,clModuleInformation & agInformation) {
  method_name("getErrorInformation");

  clEntityInformation lcInfo;
  clString            lcString;

  agStream >> lcString;
  if (lcString!="extern_error") send_error(erErrorInformation);
  agStream >> lcString;
  if (lastCharacter(lcString)!=';') send_error(erErrorInformation);
  lcString.resize(lcString.size()-1);
  getCommentary(agStream,lcInfo.description());
  lcInfo.name()=lcString;
  agInformation.errors().push_back(lcInfo);
 }
 //---------------------------------------------------------------------------GetFunctionInformation
 function void getFunctionInformation(clInStream & agStream,clModuleInformation & agInformation) {
  clEntityInformation lcInfo;
  clString            lcString;

  getCommentary(agStream,lcInfo.description());
  getStringII(agStream,lcInfo.declaration(),"{");
  lcInfo.reference()=agInformation.functions().size();
  agInformation.functions().push_back(lcInfo);
 }
 //----------------------------------------------------------------------------GetIncludeInformation
 function void getIncludeInformation(clInStream & agStream,clModuleInformation & agInformation) {
  method_name("getIncludeInformation");

  clString lcString1;
  clString lcString2;

  agStream >> lcString1 >> lcString2;
  if (lcString1=="" or lcString2=="" or agStream.fail()) send_error(erIncludeInformation);

  if (lcString2==goIncludeFlag) agInformation.includes().push_back(lcString1);
  else if (lcString2==goNeedFlag) agInformation.needs().push_back(lcString1);
  //else if (lcString2!=goInterfaceFlag) send_error(erIncludeInformation);
 }
 //-----------------------------------------------------------------------GetMacrocommandInformation
 function void getMacrocommandInformation(clInStream & agStream,
                                          clModuleInformation & agInformation) {
  method_name("getMacrocommandInformation");

  clEntityInformation lcInfo;
  clString            lcString;

  getCommentary(agStream,lcInfo.description());
  agStream >> lcString;
  while (lcString!="" and lcString!="#define" and lcString!="#undef") agStream >> lcString;
  if (lcString=="") send_error(erMacrocommandInformation);
  agStream >> lcInfo.declaration();
  if (agStream.fail()) send_error(erMacrocommandInformation);
  lcInfo.reference()=agInformation.macrocommands().size();
  agInformation.macrocommands().push_back(lcInfo);
 }
 //-----------------------------------------------------------------------------GetMethodInformation
 function void getMethodInformation(clInStream & agStream,clModuleInformation & agInformation) {
  method_name("getMethodInformation");

  clEntityInformation lcInfo;
  clString            lcString;

  agStream >> lcInfo.name() >> lcString;
  if (lcString!=goEndMethodFlag) send_error(erMethodInformation);
  getCommentary(agStream,lcInfo.description());
  getStringIV(agStream,lcInfo.declaration(),"{*");
  lcInfo.reference()=agInformation.methods().size();
  agInformation.methods().push_back(lcInfo);
 }
 //---------------------------------------------------------------------GetAbstractMethodInformation
 function void getAbstractMethodInformation(clInStream & agStream,
                                            clModuleInformation & agInformation) {
  method_name("getAbstractMethodInformation");

  clEntityInformation lcInfo;
  clString            lcString;

  agStream >> lcInfo.name() >> lcString;
  if (lcString!=goEndMethodFlag) send_error(erMethodInformation);
  getCommentary(agStream,lcInfo.description());

  if (agInformation.isJava()) getStringIV(agStream,lcInfo.declaration(),"//");
  else getStringIV(agStream,lcInfo.declaration(),"=");

  lcInfo.reference()=agInformation.methods().size();
  agInformation.methods().push_back(lcInfo);
 }
 //--------------------------------------------------------------------------GetNamespaceInformation
 function void getNamespaceInformation(clInStream & agStream,clModuleInformation & agInformation) {
  method_name("getNamespaceInformation");

  clString               lcString1;
  clString               lcString2;

  agStream >> lcString1 >> lcString2;
  if (lcString1!="using" or lcString2!="namespace") send_error(erNamespaceInformation);
  agStream >> lcString1;
  if (lastCharacter(lcString1)!=';') send_error(erNamespaceInformation);
  lcString1.resize(lcString1.size()-1);
  if (agStream.fail()) send_error(erNamespaceInformation);
  agInformation.namespaces().push_back(lcString1);
 }
 //-------------------------------------------------------------------------------GetTypeInformation
 function void getTypeInformation(clInStream & agStream,clModuleInformation & agInformation) {
  method_name("getTypeInformation");

  clEntityInformation lcInfo;
  clString            lcString1;
  clString            lcString2;
  clString            lcString3;

  getCommentary(agStream,lcInfo.description());
  agStream >> lcString1;

  if (lcString1=="typedef") {
   lcString1="type";
   lcString3=getStringII(agStream,lcString2,"*;");
   lcString1+=" "+lcString2+lcString3;
  }
  else if (lcString1=="enumeration") {
   lcString3=getStringI(agStream,lcString2,"*;");
   lcString1+=" "+lcString2+" "+lcString3;
  }
  else if (lcString1=="structure") {
   lcString3=getStringIII(agStream,lcString2,goEndStructureFlag);
   lcString1+=" "+lcString2;
  }
  else if (lcString1=="type_union") {
   lcString3=getStringIII(agStream,lcString2,goEndStructureFlag);
   lcString1+=" "+lcString2;
  }
  else send_error(erTypeInformation);

  lcString1.resize(lcString1.size()-1);
  lcInfo.declaration()=lcString1;
  agInformation.types().push_back(lcInfo);
 }
 //---------------------------------------------------------------------------GetVariableInformation
 function void getVariableInformation(clInStream & agStream,clModuleInformation & agInformation) {
  method_name("getVariableInformation");

  tyCardinal          lcCounter1;
  tyCardinal          lcCounter2;
  tyCardinal          lcCounter3;
  clEntityInformation lcInfo;
  clString            lcString1;
  clString            lcString2;

  getCommentary(agStream,lcInfo.description());
  lcString2=getStringII(agStream,lcString1,"*;");
  lcString1+=lcString2;
  lcCounter1=0;
  while (lcString1[lcCounter1]!=end_string and lcString1[lcCounter1]!=',') lcCounter1++;
  if (lcString1[lcCounter1]==end_string) send_error(erVariableInformation);
  lcCounter2=lcCounter1+1;
  while (lcString1[lcCounter2]!=end_string and lcString1[lcCounter2]!=',') lcCounter2++;
  lcCounter3=lcString1.size()-1;
  while (lcCounter3>0 and lcString1[lcCounter3]!=',') lcCounter3--;

  if (lcString1[lcCounter2]==end_string
      or lcCounter3+2>=lcString1.size()) send_error(erVariableInformation);

  lcString1=lcString1.part(lcCounter1+1,lcCounter2-lcCounter1-1)+" "+
            lcString1.part(lcCounter3+1,lcString1.size()-lcCounter3-3);

  if (not agInformation.isJava()) lcString1+="()";
  lcInfo.declaration()=lcString1;
  agInformation.variables().push_back(lcInfo);
 }
}

// F o l d e r P r o c e s s i n g D o c u m e n t a t i o n  Implementation //---------------------
namespace private_area {
 //--------------------------------------------------------------------------------------Constructor
 property clFolderProcessingDocumentation::
 clFolderProcessingDocumentation(clModuleInformationX & agInformationX,tyBoolean agDisplayed)
 : atModuleName(""),atModulePath(""),atLevel(0),atModuleInformationX(agInformationX),
   atDisplayed(agDisplayed),atJirk(false) {}
 //---------------------------------------------------------------------------------------Destructor
 property clFolderProcessingDocumentation::~clFolderProcessingDocumentation(void) {}
 //--------------------------------------------------------------------------------------StartFolder
 property void clFolderProcessingDocumentation::startFolder(ctString & agFullName) {
  clString lcParent = atModulePath;

  clString lcPath;
  clString lcShortName;
  clString lcUpperShortName;

  extractShortName(lcPath,lcShortName,agFullName);
  if (lcShortName=="jirk") atJirk=true;
  lcUpperShortName=lcShortName;

  if (lcUpperShortName.data()[0]>='a' and lcUpperShortName.data()[0]<='z')
   lcUpperShortName.data()[0]=tyCharacter(lcUpperShortName.data()[0]-'a'+'A');

  if (atModuleName=="") {
   atModuleName=lcUpperShortName;
   atModulePath=lcUpperShortName;
  }
  else {
   atModuleName+="_"+lcShortName;
   atModulePath+="/"+lcUpperShortName;
  }

  if (atModuleInformationX.count(atModulePath)==0 and not atJirk) {
   private_area::registerModule(atModuleInformationX,atModulePath,atModuleName,lcUpperShortName);
   atModuleInformationX[atModulePath]->parent()=lcParent;
   if (lcParent!="") atModuleInformationX[lcParent]->children().insert(atModulePath);
   atModuleInformationX[atModulePath]->level()=atLevel++;
   if (atDisplayed) environment::out(atModuleInformationX[atModulePath]->name().data(),true,true);
  }
 }
 //----------------------------------------------------------------------------------------EndFolder
 property void clFolderProcessingDocumentation::endFolder(ctString & agFullName) {
  clString lcPath;
  clString lcShortName;

  tyCardinal lcCounter = atModulePath.size()-1;

  extractShortName(lcPath,lcShortName,agFullName);
  if (lcShortName=="jirk") atJirk=false;
  while (lcCounter>0 and atModulePath[lcCounter]!='/') lcCounter--;
  atModuleName.resize(lcCounter);
  atModulePath.resize(lcCounter);
  atLevel--;
 }
 //---------------------------------------------------------------------------------------------File
 property void clFolderProcessingDocumentation::file(ctString & agFullName) {
  method_name("file");

  clString  lcBody;
  clString  lcCppName;
  clString  lcExtension;
  clInFile  lcFile;
  clString  lcModuleName;
  clString  lcModulePath;
  tyBoolean lcNotShown;
  clString  lcPath;
  clString  lcShortName;
  clString  lcUpperShortName;

  clString lcString = clString("*.")+hppExtension();

  if (not atJirk) {
   // C++ File //
   if (matched(agFullName.data(),lcString.data())) {
    extractShortName(lcPath,lcShortName,agFullName);
    separateFileName(lcBody,lcExtension,lcShortName);
    lcUpperShortName=lcBody;

    if (lcUpperShortName.data()[0]>='a' and lcUpperShortName.data()[0]<='z')
     lcUpperShortName.data()[0]=tyCharacter(lcUpperShortName.data()[0]-'a'+'A');

    if (atModuleName=="") {
     lcModuleName=lcUpperShortName;
     lcModulePath=lcUpperShortName;
    }
    else {
     lcModuleName=atModuleName+"_"+lcBody;
     lcModulePath+=atModulePath+"/"+lcUpperShortName;
    }

    if (atModuleInformationX.count(lcModulePath)==0) {
     private_area::registerModule(atModuleInformationX,lcModulePath,lcModuleName,lcUpperShortName);
     atModuleInformationX[lcModulePath]->parent()=atModulePath;
     atModuleInformationX[lcModulePath]->level()=atLevel;
    }

    if (atDisplayed) environment::out(atModuleInformationX[lcModulePath]->name().data(),true,true);
    atModuleInformationX[lcModulePath]->hppSourceFile()=agFullName;
    separateFileName(lcBody,lcExtension,agFullName);
    lcCppName=lcBody+"."+cppExtension();

    open(lcFile,agFullName.data(),ios::in);
    lcNotShown=(not getModuleInformation(lcFile,*atModuleInformationX[lcModulePath]));
    close(lcFile);
    if (lcFile.fail()) send_error(erFileReading);

    if (fileExists(lcCppName.data())) {
     atModuleInformationX[lcModulePath]->cppSourceFile()=lcCppName;
     open(lcFile,lcCppName.data(),ios::in);
     lcNotShown=lcNotShown or not getModuleInformation(lcFile,*atModuleInformationX[lcModulePath]);
     close(lcFile);
     if (lcFile.fail()) send_error(erFileReading);
    }

    if (lcNotShown) {
     delete_object(atModuleInformationX[lcModulePath]);
     atModuleInformationX.erase(lcModulePath);
    }
    else
     if (atModulePath!="") atModuleInformationX[atModulePath]->children().insert(lcModulePath);
   }

   // Java File //
   else if (matched(agFullName.data(),"*.java")) {
    extractShortName(lcPath,lcShortName,agFullName);
    separateFileName(lcBody,lcExtension,lcShortName);

    if (atModuleName=="") {
     lcModuleName=lcBody;
     lcModulePath=lcBody;
    }
    else {
     lcModuleName=atModuleName+"_"+lcBody;
     lcModulePath+=atModulePath+"/"+lcBody;
    }

    if (atModuleInformationX.count(lcModulePath)==0) {
     private_area::registerModule(atModuleInformationX,lcModulePath,lcModuleName,lcBody);
     atModuleInformationX[lcModulePath]->isJava()=true;
     atModuleInformationX[lcModulePath]->parent()=atModulePath;
     atModuleInformationX[lcModulePath]->level()=atLevel;
    }

    if (atDisplayed) environment::out(atModuleInformationX[lcModulePath]->name().data(),true,true);
    atModuleInformationX[lcModulePath]->hppSourceFile()=agFullName;
    open(lcFile,agFullName.data(),ios::in);
    lcNotShown=(not getModuleInformation(lcFile,*atModuleInformationX[lcModulePath]));

    if (lcNotShown) {
     delete_object(atModuleInformationX[lcModulePath]);
     atModuleInformationX.erase(lcModulePath);
    }
    else
     if (atModulePath!="") atModuleInformationX[atModulePath]->children().insert(lcModulePath);

    close(lcFile);
    if (lcFile.fail()) send_error(erFileReading);
   }
  }
 }
 //------------------------------------------------------------------------------------------Unknown
 property void clFolderProcessingDocumentation::unknown(ctString &) {}
}

// I n i t i a l i z e r  Implementation //---------------------------------------------------------
namespace private_area {
 //--------------------------------------------------------------------------------------------Start
 property void clInitializer::start(void) {
  if (atCounter++ == 0) {
   try {
    #include <bpp/modules.hpp> /*NEED*/
    registerStop(this);
    environment::informInitialization(goModuleName);

    erModuleDescription.create("Meta Model - Problem to extract a module description.");
    erIncludeInformation.create("Meta Model - Problem to extract include documentation.");
    erAliasInformation.create("Meta Model - Problem to extract alias documentation.");
    erNamespaceInformation.create("Meta Model - Problem to extract namespace documentation.");
    erMacrocommandInformation.create("Meta Model - Problem to extract macrocommand documentation.");
    erTypeInformation.create("Meta Model - Problem to extract type documentation.");
    erErrorInformation.create("Meta Model - Problem to extract error documentation.");
    erConstantInformation.create("Meta Model - Problem to extract constant documentation.");
    erVariableInformation.create("Meta Model - Problem to extract variable documentation.");
    erFunctionInformation.create("Meta Model - Problem to extract function documentation.");
    erClassInformation.create("Meta Model - Problem to extract class documentation.");
    erAttributeInformation.create("Meta Model - Problem to extract attribute documentation.");
    erMethodInformation.create("Meta Model - Problem to extract method documentation.");
    erClassTypeInformation.create("Meta Model - Problem to extract type documentation in a class.");

    goCodeFileName  = "--code.htm";
    goHomeFileName  = "--home.htm";
    goIndexFileName = "--index.htm";
    goMenuFileName  = "--menu.htm";

    goAbstractMethodFlag  = "/*AMETHOD";
    goAliasFlag           = "/*ALIAS*/";
    goAttributeFlag       = "/*ATTRIBUTE";
    goClassFlag           = "/*CLASS";
    goClassTypeFlag       = "/*TYPE";
    goConstantFlag        = "/*CONSTANT*/";
    goDescriptionFlag     = "/*DESCRIPTION*/";
    goDoNotShowFlag       = "/*DO_NOT_SHOW*/";
    goEndAbstractFlag     = ";//";
    goEndAliasFlag        = "//";
    goEndAttributeFlag    = "*/";
    goEndClassFlag        = "*/";
    goEndClassTypeFlag    = "*/";
    goEndCommentaryFlag   = "*/";
    goEndMethodFlag       = "*/";
    goEndStructureFlag    = "//";
    goErrorFlag           = "/*ERROR*/";
    goFunctionFlag        = "/*FUNCTION*/";
    goIncludeFlag         = "/*INCLUDE*/";
    goInterfaceFlag       = "/*INTERFACE*/";
    goMacrocommandFlag    = "/*MACROCOMMAND*/";
    goMethodFlag          = "/*METHOD";
    goNamespaceFlag       = "/*NAMESPACE*/";
    goNeedFlag            = "/*NEED*/";
    goStartCommentaryFlag = "/*";
    goTypeFlag            = "/*TYPE*/";
    goVariableFlag        = "/*VARIABLE*/";
   }

   initializer_catch;
  }
 }
 //---------------------------------------------------------------------------------------------Stop
 property void clInitializer::stop(void) { environment::informTermination(goModuleName); }
}

// End //-------------------------------------------------------------------------------------------
}