office-gobmx/rsc/source/tools/rscdef.cxx
Matteo Casalin f00967cf38 sal_uIntPtr/sal_uLong to Index (aka sal_uInt32) in UniqueIndex
Change-Id: I212cb3bb9d920741629fc4564bbd28b393e8fe00
2016-03-01 23:51:05 +01:00

677 lines
15 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* 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 .
*/
// overall program includes
#include <rscdef.hxx>
#include <limits.h>
bool RscId::bNames = true;
void RscId::SetNames( bool bSet )
{
bNames = bSet;
}
sal_Int32 RscId::GetNumber() const
{
sal_Int32 lVal;
aExp.Evaluate( &lVal );
return lVal;
}
void RscId::Create( const RscExpType & rExpType )
{
aExp = rExpType;
if( aExp.IsDefinition() )
aExp.aExp.pDef->IncRef();
else if( aExp.IsExpression() )
{
sal_Int32 lValue;
aExp.Evaluate( &lValue );
aExp.SetLong( lValue );
}
}
void RscId::Destroy()
{
if( aExp.IsDefinition() )
aExp.aExp.pDef->DecRef();
aExp.cType = RSCEXP_NOTHING;
}
RscId::RscId( const RscId& rRscId )
{
aExp = rRscId.aExp;
if( aExp.IsDefinition() )
aExp.aExp.pDef->IncRef();
}
RscId::RscId( RscDefine * pDef )
{
RscExpType aExpType;
aExpType.aExp.pDef = pDef;
aExpType.cType = RSCEXP_DEF;
aExpType.cUnused = false;
Create( aExpType );
}
RscId& RscId::operator = ( const RscId& rRscId )
{
if( rRscId.aExp.IsDefinition() )
rRscId.aExp.aExp.pDef->IncRef();
Destroy();
aExp = rRscId.aExp;
return *this;
}
bool RscId::operator == ( const RscId& rRscId ) const
{
return GetNumber() == rRscId.GetNumber();
}
bool RscId::operator < ( const RscId& rRscId ) const
{
return GetNumber() < rRscId.GetNumber();
}
bool RscId::operator > ( const RscId& rRscId ) const
{
return GetNumber() > rRscId.GetNumber();
}
RscId::operator sal_Int32() const
{
return GetNumber();
}
OString RscId::GetName() const
{
OStringBuffer aStr;
if ( !aExp.IsNothing() )
{
if( bNames )
aExp.AppendMacro(aStr);
else
aStr.append(GetNumber());
}
return aStr.makeStringAndClear();
}
RscDefine::RscDefine( sal_uLong lKey, const OString& rDefName, sal_Int32 lDefId )
: StringNode( rDefName )
{
nRefCount = 0;
lFileKey = lKey;
lId = lDefId;
pExp = nullptr;
}
RscDefine::RscDefine( sal_uLong lKey, const OString& rDefName,
RscExpression * pExpression )
: StringNode( rDefName )
, lId(0)
{
nRefCount = 0;
lFileKey = lKey;
pExpression->Evaluate( &lId );
pExp = pExpression;
}
RscDefine::~RscDefine()
{
delete pExp;
if( nRefCount )
RscExit( 14 );
}
void RscDefine::DecRef()
{
nRefCount--;
if( 0 == nRefCount )
{
delete this;
}
}
void RscDefine::DefineToNumber()
{
delete pExp;
pExp = nullptr;
SetName(OString::number(lId));
}
void RscDefine::Evaluate()
{
if( pExp )
pExp->Evaluate( &lId );
}
RscDefine * RscDefine::Search( const char * pStr )
{
return static_cast<RscDefine *>(StringNode::Search( pStr ));
}
OString RscDefine::GetMacro()
{
if( pExp )
return pExp->GetMacro();
return OString::number(lId);
}
RscDefine * RscDefineList::New( sal_uLong lFileKey, const OString& rDefName,
sal_Int32 lDefId, size_t lPos )
{
RscDefine * pDef;
pDef = new RscDefine( lFileKey, rDefName, lDefId );
pDef->IncRef();
if ( lPos < maList.size() )
{
RscSubDefList::iterator it = maList.begin();
::std::advance( it, lPos );
maList.insert( it, pDef );
}
else
{
maList.push_back( pDef );
}
return pDef;
}
RscDefine * RscDefineList::New( sal_uLong lFileKey, const OString& rDefName,
RscExpression * pExpression, size_t lPos )
{
RscDefine * pDef;
pDef = new RscDefine( lFileKey, rDefName, pExpression );
pDef->IncRef();
if ( lPos < maList.size() )
{
RscSubDefList::iterator it = maList.begin();
::std::advance( it, lPos );
maList.insert( it, pDef );
}
else
{
maList.push_back( pDef );
}
return pDef;
}
bool RscDefineList::Remove()
{
if ( maList.empty() )
return false;
maList[ 0 ]->DefineToNumber();
maList[ 0 ]->DecRef();
maList.erase( maList.begin() );
return true;
}
void RscDefineList::WriteAll( FILE * fOutput )
{
for ( size_t i = 0, n = maList.size(); i < n; ++i )
{
RscDefine* pDefEle = maList[ i ];
fprintf( fOutput, "#define %s %s\n",
pDefEle->GetName().getStr(),
pDefEle->GetMacro().getStr()
);
}
}
bool RscExpType::Evaluate( sal_Int32 * plValue ) const
{
if( IsDefinition() )
{
aExp.pDef->Evaluate();
// ignore potential errors
*plValue = aExp.pDef->GetNumber();
}
else if( IsExpression() )
return aExp.pExp->Evaluate( plValue );
else if( IsNothing() )
*plValue = 0;
else
*plValue = GetLong();
return true;
}
void RscExpType::AppendMacro(OStringBuffer& rStr) const
{
if( IsDefinition() )
rStr.append(aExp.pDef->GetName());
else if( IsExpression() )
rStr.append(aExp.pExp->GetMacro());
else if( IsNumber() )
rStr.append(GetLong());
}
RscExpression::RscExpression( RscExpType aLE, char cOp, RscExpType aRE )
{
aLeftExp = aLE;
cOperation = cOp;
aRightExp = aRE;
if( aLeftExp.IsDefinition() )
aLeftExp.aExp.pDef->IncRef();
if( aRightExp.IsDefinition() )
aRightExp.aExp.pDef->IncRef();
}
RscExpression::~RscExpression()
{
if( aLeftExp.IsDefinition() )
aLeftExp.aExp.pDef->DecRef();
else if( aLeftExp.IsExpression() )
delete aLeftExp.aExp.pExp;
if( aRightExp.IsDefinition() )
aRightExp.aExp.pDef->DecRef();
else if( aRightExp.IsExpression() )
delete aRightExp.aExp.pExp;
}
bool RscExpression::Evaluate( sal_Int32 * plValue )
{
sal_Int32 lLeft;
sal_Int32 lRight;
// interpret left and right branches
if( aLeftExp.Evaluate( &lLeft ) && aRightExp.Evaluate( &lRight ) )
{
if( cOperation == '&' )
*plValue = lLeft & lRight;
else if( cOperation == '|' )
*plValue = lLeft | lRight;
else if( cOperation == '+' )
*plValue = lLeft + lRight;
else if( cOperation == '-' )
*plValue = lLeft - lRight;
else if( cOperation == '*' )
*plValue = lLeft * lRight;
else if( cOperation == 'r' )
*plValue = lLeft >> lRight;
else if( cOperation == 'l' )
*plValue = lLeft << lRight;
else
{
if( 0L == lRight )
return false;
*plValue = lLeft / lRight;
}
return true;
}
return false;
}
OString RscExpression::GetMacro()
{
OStringBuffer aLeft;
// output optimization
if( aLeftExp.IsNothing() )
{
if ( '-' == cOperation )
{
aLeft.append('(');
aLeft.append('-');
}
aRightExp.AppendMacro(aLeft);
if( '-' == cOperation )
{
aLeft.append(')');
}
}
else if( aRightExp.IsNothing() )
aLeftExp.AppendMacro(aLeft);
else
{
aLeft.append('(');
// interpret left branch
aLeftExp.AppendMacro(aLeft);
aLeft.append(cOperation);
aLeft.append('(');
// interpret right branch
aRightExp.AppendMacro(aLeft);
aLeft.append(')');
aLeft.append(')');
}
return aLeft.makeStringAndClear();
}
RscFile::RscFile()
{
bLoaded = false;
bIncFile = false;
bDirty = false;
bScanned = false;
}
RscFile::~RscFile()
{
for ( size_t i = 0, n = aDepLst.size(); i < n; ++i )
delete aDepLst[ i ];
aDepLst.clear();
// from back to front is better because of dependencies
// objects are destroyed when reference counter is NULL
while( aDefLst.Remove() ) ;
}
bool RscFile::Depend( sal_uLong lDepend, sal_uLong lFree )
{
for ( size_t i = aDepLst.size(); i > 0; )
{
RscDepend * pDep = aDepLst[ --i ];
if( pDep->GetFileKey() == lDepend )
{
for ( size_t j = i ? --i : 0; j > 0; )
{
pDep = aDepLst[ --j ];
if( pDep->GetFileKey() == lFree )
return true;
}
return false;
}
}
return true;
}
void RscFile::InsertDependFile( sal_uLong lIncFile, size_t lPos )
{
for ( size_t i = 0, n = aDepLst.size(); i < n; ++i )
{
RscDepend* pDep = aDepLst[ i ];
if( pDep->GetFileKey() == lIncFile )
return;
}
// current pointer points to last element
if( lPos >= aDepLst.size() )
{ // the last element must always stay the last one
// put dependency before the last position
aDepLst.push_back( new RscDepend( lIncFile ) );
}
else
{
RscDependList::iterator it = aDepLst.begin();
::std::advance( it, lPos );
aDepLst.insert( it, new RscDepend( lIncFile ) );
}
}
RscDefTree::~RscDefTree()
{
Remove();
}
void RscDefTree::Remove()
{
while( pDefRoot )
{
RscDefine * pDef = pDefRoot;
pDefRoot = static_cast<RscDefine *>(pDefRoot->Remove( pDefRoot ));
pDef->DecRef();
}
}
RscDefine * RscDefTree::Search( const char * pName )
{
if( pDefRoot )
return pDefRoot->Search( pName );
return nullptr;
}
void RscDefTree::Insert( RscDefine * pDef )
{
if( pDefRoot )
pDefRoot->Insert( pDef );
else
pDefRoot = pDef;
pDef->IncRef();
}
void RscDefTree::Remove( RscDefine * pDef )
{
if( pDefRoot )
{
// in case pDef == pDefRoot
pDefRoot = static_cast<RscDefine *>(pDefRoot->Remove( pDef ));
}
pDef->DecRef();
}
bool RscDefTree::Evaluate( RscDefine * pDef )
{
if( pDef )
{
if( !Evaluate( static_cast<RscDefine *>(pDef->Left()) ) )
return false;
if( !Evaluate( static_cast<RscDefine *>(pDef->Right()) ) )
return false;
}
return true;
}
RscFileTab::RscFileTab()
{
}
RscFileTab::~RscFileTab()
{
aDefTree.Remove();
Index aIndex = LastIndex();
while( aIndex != IndexNotFound )
{
delete Remove( aIndex );
aIndex = LastIndex();
};
}
RscFileTab::Index RscFileTab::Find( const OString& rName )
{
Index aIndex = FirstIndex();
while( aIndex != IndexNotFound && (Get(aIndex)->aFileName != rName) )
aIndex = NextIndex(aIndex);
return aIndex;
}
RscDefine * RscFileTab::FindDef( const char * pName )
{
return aDefTree.Search( pName );
}
/* This method gives back true when lDepend
exists and is behind lFree, or when lDepend does not exist. */
bool RscFileTab::Depend( Index lDepend, Index lFree )
{
if( lDepend == lFree )
return true;
Index aIndex = FirstIndex();
while( aIndex != IndexNotFound )
{
RscFile * pFile = Get(aIndex);
if( !pFile->IsIncFile() )
{
if( !pFile->Depend( lDepend, lFree ) )
return false;
}
aIndex = NextIndex(aIndex);
}
return true;
}
bool RscFileTab::TestDef( Index lFileKey, size_t lPos,
const RscDefine * pDefDec )
{
if( lFileKey == pDefDec->GetFileKey() )
{
RscFile * pFile = GetFile( pDefDec->GetFileKey() );
if( pFile && (lPos <= pFile->aDefLst.GetPos( const_cast<RscDefine *>(pDefDec) ))
&& (lPos != ULONG_MAX ) )
{
return false;
}
}
else if( !Depend( lFileKey, pDefDec->GetFileKey() ) )
return false;
return TestDef( lFileKey, lPos, pDefDec->pExp );
}
bool RscFileTab::TestDef( Index lFileKey, size_t lPos,
const RscExpression * pExpDec )
{
if( !pExpDec )
return true;
if( pExpDec->aLeftExp.IsExpression() )
if( !TestDef( lFileKey, lPos, pExpDec->aLeftExp.aExp.pExp ) )
return false;
if( pExpDec->aLeftExp.IsDefinition() )
if( !TestDef( lFileKey, lPos, pExpDec->aLeftExp.aExp.pDef ) )
return false;
if( pExpDec->aRightExp.IsExpression() )
if( !TestDef( lFileKey, lPos, pExpDec->aRightExp.aExp.pExp ) )
return false;
if( pExpDec->aRightExp.IsDefinition() )
if( !TestDef( lFileKey, lPos, pExpDec->aRightExp.aExp.pDef ) )
return false;
return true;
}
RscDefine * RscFileTab::NewDef( Index lFileKey, const OString& rDefName,
sal_Int32 lId, sal_uLong lPos )
{
RscDefine * pDef = FindDef( rDefName );
if( !pDef )
{
RscFile * pFile = GetFile( lFileKey );
if( pFile )
{
pDef = pFile->aDefLst.New( lFileKey, rDefName, lId, lPos );
aDefTree.Insert( pDef );
}
}
else
pDef = nullptr;
return pDef;
}
RscDefine * RscFileTab::NewDef( Index lFileKey, const OString& rDefName,
RscExpression * pExp, sal_uLong lPos )
{
RscDefine * pDef = FindDef( rDefName );
if( !pDef )
{
// are macros in expressions defined?
if( TestDef( lFileKey, lPos, pExp ) )
{
RscFile * pFile = GetFile( lFileKey );
if( pFile )
{
pDef = pFile->aDefLst.New( lFileKey, rDefName, pExp, lPos );
aDefTree.Insert( pDef );
}
}
}
else
pDef = nullptr;
if( !pDef )
{
// pExp is always always owned and must be deleted after used
delete pExp;
}
return pDef;
}
void RscFileTab::DeleteFileContext( Index lFileKey )
{
RscFile* pFName = GetFile( lFileKey );
if( pFName )
{
for ( size_t i = 0, n = pFName->aDefLst.maList.size(); i < n; ++i )
{
RscDefine * pDef = pFName->aDefLst.maList[ i ];
aDefTree.Remove( pDef );
};
while( pFName->aDefLst.Remove() ) ;
}
}
RscFileTab::Index RscFileTab::NewCodeFile( const OString& rName )
{
Index lKey = Find( rName );
if( lKey == IndexNotFound )
{
RscFile * pFName = new RscFile();
pFName->aFileName = rName;
pFName->aPathName = rName;
lKey = Insert( pFName );
pFName->InsertDependFile( lKey, ULONG_MAX );
}
return lKey;
}
RscFileTab::Index RscFileTab::NewIncFile(const OString& rName,
const OString& rPath)
{
Index lKey = Find( rName );
if( lKey == IndexNotFound )
{
RscFile * pFName = new RscFile();
pFName->aFileName = rName;
pFName->aPathName = rPath;
pFName->SetIncFlag();
lKey = Insert( pFName );
pFName->InsertDependFile( lKey, ULONG_MAX );
}
return lKey;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */