/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_idl.hxx"

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <tools/fsys.hxx>
#include <tools/debug.hxx>
#include <database.hxx>
#include <globals.hxx>

/****************** SvIdlDataBase ****************************************/
/*************************************************************************
|*    SvIdlDataBase::SvIdlDataBase()
|*
|*    Beschreibung
*************************************************************************/
/*
void PrimeNumber(){
    sal_uInt16 i, n;
    for( i = 5001; i < 5500; i += 2 ){
        for( n = 2; n < i && ((i % n) != 0); n++ );
        if( n == i ){
            printf( "\nPrimzahl: %d\n", i );
            return;
        }
    }
}
*/

SvIdlDataBase::SvIdlDataBase( const SvCommand& rCmd )
	: bExport( sal_False )
	, nUniqueId( 0 )
    , nVerbosity( rCmd.nVerbosity )
    , bIsModified( sal_False )
    , aPersStream( *IDLAPP->pClassMgr, NULL )
    , pIdTable( NULL )
{
	//PrimeNumber();
}

/*************************************************************************
|*    SvIdlDataBase::~SvIdlDataBase()
|*
|*    Beschreibung
*************************************************************************/
SvIdlDataBase::~SvIdlDataBase()
{
    String * pStr = aIdFileList.First();
    while( pStr )
    {
        delete pStr;
        pStr = aIdFileList.Next();
    }
    delete pIdTable;
}

/*************************************************************************
|*    SvIdlDataBase::GetTypeList()
|*
|*    Beschreibung
*************************************************************************/
#define ADD_TYPE( Name, OdlName, ParserChar, CName, BasName, BasPost )            \
    aTypeList.Append( new SvMetaType( SvHash_##Name()->GetName(),	\
                     BasName, OdlName, ParserChar, CName, BasName, BasPost ) );

SvMetaTypeMemberList & SvIdlDataBase::GetTypeList()
{
    if( aTypeList.Count() == 0 )
    { // Initial fuellen
        aTypeList.Append( new SvMetaTypeString() );
        aTypeList.Append( new SvMetaTypevoid() );

		// MI: IDispatch::Invoke kann keine unsigned
        ADD_TYPE( UINT16,    "long", 'h', "unsigned short", "Long", "&" );
        ADD_TYPE( INT16,     "short", 'h', "short", "Integer", "%" );
        ADD_TYPE( UINT32,    "long", 'l', "unsigned long", "Long", "&" );
        ADD_TYPE( INT32,     "long", 'l', "long", "Long", "&" );
        ADD_TYPE( int,       "int", 'i', "int", "Integer", "%" );
        ADD_TYPE( BOOL,      "boolean", 'b', "unsigned char", "Boolean", "" );
        ADD_TYPE( char,      "char", 'c', "char", "Integer", "%" );
        ADD_TYPE( BYTE,      "char", 'c', "unsigned char", "Integer", "%" );
        ADD_TYPE( float,     "float", 'f', "float", "Single", "!" );
        ADD_TYPE( double,    "double", 'F', "double", "Double", "#" );
        ADD_TYPE( SbxObject, "VARIANT", 'o', "C_Object", "Object", "" );


        // A c h t u n g !!!, bei hinzufuegen von Typen werden alle
        // bin�ren Datenbasen inkompatibel

    /*
        // So tun als ob die Init-Daten auf einem Stream gelesen wurden
        SvMemoryStream aStm;
        aPersStream.SetStream( &aStm );
        // Alle Init-Daten Streamen
        aPersStream << aTypeList;
        // Nur die Id-Zuordnung merken
        aPersStream.SetStream( NULL );
    */
    }
    return aTypeList;
}

/*************************************************************************
|*
|*    SvIdlDataBase::GetModuleInfo()
|*
|*    Beschreibung
|*    Ersterstellung    MM 13.12.94
|*    Letzte Aenderung  MM 13.12.94
|*
*************************************************************************/
SvMetaModule * SvIdlDataBase::GetModule( const ByteString & rName )
{
    for( sal_uLong n = 0; n < aModuleList.Count(); n++ )
        if( aModuleList.GetObject( n )->GetName() == rName )
            return aModuleList.GetObject( n );
    return NULL;
}

/*************************************************************************
|*
|*    SvIdlDataBase::IsBinaryFormat()
|*
|*    Beschreibung
|*
*************************************************************************/
#define DATABASE_SIGNATURE  (sal_uInt32)0x13B799F2
#define DATABASE_VER 0x0006
sal_Bool SvIdlDataBase::IsBinaryFormat( SvStream & rStm )
{
    sal_uInt32  nSig = 0;
    sal_uLong   nPos = rStm.Tell();
    rStm >> nSig;
    rStm.Seek( nPos );

    return nSig == DATABASE_SIGNATURE;
}

/*************************************************************************
|*
|*    SvIdlDataBase::Load()
|*
|*    Beschreibung
|*
*************************************************************************/
void SvIdlDataBase::Load( SvStream & rStm )
{
    DBG_ASSERT( aTypeList.Count() == 0, "type list already initialized" );
    SvPersistStream aPStm( *IDLAPP->pClassMgr, &rStm );

    sal_uInt16  nVersion = 0;
    sal_uInt32  nSig = 0;

    aPStm >> nSig;
    aPStm >> nVersion;
    if( nSig != DATABASE_SIGNATURE )
    {
        aPStm.SetError( SVSTREAM_FILEFORMAT_ERROR );
        return;
    }
    if( nVersion != DATABASE_VER )
    {
        aPStm.SetError( SVSTREAM_WRONGVERSION );
        return;
    }
    aPStm >> aClassList;
    aPStm >> aTypeList;
    aPStm >> aAttrList;
    aPStm >> aModuleList;
    aPStm >> nUniqueId;

    if( aPStm.IsEof() )
        aPStm.SetError( SVSTREAM_GENERALERROR );
}

/*************************************************************************
|*    SvIdlDataBase::Save()
|*
|*    Beschreibung
*************************************************************************/
void SvIdlDataBase::Save( SvStream & rStm, sal_uInt32 nFlags )
{
    SvPersistStream aPStm( *IDLAPP->pClassMgr, &rStm );
    aPStm.SetContextFlags( nFlags );

    aPStm << (sal_uInt32)DATABASE_SIGNATURE;
    aPStm << (sal_uInt16)DATABASE_VER;

    sal_Bool bOnlyStreamedObjs = sal_False;
    if( nFlags & IDL_WRITE_CALLING )
        bOnlyStreamedObjs = sal_True;

    if( bOnlyStreamedObjs )
    {
        SvMetaClassMemberList aList;
        for( sal_uLong n = 0; n < GetModuleList().Count(); n++ )
        {
            SvMetaModule * pModule = GetModuleList().GetObject( n );
            if( !pModule->IsImported() )
                aList.Append( pModule->GetClassList() );
        }
        aPStm << aList;
    }
    else
        aPStm << aClassList;

    //aClassList.WriteObjects( aPStm, bOnlyStreamedObjs );
    aTypeList.WriteObjects( aPStm, bOnlyStreamedObjs );
    aAttrList.WriteObjects( aPStm, bOnlyStreamedObjs );
    aModuleList.WriteObjects( aPStm, bOnlyStreamedObjs );
	aPStm << nUniqueId;
}

/*************************************************************************
|*    SvIdlDataBase::SetError()
|*
|*    Beschreibung
*************************************************************************/
void SvIdlDataBase::SetError( const ByteString & rError, SvToken * pTok )
{
	if( pTok->GetLine() > 10000 )
		aError.SetText( "hgchcg" );

    if( aError.nLine < pTok->GetLine()
      || (aError.nLine == pTok->GetLine() && aError.nColumn < pTok->GetColumn()) )
    {
        aError = SvIdlError( pTok->GetLine(), pTok->GetColumn() );
        aError.SetText( rError );
    }
}

