// **********************************************************************
//
// Copyright (c) 1999
// Object Oriented Concepts, Inc.
// Billerica, MA, USA
//
// All Rights Reserved
//
// **********************************************************************

#ifndef GEN_CPP_H
#define GEN_CPP_H

//
// Declare classes
//
class IdlPrettyPrint;

//
// The C++ code generator class
//
class IdlCPPGenerator
{
    //
    // The header
    //
    static const char* header_;

    //
    // The program name
    //
    const char* prog_;

    //
    // The repository
    //
    CORBA_Repository_var repository_;

    CORBA_RepositoryIdSeq idSeq_;
    IdlStringSeq includeSeq_;

    //
    // List of generated files
    //
    IdlStringSeq* fileNameSeq_;

    //
    // If partial_ is set to true, code is only generated for
    // everything that's in idSeq_;
    //
    bool partial_;

    //
    // If true, don't generate TypeCodes and Any insertion/extraction
    //
    bool noTC_;

    //
    // If true, create locality-constrained objects
    //
    bool local_;

    //
    // If true, don't use virtual inheritance
    //
    bool noVirtual_;

    //
    // If set, make include statements for header files relative to
    // this path
    //
    CORBA_String_var headerDir_;

    //
    // If set, make include statements for header files for included
    // IDL files relative to this path
    //
    CORBA_String_var otherHeaderDir_;

    //
    // If set, put this statement in front of every symbol that needs
    // an explicit DLL import
    //
    CORBA_String_var dllImport_;

    //
    // Suffix for header and source files
    //
    CORBA_String_var hSuff_;
    CORBA_String_var cSuff_;

    //
    // List with all anonymous types
    //
    OBObjSeq< CORBA_TypeCode > anonTCSeq_; // Use addAnon to fill

    //
    // Cache for absolute names
    //
    IdlStringSeq absSeq_;

    //
    // Print header comment
    //
    void comment(const char*, IdlPrettyPrint&);

    //
    // Precede C++ keywords by an underscore
    //
    char* fixKwd(const char*);

    //
    // Add anonymous type
    //
    void addAnon(CORBA_TypeCode_ptr);

    //
    // Create type string
    //
    enum GetType
    {
	GetTypeNormal,  // Normal type string
	GetTypePtr,     // _ptr type string
	GetTypeRef,     // Ref (== _ptr) type string
	GetTypeVar,     // _var type string
	GetTypeStruct,  // Type string for use in structs
	GetTypeSeq,     // Type string for use in sequence templates
	GetTypeArray,   // Type string for use in arrays
	GetTypeSlice,   // Type string for use as array slice
	GetTypeForAny,  // Type string for use as array for any insert/extract
	GetTypeIn,      // Type string for use as in parameter
	GetTypeOut,     // Type string for use as out parameter
	GetTypeInOut,   // Type string for use as inout parameter
	GetTypeReturn,  // Type string for use as return value
	GetTypeConst    // Type string for use in constant declarations
    };
    
    char* getTypeString(const char*, CORBA_TypeCode_ptr,
			GetType = GetTypeNormal,
			bool = false, const char* = 0);

    //
    // Get array type and total number of elements
    //
    void getArrayType(CORBA_TypeCode_ptr, CORBA_TypeCode_ptr&, CORBA_ULong&);

    //
    // Check for C++ type equality
    //
    bool isSameCPPType(CORBA_TypeCode_ptr, CORBA_TypeCode_ptr);

    //
    // Write marshal/unmarshal/marshalCount code
    //
    void writeMarshalCode(CORBA_TypeCode_ptr, bool,
			  const char*, const char*,
			  IdlPrettyPrint&);
    void writeMarshalCountCode(CORBA_TypeCode_ptr, bool,
			       const char*, const char*,
			       IdlPrettyPrint&);
    void writeUnmarshalCode(CORBA_TypeCode_ptr, bool,
			    const char*, const char*, const char*,
			    IdlPrettyPrint&);
    
    //
    // Write unmarshal code for out and inout values
    //
    void writeReturnUnmarshalCode(const char*, CORBA_TypeCode_ptr,
				  IdlPrettyPrint&);
    void writeOutUnmarshalCode(const char*, CORBA_TypeCode_ptr,
			       IdlPrettyPrint&, CORBA_ULong);

    //
    // Check if the implementation and declaration of a type is already
    // in the ORBacus library
    //
    bool isInLibrary(CORBA_TypeCode_ptr);

    //
    // Check if code needs to be generated for a specific repository id
    //
    bool check(const char*);

    //
    // Get absolute name
    //
    char* getAbsolute(CORBA_Contained_ptr);
    char* getAbsolute(const char*);
   
    //
    // Get scope and prefix
    // (prefix is needed if alternative module mapping is used)
    //
    void getScopeAndPrefix(CORBA_Container_ptr, char*&, char*&);

    //
    // Print union labels
    //
    void printUnionLabels(const IdlUnionMemberInfo&, IdlPrettyPrint&,
			  const char*);

    //
    // Generate code for the header file, general part
    //
    void genCPlusPlusH(CORBA_Container_ptr, IdlPrettyPrint&);

    //
    // Generate code for the header file, CORBA namespace part
    //
    void genCPlusPlusHGlobalNamespace(CORBA_Container_ptr, IdlPrettyPrint&);

    //
    // Generate code for the header file, anonymous types part
    //
    void genCPlusPlusHAnonTypes(IdlPrettyPrint&, const char*);

    //
    // Generate code for the source file, general part
    //
    void genCPlusPlusC(CORBA_Container_ptr, IdlPrettyPrint&);

    //
    // Generate code for the source file, anonymous types part
    //
    void genCPlusPlusCAnonTypes(IdlPrettyPrint&, const char*);

    //
    // Generate code for the skeleton header file, general part
    //
    void genCPlusPlusSkelH(CORBA_Container_ptr, IdlPrettyPrint&);

    //
    // Generate code for the skeleton header file, protected part
    //
    void genCPlusPlusSkelHProtected(CORBA_Container_ptr, IdlPrettyPrint&);

    //
    // Generate code for the skeleton source file, general part
    //
    void genCPlusPlusSkelC(CORBA_Container_ptr, IdlPrettyPrint&);

    //
    // Generate code for the skeleton source file, protected part
    //
    void genCPlusPlusSkelCProtected(CORBA_Container_ptr, IdlPrettyPrint&);

    //
    // Generate code for the tie header file
    //
    void genCPlusPlusTieH(CORBA_Container_ptr, IdlPrettyPrint&);

public:

    IdlCPPGenerator(const char*, CORBA_Repository_ptr,
		    const CORBA_RepositoryIdSeq&, const IdlStringSeq&,
		    IdlStringSeq*&, bool, bool, bool,
		    const char*, const char*,
		    const char*, const char*, const char*);

    IdlCPPGenerator(const char*, CORBA_Repository_ptr,
		    IdlStringSeq*&, bool, bool, bool,
		    const char*, const char*,
		    const char*, const char*, const char*);

    //
    // Generate C++ code
    //
    int gen(const char*, const char*);
    int genSkel(const char*, const char*);
    int genTie(const char*, const char*);
};

#endif
