--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bintools/rcomp/src/main.cpp Tue Oct 27 16:36:35 2009 +0000
@@ -0,0 +1,568 @@
+/*
+* 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;
+ }
+
+
+
+