/*************************************************************************
|*    SvIdlDataBase::Push()
|*
|*    Beschreibung
*************************************************************************/
void SvIdlDataBase::Push( SvMetaObject * pObj )
{
	GetStack().Push( pObj );
}

#ifdef IDL_COMPILER
/*************************************************************************
|*
|*    SvIdlDataBase::FindId()
|*
|*    Beschreibung
|*
*************************************************************************/
sal_Bool SvIdlDataBase::FindId( const ByteString & rIdName, sal_uLong * pVal )
{
    if( pIdTable )
    {
        sal_uInt32 nHash;
        if( pIdTable->Test( rIdName, &nHash ) )
        {
            *pVal = pIdTable->Get( nHash )->GetValue();
            return sal_True;
        }
    }
    return sal_False;
}

/*************************************************************************
|*
|*    SvIdlDataBase::InsertId()
|*
|*    Beschreibung
|*
*************************************************************************/
sal_Bool SvIdlDataBase::InsertId( const ByteString & rIdName, sal_uLong nVal )
{
    if( !pIdTable )
        pIdTable = new SvStringHashTable( 20003 );

    sal_uInt32 nHash;
    if( pIdTable->Insert( rIdName, &nHash ) )
    {
        pIdTable->Get( nHash )->SetValue( nVal );
        return sal_True;
    }
    return sal_False;
}

/*************************************************************************
|*    SvIdlDataBase::ReadIdFile()
|*
|*    Beschreibung
*************************************************************************/
sal_Bool SvIdlDataBase::ReadIdFile( const String & rFileName )
{
    DirEntry aFullName( rFileName );
    aFullName.Find( GetPath() );

    String * pIdFile = aIdFileList.First();
    while( pIdFile )
    {
        if( *pIdFile == rFileName )
            return sal_True; // schon eingelesen
        pIdFile = aIdFileList.Next();
    }

    aIdFileList.Insert( new String( rFileName ), LIST_APPEND );

    SvTokenStream aTokStm( aFullName.GetFull() );
    if( aTokStm.GetStream().GetError() == SVSTREAM_OK )
    {
        SvToken * pTok = aTokStm.GetToken_Next();

        while( !pTok->IsEof() )
        {
            if( pTok->IsChar() && pTok->GetChar() == '#' )
            {
                pTok = aTokStm.GetToken_Next();
                if( pTok->Is( SvHash_define() ) )
                {
                    pTok = aTokStm.GetToken_Next();
                    ByteString aDefName;
                    if( pTok->IsIdentifier() )
                        aDefName = pTok->GetString();
                    else
                    {
                        ByteString aStr( "unexpected token after define" );
                        // Fehler setzen
                        SetError( aStr, pTok );
                        WriteError( aTokStm );
                        return sal_False;
                    }

                    sal_uLong nVal = 0;
                    sal_Bool bOk = sal_True;
                    while( bOk )
                    {
                        pTok = aTokStm.GetToken_Next();
                        if( pTok->IsIdentifier() )
                        {
                            sal_uLong n;
                            if( FindId( pTok->GetString(), &n ) )
                                nVal += n;
                            else
                                bOk = sal_False;
                        }
                        else if( pTok->IsChar() )
                        {
                            if( pTok->GetChar() == '-'
                              || pTok->GetChar() == '/'
                              || pTok->GetChar() == '*'
                              || pTok->GetChar() == '&'
                              || pTok->GetChar() == '|'
                              || pTok->GetChar() == '^'
                              || pTok->GetChar() == '~' )
                            {
                                ByteString aStr( "unknown operator '" );
                                aStr += pTok->GetChar();
                                aStr += "'in define";
                                // Fehler setzen
                                SetError( aStr, pTok );
                                WriteError( aTokStm );
                                return sal_False;
                            }
                            if( pTok->GetChar() != '+'
                              && pTok->GetChar() != '('
                              && pTok->GetChar() != ')' )
                                // nur + erlaubt, Klammern spielen kein Rolle,
                                // da + komutativ ist
                                break;
                        }
                        else if( pTok->IsInteger() )
                        {
                            nVal += pTok->GetNumber();
                        }
                        else
                            break;
                    }
                    if( bOk )
                    {
                        if( !InsertId( aDefName, nVal ) )
                        {
	                        ByteString aStr = "hash table overflow: ";
			                SetError( aStr, pTok );
                            WriteError( aTokStm );
                            return sal_False;
                        }
                    }
                }
                else if( pTok->Is( SvHash_include() ) )
                {
                    pTok = aTokStm.GetToken_Next();
                    ByteString aName;
                    if( pTok->IsString() )
                        aName = pTok->GetString();
                    else if( pTok->IsChar() && pTok->GetChar() == '<' )
                    {
                        pTok = aTokStm.GetToken_Next();
                        while( !pTok->IsEof()
                          && !(pTok->IsChar() && pTok->GetChar() == '>') )
                        {
                            aName += pTok->GetTokenAsString();
                            pTok = aTokStm.GetToken_Next();
                        }
                        if( pTok->IsEof() )
                        {
                            ByteString aStr( "unexpected eof in #include" );
                            // Fehler setzen
                            SetError( aStr, pTok );
                            WriteError( aTokStm );
                            return sal_False;
                        }
                    }
                    if( !ReadIdFile( String::CreateFromAscii(aName.GetBuffer()) ) )
                    {
                        ByteString aStr = "cannot read file: ";
                        aStr += aName;
                        SetError( aStr, pTok );
                        WriteError( aTokStm );
                        return sal_False;
                    }
                }
            }
            else
                pTok = aTokStm.GetToken_Next();
        }
    }
    else
        return sal_False;
    return sal_True;
}

