diff -r 000000000000 -r 044383f39525 bintools/rcomp/src/main.cpp --- /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 +#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; + } + + + +