fix: make sure host attribute is set rather than blank in logs on windows by using the env var 'COMPUTERNAME' instead of 'HOSTNAME'. Thus make it less difficult to order recipes in the log by time.
/*
* Copyright (c) 2000-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 <stdio.h>
#include <string.h>
#include "unistd.h"
#if defined( __MSVCDOTNET__) || defined(__TOOLS2__)
#include <iostream>
using std::cout;
using std::endl;
using std::cerr;
#else //!__MSVCDOTNET__
#ifndef __LINUX__
#include <io.h>
#endif //!__LINUX__
#endif //__MSVCDOTNET__
#include "RESOURCE.H"
#include "DATATYPE.H"
#include "MEM.H"
#include "RCBINSTR.H"
#include "NUMVAL.H"
#include "ERRORHAN.H"
#include "FILEACC.H"
#include "VERSION.H"
#include "CTABLE.H"
#include "main.h"
#include "TOKENS.H"
#include "localise.h"
#include "qualifar.h"
#include "messages.h"
extern NameIdMap* pResourceNameIds;
extern long CurrentId;
void WriteHeaderFile(FILE* aRSG, IndexTable& aIndex)
{
IndexTableIterator next(aIndex);
IndexTableItem * p;
while( ( p = next() ) != NULL)
{
ResourceHeader& r=p->Resource();
if (r.iLabel.Length()>0 && !r.iLocal)
{
r.iLabel.Upper();
if (r.iFormatAsHex)
fprintf(aRSG, "#define %-41s 0x%x\n", r.iLabel.GetAssertedNonEmptyBuffer(), r.iResourceId);
else
fprintf(aRSG, "#define %-41s %d\n", r.iLabel.GetAssertedNonEmptyBuffer(), r.iResourceId);
}
}
}
void WriteBitArrayOfResourcesContainingCompressedUnicode(RCBinaryStream& aRSC, const IndexTable& aIndex)
{
IndexTableIterator next(aIndex);
unsigned char bitBuffer = 0;
int numberOfBitsInBuffer = 0;
for (;;)
{
IndexTableItem* const p = next();
if (p == NULL)
{
if (numberOfBitsInBuffer > 0)
{
aRSC.Write(&bitBuffer, 1);
}
break;
}
if (p->Resource().ContainsCompressedUnicode())
{
bitBuffer |= (1 << numberOfBitsInBuffer);
}
++numberOfBitsInBuffer;
if (numberOfBitsInBuffer == 8)
{
aRSC.Write(&bitBuffer, 1);
bitBuffer = 0;
numberOfBitsInBuffer = 0;
}
}
}
void WriteBinaryResourceData(RCBinaryStream& aRSC, IndexTable& aIndex, int& aSizeOfLargestResourceWhenUncompressed, const char* aDumpDirectory)
{
IndexTableIterator next(aIndex);
IndexTableItem * p;
int resourceIndex=1;
while( ( p = next() ) != NULL)
{
char* dumpFile=NULL;
if (aDumpDirectory!=NULL)
{
dumpFile=new char[strlen(aDumpDirectory)+20];
strcpy(dumpFile, aDumpDirectory);
char resourceIndexAsString[20];
sprintf(resourceIndexAsString, "%d", resourceIndex);
strcat(dumpFile, resourceIndexAsString);
}
p->SetOffset(aRSC.GetPosition()); // record start of this resource in the index
p->Resource().StreamOut(aRSC, aSizeOfLargestResourceWhenUncompressed, dumpFile); // write out binary form of resource
delete [] dumpFile;
++resourceIndex;
}
}
void WriteResourceFile(RCBinaryStream& aRSC, IndexTable& aIndex, bool aThirdUidIsOffset, const char* aDumpDirectory)
{
char flags=0;
if (aThirdUidIsOffset)
{
flags|=0x01;
}
aRSC << flags; // these flags are to be used only by a dictionary-compressing program rather than to be used directly by Bafl when reading non-dictionary-compressed resource files (as output by Rcomp)
const int positionToOverWriteFrom=aRSC.GetPosition();
NumericValue twoByteSizeOfLargestResourceWhenUncompressed(L_WORD);
aRSC << twoByteSizeOfLargestResourceWhenUncompressed;
WriteBitArrayOfResourcesContainingCompressedUnicode(aRSC, aIndex); // simply makes space for the bit-array without writing anything sensible in it (as we don't yet know which resources will contain compressed Unicode)
int sizeOfLargestResourceWhenUncompressed=0;
WriteBinaryResourceData(aRSC, aIndex, sizeOfLargestResourceWhenUncompressed, aDumpDirectory);
aIndex.SetIndexOffset(aRSC.GetPosition());
aRSC << aIndex;
aRSC.SetPosition(positionToOverWriteFrom);
twoByteSizeOfLargestResourceWhenUncompressed=sizeOfLargestResourceWhenUncompressed;
aRSC << twoByteSizeOfLargestResourceWhenUncompressed;
WriteBitArrayOfResourcesContainingCompressedUnicode(aRSC, aIndex); // overwrites the bit array with correct data
if(verbose)
{
MOFF; cout << aIndex; cout << endl; MON;
}
}
void CheckLabels() // checks whether the labels that are used in the input have been declared
{
QualifiedStringArrayIterator nextLabel(pG->UsedIdentifiers);
QualifiedString * pLabel;
while ((pLabel = nextLabel() ) != NULL)
{
bool found = false; // gets set to true if the label in question is declared
StringArrayIterator nextDeclared(pG->AllIdentifiers);
String * pDeclared;
while ( ( (pDeclared = nextDeclared() ) != NULL) && ( ! found ))
{
StringLess stringCompare;
if( !stringCompare(*pDeclared,(*pLabel).GetEntry()) && !stringCompare((*pLabel).GetEntry(),*pDeclared) )
{ // this comparison returns true if the label is the same as the declared label
found = true;
}
}
if( ! found ) // if label hasn't been declared emit warning
{
Message * message = pG->Messages.GetEntry(LT_045);
String fileName = (*pLabel).GetFileName();
int lineNumber = (*pLabel).GetLineNumber();
if(message->GetActivated())
{
String comment = message->GetMessageOutput();
comment += (*pLabel).GetEntry();
ErrorHandler::OutputWholeLine(fileName, lineNumber, comment);
}
}
}
}
/* Tokenize expects a string in the following format:
* \d{3}(,\d{3})*
* i.e. comma-separated three digit numbers.
* The string should contain no whitespace.
*/
void Tokenize(String aString)
{
int length = aString.Length();
for(int end=3; end<=length; end+=4)
{
String messageNumber = aString.ExtractSubString(end-3,end-1);
if(messageNumber.IsDecNatural())
{
Message * message = pG->Messages.GetTextEntry(messageNumber);
if(message != NULL)
{
message->SetActivationStatus(false);
}
}
}
}
void OutputHelp()
{
cerr << "Resource compiler version " << version << " (Build " << build << ") (C) 1997-2009 Nokia Corporation." << endl;
cerr << "Usage: rcomp [-vpul] [-force] [-oRSCFile] [-{uid2,uid3}] [-hHeaderFile] [-sSourceFile] [-iBaseInputFileName]" << endl;
cerr << "\tv" << "\tverbose" << endl;
cerr << "\tp" << "\tParser debugging" << endl;
cerr << "\tl" << "\tCheck localisation comments" << endl;
cerr << "\tforce" << "\tEmit localisation warnings even if no localisation tags are present" << endl;
cerr << "\tadd-defaults" << "\tAmend input rss/rpp file to add missing default localisation options" << endl;
cerr << endl;
cerr << "\tu" << "\tGenerate Unicode resource binary" << endl;
cerr << endl;
cerr << "If no source file is specified, the source will be read from standard input." << endl;
cerr << "(-i is used to specify the file given to the preprocessor this " << endl;
cerr << " name is used in generating debug output.)" << endl;
}
GlobalData *pG;
GlobalLocalisationData *pGL;
String InputBaseName;
int main(int argc, char * argv[])
{
cout << "\n";
int vParam=0;
bool lParam = false; // used as flag to specify whether checking of localisation comment tags should be performed
bool lForce = false; // used as flag to force localisation output even if there are no localisation comments
bool lAddDefaults = false; // used as flag to add missing default localisation data to input rss/rpp file, this is not the default behaviour
logmemorysetting = 0;
unsigned short pParam = 0;
String DataOutputFileName;
String HeaderOutputFileName;
String MessageSuppressionList;
String BasePath;
String SourceFileName;
FILE * pSourceFile;
char* uidsParameter=NULL;
char* dumpDirectory=NULL;
fpos_t filePositionIndicator;
int i;
char *fullcommand = argv[0];
std::string s(fullcommand);
if(argc<=1)
{
OutputHelp();
exit(-1);
}
else
{
// Look through arguments for ones beginning with '-?'.
for(i = 1; i < argc; i++)
{
if(* argv[i] == '-')
{
char * settings = argv[i] + 1;
if(strchr(settings, '?') )
{
OutputHelp();
exit(-1);
}
}
}
for(i = 1; i < argc; i++)
{
if(* argv[i] == '-')
{
char * settings = argv[i] + 1;
if(* settings == 'o' || * settings == 'O')
{
DataOutputFileName = (settings + 1);
continue;
}
if(* settings == 'm' || * settings == 'M')
{
MessageSuppressionList = (settings + 1);
continue;
}
if(* settings == 'h' || * settings == 'H')
{
HeaderOutputFileName = (settings + 1);
continue;
}
if(* settings == 'i' || * settings == 'I')
{
InputBaseName = (settings + 1);
String DriveAndDirectory = FileAccess::GetDriveAndDirectory(InputBaseName);
BasePath = FileAccess::FullPath(DriveAndDirectory);
continue;
}
if(* settings == 's' || * settings == 'S')
{
SourceFileName = (settings + 1);
continue;
}
if(* settings == '{')
{
uidsParameter = settings + 1;
char* temp = strchr(uidsParameter, ',');
if ((temp == NULL) || (temp == uidsParameter) || (strchr(temp + 1, ',') != NULL)) // check that there is *one* comma in this parameter (no more and no less), and that it is not the first thing immediately after the '{'
{
OutputHelp();
exit(-1);
}
*temp = ' ';
temp = strchr(uidsParameter, '}');
if ((temp == NULL) || (temp[1] != '\0'))
{
OutputHelp();
exit(-1);
}
*temp = ' ';
continue;
}
if(* settings == ':')
{
dumpDirectory=settings+1;
continue;
}
if(strchr(settings, 'u') || strchr(settings, 'U') )
{
SourceCharacterSet = String::CP1252;
TargetCharacterSet = String::Unicode;
}
if(strchr(settings, 'v') || strchr(settings, 'V') )
vParam = 1;
if(strchr(settings, 'p') || strchr(settings, 'P') )
pParam = 1;
if(strchr(settings, 'l') || strchr(settings, 'L') )
lParam = true;
if(strchr(settings, 'f') || strchr(settings, 'F') )
lForce = true;
if(strchr(settings, 'a') || strchr(settings, 'A') )
lAddDefaults = true;
}
}
}
if(SourceFileName.Length() == 0)
{
pSourceFile = stdin;
}
else
{
if((pSourceFile = fopen(SourceFileName.GetAssertedNonEmptyBuffer(), "r") ) == NULL)
{
cerr << "Failed to open " << SourceFileName << endl;
exit(-2);
}
}
//Searchig for BOM signature which if found will be ignored
unsigned char buffer[3];
fread( buffer, sizeof( char ), 3, pSourceFile);
if((buffer[0]!=239) && (buffer[1]!=187) && (buffer[2]!=191))
{
// BOM not found. Set the file-position indicator to 0
filePositionIndicator = fpos_t();
if(fsetpos(pSourceFile, &filePositionIndicator) !=0)
{
perror("fsetpos error");
}
}
verbose = vParam;
pG = new GlobalData;
if (pG==NULL)
exit(-4);
Tokenize(MessageSuppressionList);
pGL = new GlobalLocalisationData;
if(pG==NULL)
exit(-4);
pG->WarningMultiExplained = false;
pG->FileLineHandler.SetPath(BasePath);
#ifdef __TOOLS2__
pG->FileLineHandler.SetBase(SourceFileName,0);
#endif
int ret=ParseSourceFile(pSourceFile, pParam);
fclose(pSourceFile);
pGL->StoreFinalComment(); // final comment not stored during running of lex and yacc
if(lParam && (pGL->LocalisationCommentsExist() || lForce))
{
pGL->AnalyseLocalisationData();
pGL->PrintLocalisationWarnings();
if(lAddDefaults)
{
// only add deafult localisation values to rpp/rss file if the option has been set on the command line
if(verbose)
{
cout << "* Reparsing source file and adding any missing default localisation comments" << endl;
}
pGL->OutputLocalisedFile(SourceFileName);
}
}
if (ret != 0)
{
cerr << "RCOMP failed with code " << ret << endl;
exit(ret);
}
// A successful parse, now generate the output files
CheckLabels(); // check that all labels are declared and emit suitable warnings if not
if(DataOutputFileName.Length() != 0)
{
#ifdef __LINUX__
std::string totalpath(s.substr( 0, s.rfind("/")+1 ));
const char* uidTool = "uidcrc";
#else
std::string totalpath(s.substr( 0, s.rfind("\\")+1 ));
const char* uidTool = "uidcrc.exe";
#endif
// Calls the uidcrc tool with the full path to where RCOMP resides in
std::string uidpath(uidTool);
totalpath += uidpath;
// Find and replace all occurences of \ with /
std::string searchString( "\\" );
std::string replaceString( "/" );
std::string::size_type pos = 0;
while ( (pos = totalpath.find("\\", pos)) != std::string::npos ) {
totalpath.replace( pos, searchString.size(), replaceString );
pos++;
}
const char *uidcrcTool = totalpath.c_str();
bool thirdUidIsOffset=true;
char uidcrcUIDs[3][100];
strcpy (uidcrcUIDs[0], "0x101f4a6b");
if (uidsParameter)
{
// Command line argument takes precedence
strcpy (uidcrcUIDs[1], strtok (uidsParameter, " "));
strcpy (uidcrcUIDs[2], strtok (NULL, " "));
char* const temp = strchr(uidcrcUIDs[2], '*');
if (temp == NULL)
{
thirdUidIsOffset=false;
}
}
else
{
// otherwise use values supplied in source
extern unsigned long Uid2;
extern unsigned long Uid3;
sprintf(uidcrcUIDs[1], "0x%08lx", Uid2);
if (Uid3 != 0)
{
sprintf(uidcrcUIDs[2], "0x%08lx", Uid3);
thirdUidIsOffset=false;
}
}
if (thirdUidIsOffset)
{
const unsigned int idOfAnyResource = CurrentId; // *must* be unsigned so that when we right-shift it, the top bit doesn't get propagated if its set (i.e. "negative")
sprintf(uidcrcUIDs[2], "0x%08x", idOfAnyResource >> 12); // use the 20 bits derived from the resource file's NAME as the 3rd UID
}
if (verbose)
{
MOFF; cout << uidcrcTool << " " << uidcrcUIDs[0] << " " << uidcrcUIDs[1] << " " << uidcrcUIDs[2] << " " << DataOutputFileName.GetAssertedNonEmptyBuffer(); cout << endl; MON;
}
#ifndef __LINUX__
const int error = _spawnlp (_P_WAIT,
uidcrcTool,
uidcrcTool,
uidcrcUIDs[0],
uidcrcUIDs[1],
uidcrcUIDs[2],
DataOutputFileName.GetAssertedNonEmptyBuffer(),
NULL);
#else
char uidcrc_params[256];
const int ret = snprintf(uidcrc_params,
sizeof(uidcrc_params),
"%s %s %s %s %s",
uidcrcTool,
uidcrcUIDs[0],
uidcrcUIDs[1],
uidcrcUIDs[2],
DataOutputFileName.GetBuffer());
if(ret <= 0) {
cerr << "Failed to write UIDs to " << DataOutputFileName << endl;
exit(ret);
}
const int error = system(uidcrc_params);
#endif //__LINUX__
if(error != 0)
{
cerr << "Failed to write UIDs to " << DataOutputFileName << endl;
exit(error);
}
RCBinaryStream RSCStream;
RSCStream.OpenForAppend(DataOutputFileName);
if(! RSCStream.IsOpen())
{
cerr << "Failed to open " << DataOutputFileName << endl;
exit(-2);
}
WriteResourceFile(RSCStream, pG->Index, thirdUidIsOffset, dumpDirectory);
}
if(HeaderOutputFileName.Length() != 0)
{
FILE* RSG;
RSG = fopen(HeaderOutputFileName.GetAssertedNonEmptyBuffer(), "w");
if(RSG==NULL)
{
cerr << "Failed to open " << HeaderOutputFileName << endl;
exit(-2);
}
WriteHeaderFile(RSG, pG->Index);
fclose(RSG);
}
delete pG;
delete pGL;
return 0;
}