/*************************************************************************
|*    SvIdlDataBase::FindType()
|*
|*    Beschreibung
*************************************************************************/
SvMetaType * SvIdlDataBase::FindType( const SvMetaType * pPType,
									SvMetaTypeMemberList & rList )
{
	SvMetaType * pType = rList.First();
	while( pType && pPType != pType )
		pType = rList.Next();
	return pType;
}

SvMetaType * SvIdlDataBase::FindType( const ByteString & rName )
{
	SvMetaType * pType = aTypeList.First();
	while( pType && rName != pType->GetName() )
		pType = aTypeList.Next();
	return pType;
}

/*************************************************************************
|*    SvIdlDataBase::ReadKnownType()
|*
|*    Beschreibung
*************************************************************************/
SvMetaType * SvIdlDataBase::ReadKnownType( SvTokenStream & rInStm )
{
    sal_Bool bIn	= sal_False;
    sal_Bool bOut	= sal_False;
    int nCall0	= CALL_VALUE;
    int nCall1	= CALL_VALUE;
	sal_Bool bSet   = sal_False; //irgent ein Attribut gesetzt

    sal_uInt32  nTokPos = rInStm.Tell();
    SvToken * pTok = rInStm.GetToken_Next();

	if( pTok->HasHash() )
	{
	    sal_uInt32 nBeginPos = 0; // kann mit Tell nicht vorkommen
	    while( nBeginPos != rInStm.Tell() )
	    {
	        nBeginPos = rInStm.Tell();
	        if( pTok->Is( SvHash_in() ) )
	        {
	            bIn  = sal_True;
	            pTok = rInStm.GetToken_Next();
				bSet = sal_True;
	        }
	        if( pTok->Is( SvHash_out() ) )
	        {
	            bOut = sal_True;
	            pTok = rInStm.GetToken_Next();
				bSet = sal_True;
	        }
	        if( pTok->Is( SvHash_inout() ) )
	        {
	            bIn  = sal_True;
	            bOut = sal_True;
	            pTok = rInStm.GetToken_Next();
				bSet = sal_True;
	        }
	    }
	}
/*
    SvMetaTypeList aTmpTypeList;
    if( FillTypeList( aTmpTypeList, pTok ) )
*/
    if( pTok->IsIdentifier() )
    {
        ByteString aName = pTok->GetString();
        SvMetaTypeMemberList & rList = GetTypeList();
        SvMetaType * pType = rList.First();
        while( pType )
        {
            if( pType->GetName() == aName )
				break;
            pType = rList.Next();
        }
		if( pType )
		{
			pTok = rInStm.GetToken();
			if( pTok->IsChar() )
			{
				if( pTok->GetChar() == '&' || pTok->GetChar() == '*' )
				{
					nCall0 = (pTok->GetChar() == '&') ? CALL_REFERENCE :
														CALL_POINTER;
					rInStm.GetToken_Next();
					pTok = rInStm.GetToken();
					if( pTok->GetChar() == '&' || pTok->GetChar() == '*' )
					{
						nCall1 = (pTok->GetChar() == '&') ? CALL_REFERENCE :
															CALL_POINTER;
						rInStm.GetToken_Next();
					}
					bSet = sal_True;
				}
			}
			/*
			SvMetaType * pMetaType = aTmpTypeList.First();
			while( pMetaType )
			{
				if( pMetaType->GetIn() == bIn
				  && pMetaType->GetOut() == bOut
				  && pMetaType->GetCall0() == nCall0
				  && pMetaType->GetCall1() == nCall1 )
				{
					return pMetaType;
				}
				pMetaType = aTmpTypeList.Next();
			}
			*/
			//SvMetaType * pType = aTmpTypeList.First();
			if( !bSet )
				// Ist genau dieser Typ
				return pType;

			DBG_ASSERT( aTmpTypeList.First(), "mindestens ein Element" );
			SvMetaTypeRef xType = new SvMetaType( pType->GetName(), 'h', "dummy" );
			xType->SetRef( pType );
			xType->SetIn( bIn );
			xType->SetOut( bOut );
			xType->SetCall0( nCall0 );
			xType->SetCall1( nCall1 );

			aTmpTypeList.Append( xType );
			return xType;
		}
    }
    rInStm.Seek( nTokPos );
    return NULL;
}

