--- a/bintools/rcomp/src/main.cpp Fri Aug 13 14:59:05 2010 +0300
+++ b/bintools/rcomp/src/main.cpp Wed Aug 18 17:23:33 2010 +0300
@@ -1,568 +1,633 @@
-/*
-* 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;
- }
-
-
-
-
+/*
+* Copyright (c) 2000-2010 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>
+#include <fstream>
+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-2010 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 = NULL ; //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");
+ exit(-2);
+ }
+ }
+ }
+
+ verbose = vParam;
+ pG = new GlobalData;
+ if (pG==NULL)
+ exit(-4);
+
+ if(NULL == pSourceFile){ // Cache the standard input
+ pG->StdInBufLength = 0;
+ unsigned long allocSize = 0x100000 ; // 1M bytes
+ pG->StdInfBufPos = 0 ;
+ pG->StdInBuffer = (char*)malloc(allocSize);
+ if(NULL == pG->StdInBuffer){
+ delete pG ;
+ exit(-4);
+ }
+ int result = 1;
+ char* buffer = pG->StdInBuffer;
+ FILE *file = stdin ;
+ const int KIOBytes = 0x20000 ;
+ while(1) {
+ result = fread(buffer, 1, KIOBytes, file);
+ if(result == 0){
+ *buffer = 0;
+ break ;
+ }
+ buffer += result ;
+ pG->StdInBufLength += result ;
+ if((pG->StdInBufLength + KIOBytes) > allocSize) {
+ allocSize += KIOBytes ;
+ pG->StdInBuffer = (char*)realloc(pG->StdInBuffer,allocSize);
+ if(NULL == pG->StdInBuffer){
+ delete pG ;
+ exit(-4);
+ }
+ buffer = pG->StdInBuffer + pG->StdInBufLength;
+ }
+
+ }
+ const unsigned char BOM[] = {0xef , 0xbb, 0xbf, 0x0 };
+ if(0 == memcmp(pG->StdInBuffer,BOM,3))
+ pG->StdInfBufPos = 3 ;
+ }
+ else {
+ pG->StdInBuffer = 0 ;
+ pG->StdInBufLength = 0;
+ }
+
+ 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);
+ if(pSourceFile != NULL)
+ fclose(pSourceFile);
+ if(pG->StdInBuffer != NULL)
+ free(pG->StdInBuffer);
+
+ 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";
+
+ // in case unix style of seperator is used in windows.
+ if(!totalpath.length()){
+ totalpath = s.substr( 0, s.rfind("/")+1 );
+ }
+
+#endif
+
+ std::string uidpath(uidTool);
+
+ // try to call the uidcrc tool with the full path to where RCOMP resides in
+ // if does not exists, search uidcrc in PATH
+ if(totalpath.length()){
+
+ std::string trypath(totalpath);
+ trypath += uidpath;
+
+ std::fstream _file;
+ _file.open(trypath.c_str(), std::ios::in);
+ if(!_file){
+ // try to search from PATH
+ totalpath = uidpath;
+ }
+ else{
+ _file.close();
+ // invoke from the path RCOMP resides in
+ totalpath += uidpath;
+ }
+ }
+ else{
+ // search from PATH
+ 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;
+ }
+
+ int namelen = strlen(uidcrcTool) + strlen(uidcrcUIDs[0]) * 3 + DataOutputFileName.Length() + 10;
+ char *uidcrc_params = new char[namelen];
+ const int ret = snprintf(uidcrc_params,
+ namelen,
+ "%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);
+
+ if(error != 0)
+ {
+ cerr << "Failed to write UIDs to " << DataOutputFileName << endl;
+ exit(error);
+ }
+ delete[] uidcrc_params;
+
+ 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;
+ }
+
+
+
+