diff -r 7c4a911dc066 -r 541af5ee3ed9 bintools/rcomp/src/main.cpp --- 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 -#include -#include - -#include "unistd.h" - -#if defined( __MSVCDOTNET__) || defined(__TOOLS2__) -#include -using std::cout; -using std::endl; -using std::cerr; -#else //!__MSVCDOTNET__ -#ifndef __LINUX__ -#include -#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 +#include +#include + + +#include "unistd.h" + +#if defined( __MSVCDOTNET__) || defined(__TOOLS2__) +#include +#include +using std::cout; +using std::endl; +using std::cerr; +#else //!__MSVCDOTNET__ +#ifndef __LINUX__ +#include +#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; + } + + + +