/*************************************************************************
|*
|*    SvIdlDataBase::ReadKnownAttr()
|*
|*    Beschreibung
|*
*************************************************************************/
SvMetaAttribute * SvIdlDataBase::ReadKnownAttr
(
	SvTokenStream & rInStm,
	SvMetaType *	pType	/* Wenn der pType == NULL, dann muss der Typ
							   noch gelesen werden. */
)
{
    sal_uInt32  nTokPos = rInStm.Tell();

	if( !pType )
    	pType = ReadKnownType( rInStm );

    if( pType )
    {
		// Wenn wir Slots auf die Wiese stellen, d"urfen wir nicht voraussetzen,
		// da\s jeder Slot einen anderen Namen hat!
/*
        SvToken * pTok = rInStm.GetToken_Next();
        if( pTok->IsIdentifier() )
            for( sal_uLong n = 0; n < aAttrList.Count(); n++ )
            {
                SvMetaAttribute * pAttr = aAttrList.GetObject( n );
                if( pAttr->GetName() == pTok->GetString() )
                    return pAttr;
            }
*/
    }
    else
    {
        // sonst SlotId?
        SvToken * pTok = rInStm.GetToken_Next();
	    if( pTok->IsIdentifier() )
	    {
			sal_uLong n;
	        if( FindId( pTok->GetString(), &n ) )
	        {
	            for( sal_uLong i = 0; i < aAttrList.Count(); i++ )
	            {
	                SvMetaAttribute * pAttr = aAttrList.GetObject( i );
	                if( pAttr->GetSlotId() == pTok->GetString() )
	                    return pAttr;
	            }
	        }

			ByteString aStr( "Nicht gefunden : " );
			aStr += pTok->GetString();
            DBG_ERROR( aStr.GetBuffer() );
		}
    }

    rInStm.Seek( nTokPos );
    return NULL;
}

SvMetaAttribute* SvIdlDataBase::SearchKnownAttr
(
	const SvNumberIdentifier& rId
)
{
	sal_uLong n;
	if( FindId( rId, &n ) )
	{
	    for( sal_uLong i = 0; i < aAttrList.Count(); i++ )
	    {
	        SvMetaAttribute * pAttr = aAttrList.GetObject( i );
	        if( pAttr->GetSlotId() == rId )
	            return pAttr;
	    }
	}

	return NULL;
}

/*************************************************************************
|*    SvIdlDataBase::ReadKnownClass()
|*
|*    Beschreibung
*************************************************************************/
SvMetaClass * SvIdlDataBase::ReadKnownClass( SvTokenStream & rInStm )
{
    sal_uInt32  nTokPos = rInStm.Tell();
    SvToken * pTok = rInStm.GetToken_Next();

    if( pTok->IsIdentifier() )
        for( sal_uLong n = 0; n < aClassList.Count(); n++ )
        {
            SvMetaClass * pClass = aClassList.GetObject( n );
            if( pClass->GetName() == pTok->GetString() )
                return pClass;
        }

    rInStm.Seek( nTokPos );
    return NULL;
}

/*************************************************************************
|*    SvIdlDataBase::Write()
|*
|*    Beschreibung
*************************************************************************/
void SvIdlDataBase::Write( const ByteString & rText )
{
    if( nVerbosity != 0 )
        fprintf( stdout, "%s", rText.GetBuffer() );
}

/*************************************************************************
|*    SvIdlDataBase::WriteError()
|*
|*    Beschreibung
*************************************************************************/
void SvIdlDataBase::WriteError( const ByteString & rErrWrn,
								const ByteString & rFileName,
								const ByteString & rErrorText,
								sal_uLong nRow, sal_uLong nColumn ) const
{
    //Fehlerbehandlung
    fprintf( stderr, "\n%s --- %s: ( %ld, %ld )\n",
             rFileName.GetBuffer(), rErrWrn.GetBuffer(), nRow, nColumn );

    if( rErrorText.Len() )
    { // Fehler gesetzt
        fprintf( stderr, "\t%s\n", rErrorText.GetBuffer() );
	}
}

/*************************************************************************
|*    SvIdlDataBase::WriteError()
|*
|*    Beschreibung
*************************************************************************/
void SvIdlDataBase::WriteError( SvTokenStream & rInStm )
{
    //Fehlerbehandlung
    String aFileName( rInStm.GetFileName() );
	ByteString aErrorText;
	sal_uLong	nRow = 0, nColumn = 0;

    rInStm.SeekEnd();
    SvToken *pTok = rInStm.GetToken();

    // Fehlerposition
	nRow 	= pTok->GetLine();
	nColumn = pTok->GetColumn();

    if( aError.IsError() )
    { // Fehler gesetzt
        // Fehler Token suchen
	    // Fehlertext
		if( aError.GetText().Len() )
		{
			aErrorText = "may be <";
        	aErrorText += aError.GetText();
		}
		SvToken * pPrevTok = NULL;
        while( pTok != pPrevTok )
        {
			pPrevTok = pTok;
            if( pTok->GetLine() == aError.nLine
              && pTok->GetColumn() == aError.nColumn )
                break;
            pTok = rInStm.GetToken_PrevAll();
        }

        // Fehlerposition
		aErrorText += "> at ( ";
		aErrorText += ByteString::CreateFromInt64(aError.nLine);
		aErrorText += ", ";
		aErrorText += ByteString::CreateFromInt64(aError.nColumn);
		aErrorText += " )";

		// Fehler zuruecksetzen
		aError = SvIdlError();
    }

    WriteError( "error", ByteString( aFileName, RTL_TEXTENCODING_UTF8 ), aErrorText, nRow, nColumn );

    DBG_ASSERT( pTok, "token must be found" );
    if( !pTok )
        return;

    // Identifier in der Naehe suchen
    if( !pTok->IsIdentifier() )
    {
        rInStm.GetToken_PrevAll();
        pTok = rInStm.GetToken();
    }
    if( pTok && pTok->IsIdentifier() )
    {
        ByteString aN = IDLAPP->pHashTable->GetNearString( pTok->GetString() );
        if( aN.Len() )
            fprintf( stderr, "%s versus %s\n", pTok->GetString().GetBuffer(), aN.GetBuffer() );
    }
}

