DPDEF142718 Incremental rebuild fails if dependent files deleted (resurrection through merge).
/*
* Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
#include <assert.h>
#include <stdlib.h>
#include <memory.h>
#include "RESOURCE.H"
#include "DATATYPE.H"
#include "Parser.h"
#include "rcomp.hpp"
#include "NUMVAL.H"
#include "MEM.H"
#include "ERRORHAN.H"
#include "UNICODE_COMPRESSOR.H"
#include "main.h"
#if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
using std::endl;
using std::cout;
#endif //__MSVCDOTNET__
extern int verbose;
extern String::CharacterSet SourceCharacterSet;
void Panic(int aCode) // used by UNICODE_COMPRESSOR.CPP
{
exit(aCode);
}
RCTypeArray gTypes;
// StructItem based ostream functions
ostream& SimpleStructItem::StreamOut ( ostream & os)
{
return operator<< ( os, * this);
}
ostream& ArrayStructItem::StreamOut ( ostream & os)
{
return operator<< ( os, * this);
}
ostream& StructTypeStructItem::StreamOut ( ostream & os)
{
return operator<< ( os, * this);
}
ostream& StructArrayStructItem::StreamOut ( ostream & os)
{
return operator<< ( os, * this);
}
ostream& operator<< ( ostream & os, SimpleStructItem & o)
{
os << "SimpleStructItem ";
os << o.iLabel;
os << "\t" << gTypes.GetName( o.iItemType);
os << "\tDefault: " << o.iDefault;
os << "\tLength limit: " << o.iLengthLimit;
os << endl;
return os ;
}
ostream& operator<< ( ostream & os, ArrayStructItem & o)
{
os << "ArrayStructItem ";
os << o.iLabel;
os << "\t" << gTypes.GetName( o.iItemType);
os << "\tDefaults: " << o.iDefaults;
os << "\tLen Type: " << ((o.iLenType == 0) ? "<none>" : gTypes.GetName(o.iLenType));
os << "\tSize: " << o.iSize;
os << endl;
return os ;
}
ostream& operator<< ( ostream & os, StructTypeStructItem & o)
{
os << "StructTypeStructItem ";
os << o.iLabel;
os << endl;
return os;
}
ostream& operator<< ( ostream & os, StructArrayStructItem & o)
{
os << "StructArrayStructItem ";
os << o.iLabel;
os << "\tLen Type: " << ( ( o.iLenType == 0) ? "<none>" : gTypes.GetName( o.iLenType) );
os << "\tSize: " << o.iSize;
os << endl;
return os;
}
ostream& operator<< ( ostream & os, StructItemArray & o)
{
if (o.Size() == 0)
return ( os << "<none>");
StructItemArrayIterator next(o);
StructItem* p;
while ((p = next() ) != NULL)
p->StreamOut(os);
return os;
}
ostream& operator<< ( ostream & os, StructHeader & o)
{
os << "StructHeader ";
os << o.iLabel << endl;
os << "\tLen Type: " << ( ( o.iLenType == 0) ? "<none>" : gTypes.GetName( o.iLenType) ) << endl;
os << o.iSIA;
return os;
}
ostream& operator<< ( ostream & os, StructHeaderArray & o)
{
if (o.Size() == 0)
return ( os << "<none>");
StructHeaderArrayIterator next( o);
StructHeader* p;
while ( ( p = next() ) != NULL)
os << *p;
return os;
}
// ResourceItem based ostream functions
ostream& SimpleResourceItem::StreamOut(ostream& os)
{
return operator<<(os,*this);
}
ostream& ArrayResourceItem::StreamOut(ostream& os)
{
return operator<<(os,*this);
}
ostream& StructTypeResourceItem::StreamOut(ostream& os)
{
return operator<<(os,*this);
}
ostream& StructArrayResourceItem::StreamOut(ostream& os)
{
return operator<<(os,*this);
}
ostream & operator<<(ostream& os,SimpleResourceItem& o)
{
os << "SimpleResourceItem [" << gTypes.GetName(o.iStructItem->iItemType) << " " << o.iStructItem->iLabel << "] ";
switch( o.iStructItem->iItemType)
{
case L_TEXT:
case L_LTEXT:
case L_BUF:
case L_BYTE:
case L_WORD:
case L_LONG:
os << o.iValue;
break;
case L_SRLINK:
break; // Don't know value yet.
}
os << endl;
return os;
}
ostream & operator<< ( ostream & os, ArrayResourceItem & o)
{
os << "ArrayResourceItem [" << o.iStructItem->iLabel << "] ";
os << o.iValues;
os << endl;
return os;
}
ostream & operator<< ( ostream & os, StructTypeResourceItem & o)
{
static unsigned long level = 0; // Recursion level.
os << "StructTypeResourceItem (Level " << level++ << ") [" << o.iStructItem->iLabel << "] " << endl;
os << "----------------------" << endl;
os << o.iResourceItems;
os << "----------------------" << endl;
level--;
return os;
}
ostream & operator<< ( ostream & os, StructArrayResourceItem & o)
{
static unsigned long level = 0; // Recursion level.
os << "StructArrayResourceItem (Level " << level++ << ") [" << o.iStructItem->iLabel << "] " << endl;
DataType counttype = o.iStructItem->iLenType;
if (counttype==0)
counttype = L_WORD;
unsigned long nitems = o.iArrayOfResourceItemArrays.Size();
os << "ArrayLength [" << gTypes.GetName(counttype) << "] " << nitems << endl;
if (nitems > 0)
{
os << "----------------------" << endl;
os << o.iArrayOfResourceItemArrays;
os << "----------------------" << endl;
}
level--;
return os;
}
ostream & operator<< ( ostream & os, ResourceHeader & o)
{
os << "ResourceHeader ";
os << o.iLabel << endl;
os << o.iRIA;
return os;
}
ostream & operator<< ( ostream & os, ResourceItemArray & o)
{
os << "++ResourceItemArray" << endl;
if ( o.iLenType != 0)
{
os << "LenType: " << gTypes.GetName( o.iLenType) << "\t";
}
if ( o.Size() == 0)
return ( os << "<none>");
ResourceItemArrayIterator next( o);
ResourceItem * p;
while ( ( p = next() ) != NULL)
p->StreamOut( os);
return os;
}
ostream & operator<< ( ostream & os, ResourceItemArrayArray & o)
{
os << "--ResourceItemArrayArray" << endl;
if ( o.Size() == 0)
return ( os << "<none>");
ResourceItemArrayArrayIterator next( o);
ResourceItemArray * p;
while ( ( p = next() ) != NULL)
os << * p;
return os;
}
void StreamOutCompressingIfReducesSize(ResourceDataStream& aStream, const UTF16* aUncompressedUnicodeBuffer, int aUncompressedUnicodeLength)
{
const int uncompressedUnicodeSizeInBytes = aUncompressedUnicodeLength*2;
//
// Output buffer allocated to be one byte bigger than uncompressed input buffer.
// This is to allow for what appears to be the worst case where the string cannot be
// compressed at all. In this case enough memory has to be allocated to contain
// the uncompressable string, plus the one-byte compression mode tag.
//
const int maximumOutputLengthInBytes = uncompressedUnicodeSizeInBytes;
unsigned char* const compressedUnicodeBuffer = new unsigned char[maximumOutputLengthInBytes];
assert(compressedUnicodeBuffer != NULL);
int compressedUnicodeSizeInBytes;
CompressUnicode(compressedUnicodeBuffer, compressedUnicodeSizeInBytes, maximumOutputLengthInBytes, aUncompressedUnicodeBuffer, aUncompressedUnicodeLength);
if (compressedUnicodeSizeInBytes < uncompressedUnicodeSizeInBytes)
{
aStream.StartOfCompressedUnicodeRun(uncompressedUnicodeSizeInBytes, (const unsigned char*)aUncompressedUnicodeBuffer);
aStream.StreamIn(compressedUnicodeBuffer, compressedUnicodeSizeInBytes);
aStream.EndOfCompressedUnicodeRun();
}
else if (uncompressedUnicodeSizeInBytes>0)
{
aStream.TwoByteAlignmentPoint();
aStream.StreamIn((const unsigned char*)aUncompressedUnicodeBuffer, uncompressedUnicodeSizeInBytes);
}
delete [] compressedUnicodeBuffer;
}
// ResourceItem based RCBinaryStream functions
// These are used to write the raw data as required in the final output file
static void StreamOutSingleValue(
ResourceDataStream& aStream,
const String & aValue,
unsigned long aLinkValue,
DataType aItemType,
const String * aFileName,
int aLineNumber
)
{
ErrorHandler::Register( aFileName, aLineNumber); // Register in case conversion to number fails.
switch ( aItemType)
{
// 8-bit text
case L_TEXT8:
{ // Null terminator, no leading byte count.
unsigned char * p = new unsigned char[ aValue.Length() + 1];
if ( aValue.Length() > 0)
memcpy( p, aValue.GetAssertedNonEmptyBuffer(), aValue.Length() );
* ( p + aValue.Length() ) = '\0';
aStream.StreamIn(p, aValue.Length() + 1);
delete [] p;
break;
}
case L_LTEXT8:
{ // Leading byte count, no null terminator. (For zero length string a byte containing
// zero is written out.
assert ( aValue.Length() <= 255 );
unsigned char * p = new unsigned char[ aValue.Length() + 1];
if ( aValue.Length() > 0)
memcpy( p + 1, aValue.GetAssertedNonEmptyBuffer(), aValue.Length() );
*p = (unsigned char)(aValue.Length());
aStream.StreamIn(p, aValue.Length() + 1);
delete [] p;
break;
}
case L_BUF8: // Write just the characters from the string.
aStream.StreamIn((const unsigned char*)aValue.GetAssertedNonEmptyBuffer(), aValue.Length());
break;
// 16-bit text
case L_BUF16: // write out unadorned 16-bit characters
{
int output_count; // used as character count for binary output.
// reserve enough for worst case
output_count = aValue.Length();
UTF16 *output_buffer = new UTF16[output_count];
aValue.Export(output_buffer, output_count, SourceCharacterSet);
// write out the buffer as a stream of octets.
#if defined(__TOOLS2_WINDOWS__)
StreamOutCompressingIfReducesSize(aStream, (const unsigned short*)output_buffer, output_count);
#else
StreamOutCompressingIfReducesSize(aStream, output_buffer, output_count);
#endif
delete [] output_buffer;
break;
}
case L_TEXT16: // write out a null-terminated string
// this has no support in BAFL
{
int output_count; // used as character count for binary output.
// reserve enough for worst case + null terminator.
output_count = aValue.Length();
UTF16 *output_buffer = new UTF16[output_count +1];
aValue.Export(output_buffer, output_count, SourceCharacterSet);
output_buffer[output_count] = 0;
output_count +=1;
// write out the buffer as a stream of octets.
#if defined(__TOOLS2_WINDOWS__)
StreamOutCompressingIfReducesSize(aStream, (const unsigned short*)output_buffer, output_count);
#else
StreamOutCompressingIfReducesSize(aStream, output_buffer, output_count);
#endif
delete [] output_buffer;
break;
}
case L_LTEXT16: // write out counted string. The count is in
// an octet, not a word.
{
int output_count; // used as character count for binary output.
unsigned char lbcount; // To hold the leading byte count.
// reserve enough for worst case
output_count = aValue.Length();
// XXX I have commented the assert statement below out, because an LTEXT can't have length
// XXX bigger than 255, but sometimes this happens. A solution would be to throw an error
// XXX in structst.cpp, in the SimpleStructItem::SimpleStructItem() constructor.
UTF16 *output_buffer = new UTF16[output_count];
aValue.Export(output_buffer, output_count, SourceCharacterSet);
// write out the count.
lbcount = (unsigned char) output_count;
aStream.StreamIn(&lbcount,1);
// write out the buffer as a stream of octets.
StreamOutCompressingIfReducesSize(aStream, output_buffer, output_count);
delete [] output_buffer;
break;
}
case L_BYTE:
case L_WORD:
case L_LONG:
case L_DOUBLE:
assert ( aValue.Length() > 0);
if(verbose) { MOFF; cout << "Converting " << aValue << " to number." << endl; MON;}
NumericValue( aValue, aItemType).StreamOut(aStream);
break;
case L_SRLINK:
NumericValue( aLinkValue, L_LONG).StreamOut(aStream);
break;
case L_LINK:
case L_LLINK:
{
if ( aValue.Length() > 0)
{
DataType dtype = ( aItemType == L_LINK) ? L_WORD : L_LONG;
if ( aValue.IsDecNatural() ) // If a resource id was specified explicitly e.g. -75 then output the value.
NumericValue(aValue, dtype).StreamOut(aStream);
else
{
// If FindId fails to find the link it will output an
// appropriate error and kill the program.
ErrorHandler::Register(aFileName, aLineNumber);
unsigned long id = pG->ResourceNameIds.FindId(aValue);
NumericValue(id, dtype).StreamOut(aStream);
}
}
break;
}
default:
{ MOFF; cout << "RCBinaryStream:Unknown type " << gTypes.GetName( aItemType) << endl; MON;}
}
}
void SimpleResourceItem::StreamOut(ResourceDataStream& aStream) const
{
StreamOutSingleValue(aStream, iValue, iLinkValue, iStructItem->iItemType, iFileName, iLineNumber);
}
void ArrayResourceItem::StreamOut(ResourceDataStream& aStream) const
{
NumericValue * itemcount = NULL;
if(iStructItem->iSize.Length() == 0) // STRUCT item says [] i.e. no size specified.
{
if (iStructItem->iLenType == 0) // No LEN declaration so default to WORD.
itemcount = new NumericValue( L_WORD);
else
itemcount = new NumericValue( iStructItem->iLenType); // Use specified type.
* itemcount = iValues.Size();
itemcount->StreamOut(aStream);
delete itemcount;
}
if ( iValues.Size() == 0)
return;
StringArrayIterator next( iValues);
String * p;
while ( ( p = next() ) != NULL)
{
assert( iStructItem->iItemType != L_SRLINK); // Can't handle arrays of SRlinks.
StreamOutSingleValue(aStream, *p, 0, iStructItem->iItemType, iFileName, iLineNumber);
}
}
void StructTypeResourceItem::StreamOut(ResourceDataStream& aStream) const
{
iResourceItems.StreamOut(aStream);
}
void StructArrayResourceItem::StreamOut(ResourceDataStream& aStream) const
{
NumericValue * itemcount = NULL;
if(iStructItem->iLenType == 0) // No LEN declaration so default to WORD.
itemcount = new NumericValue( L_WORD);
else
itemcount = new NumericValue( iStructItem->iLenType); // Use specified type.
* itemcount = iArrayOfResourceItemArrays.Size();
itemcount->StreamOut(aStream);
delete itemcount;
if(iArrayOfResourceItemArrays.Size() == 0)
return;
iArrayOfResourceItemArrays.StreamOut(aStream);
}
void ResourceItemArray::StreamOut(ResourceDataStream& aStream) const
{
if (Size() == 0)
return;
static unsigned int RecursionLevel = 0; // Top level should not have resource size output.
const bool outputSize=((iLenType != 0) && (RecursionLevel > 0));
if (outputSize)
{
aStream.StartOfBlockWithSizePrefix(iLenType);
}
RecursionLevel++;
ResourceItemArrayIterator next(*this);
ResourceItem * p;
while ( ( p = next() ) != NULL)
{
p->StreamOut(aStream);
}
RecursionLevel--;
if (outputSize)
{
aStream.EndOfBlockWithSizePrefix();
}
}
void ResourceItemArrayArray::StreamOut(ResourceDataStream& aStream) const
{
if (Size() == 0)
return;
ResourceItemArrayArrayIterator next(*this);
ResourceItemArray * p;
while ( ( p = next() ) != NULL)
p->StreamOut(aStream);
}