/****************** SvIdlWorkingBase ****************************************/
/*************************************************************************
|*    SvIdlWorkingBase::SvIdlWorkingBase()
|*
|*    Beschreibung
*************************************************************************/
SvIdlWorkingBase::SvIdlWorkingBase(const SvCommand& rCmd) : SvIdlDataBase(rCmd)
{
}

/*************************************************************************
|*    SvIdlWorkingBase::ReadSvIdl()
|*
|*    Beschreibung
*************************************************************************/
sal_Bool SvIdlWorkingBase::ReadSvIdl( SvTokenStream & rInStm, sal_Bool bImported, const String & rPath )
{
    aPath = rPath; // nur fuer den durchlauf gueltig
    SvToken * pTok;
    sal_Bool bOk = sal_True;
        pTok = rInStm.GetToken();
        // nur ein import ganz am Anfang
        if( pTok->Is( SvHash_import() ) )
        {
            rInStm.GetToken_Next();
            rInStm.Read( '(' ); // optional
            pTok = rInStm.GetToken_Next();
            if( pTok->IsString() )
            {
                DirEntry aFullName( String::CreateFromAscii( pTok->GetString().GetBuffer() ) );
                if( aFullName.Find( rPath ) )
                {
                    SvFileStream aStm( aFullName.GetFull(),
                                        STREAM_STD_READ | STREAM_NOCREATE );
                    Load( aStm );
                    if( aStm.GetError() != SVSTREAM_OK )
                    {
                        if( aStm.GetError() == SVSTREAM_WRONGVERSION )
                        {
                            ByteString aStr( "wrong version, file " );
                            aStr += ByteString( aFullName.GetFull(), RTL_TEXTENCODING_UTF8 );
                            SetError( aStr, pTok );
                            WriteError( rInStm );
                            bOk = sal_False;
                        }
                        else
                        {
                            aStm.Seek( 0 );
                            aStm.ResetError();
                            SvTokenStream aTokStm( aStm, aFullName.GetFull() );
                            bOk = ReadSvIdl( aTokStm, sal_True, rPath );
                        }
                    }
                }
                else
                    bOk = sal_False;
            }
            else
                bOk = sal_False;
        }

    sal_uInt32 nBeginPos = 0xFFFFFFFF; // kann mit Tell nicht vorkommen

    while( bOk && nBeginPos != rInStm.Tell() )
    {
        nBeginPos = rInStm.Tell();
        pTok = rInStm.GetToken();
        if( pTok->IsEof() )
            return sal_True;
        if( pTok->IsEmpty() )
            bOk = sal_False;

        // nur ein import ganz am Anfang
        /*else */if( pTok->Is( SvHash_module() ) )
        {
            SvMetaModuleRef aModule = new SvMetaModule( rInStm.GetFileName(), bImported );
            if( aModule->ReadSvIdl( *this, rInStm ) )
                GetModuleList().Append( aModule );
            else
                bOk = sal_False;
        }
        else
            bOk = sal_False;
    }
    if( !bOk || !pTok->IsEof() )
    {
         //Fehlerbehandlung
         WriteError( rInStm );
         return sal_False;
    }
    return sal_True;
}

/*************************************************************************
|*    SvIdlWorkingBase::WriteSvIdl()
|*
|*    Beschreibung
*************************************************************************/
sal_Bool SvIdlWorkingBase::WriteSvIdl( SvStream & rOutStm )
{
    if( rOutStm.GetError() != SVSTREAM_OK )
        return sal_False;

    SvStringHashList aList;
    if( GetIdTable() )
    {
        GetIdTable()->FillHashList( &aList );
        SvStringHashEntry * pEntry = aList.First();
        while( pEntry )
        {
            rOutStm << "#define " << pEntry->GetName().GetBuffer()
                    << '\t'
                    << ByteString::CreateFromInt64(
                        pEntry->GetValue() ).GetBuffer()
                    << endl;
            pEntry = aList.Next();
        }
    }

    for( sal_uLong n = 0; n < GetModuleList().Count(); n++ )
    {
        SvMetaModule * pModule = GetModuleList().GetObject( n );
        //if( !pModule->IsImported() )
            pModule->WriteSvIdl( *this, rOutStm, 0 );
    }
    return sal_True;
}

/*************************************************************************
|*    SvIdlWorkingBase::WriteSfx()
|*
|*    Beschreibung
*************************************************************************/
sal_Bool SvIdlWorkingBase::WriteSfx( SvStream & rOutStm )
{
    if( rOutStm.GetError() != SVSTREAM_OK )
        return sal_False;

	// alle Tmp-Variablen fuer das Schreiben zuruecksetzen
	WriteReset();
	SvMemoryStream aTmpStm( 256000, 256000 );
	sal_uLong n;
    for( n = 0; n < GetModuleList().Count(); n++ )
    {
        SvMetaModule * pModule = GetModuleList().GetObject( n );
        if( !pModule->IsImported() )
            pModule->WriteSfx( *this, aTmpStm );
		aTmpStm.Seek( 0 );
    }
    for( n = 0; n < aUsedTypes.Count(); n++ )
    {
        SvMetaType * pType = aUsedTypes.GetObject( n );
        pType->WriteSfx( *this, rOutStm );
    }
	aUsedTypes.Clear();
	rOutStm << aTmpStm;
    return sal_True;
}

sal_Bool SvIdlWorkingBase::WriteHelpIds( SvStream& rOutStm )
{
    if( rOutStm.GetError() != SVSTREAM_OK )
        return sal_False;

    Table aIdTable;
	sal_uLong n;
    for( n = 0; n < GetModuleList().Count(); n++ )
    {
        SvMetaModule * pModule = GetModuleList().GetObject( n );
        //if( !pModule->IsImported() )
            pModule->WriteHelpIds( *this, rOutStm, &aIdTable );
    }

    const SvMetaAttributeMemberList & rAttrList = GetAttrList();
    for( n = 0; n < rAttrList.Count(); n++ )
    {
        SvMetaAttribute * pAttr = rAttrList.GetObject( n );
        pAttr->WriteHelpId( *this, rOutStm, &aIdTable );
    }

	return sal_True;
}

/*************************************************************************
|*    SvIdlWorkingBase::WriteSfxItem()
|*
|*    Beschreibung
*************************************************************************/
sal_Bool SvIdlWorkingBase::WriteSfxItem( SvStream & )
{
	return sal_False;
}

void SvIdlDataBase::StartNewFile( const String& rName )
{
    bExport = ( aExportFile.EqualsIgnoreCaseAscii( rName ) );
}

void SvIdlDataBase::AppendAttr( SvMetaAttribute *pAttr )
{
	aAttrList.Append( pAttr );
	if ( bExport )
		pAttr->SetNewAttribute( sal_True );
}

sal_Bool SvIdlWorkingBase::WriteCSV( SvStream& rStrm )
{
	SvMetaAttributeMemberList &rList = GetAttrList();
	sal_uLong nCount = rList.Count();
	for ( sal_uLong n=0; n<nCount; n++ )
	{
		if ( rList.GetObject(n)->IsNewAttribute() )
		{
			rList.GetObject(n)->WriteCSV( *this, rStrm );
		}
	}

	if ( rStrm.GetError() != SVSTREAM_OK )
		return sal_False;
	else
		return sal_True;
}

/*************************************************************************
|*    SvIdlWorkingBase::WriteDocumentation()
|*
|*    Beschreibung
*************************************************************************/
sal_Bool SvIdlWorkingBase::WriteDocumentation( SvStream & rOutStm )
{
    if( rOutStm.GetError() != SVSTREAM_OK )
        return sal_False;

    for( sal_uLong n = 0; n < GetModuleList().Count(); n++ )
    {
        SvMetaModule * pModule = GetModuleList().GetObject( n );
        if( !pModule->IsImported() )
            pModule->Write( *this, rOutStm, 0, WRITE_DOCU );
    }
    return sal_True;
}



#endif // IDL_COMPILER