diff -r af1ed19cc0e4 -r 5a90ee674b42 toolsandutils/e32tools/elf2e32/source/deffile.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/toolsandutils/e32tools/elf2e32/source/deffile.cpp Tue Jul 06 16:25:46 2010 +0100 @@ -0,0 +1,1002 @@ +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// Implementation of the Class DefFile for the elf2e32 tool +// @internalComponent +// @released +// +// + +// +#include +#include +#include + +#include "pl_symbol.h" +#include "deffile.h" +#include "errorhandler.h" + +#ifdef __LINUX__ + #include "h_utl.h" + #define STRUPR strupr +#else + #define STRUPR _strupr +#endif + +using std::cerr; +using std::cout; +using std::endl; + +#define SUCCESS 1 +#define FAILURE 0 + +/** +Destructor to release all the allocated memory +@internalComponent +@released +*/ +DefFile::~DefFile() +{ + if(iSymbolList && iSymbolList->size()) + { + SymbolList::iterator aItr = iSymbolList->begin(); + SymbolList::iterator last = iSymbolList->end(); + Symbol *temp; + + while(aItr != last) + { + temp = *aItr; + aItr++; + delete temp; + } + iSymbolList->clear(); + } + delete iSymbolList; +} +/** +Function to Get File Size. +@param fptrDef - File pointer to DEF file +@internalComponent +@released +*/ +int DefFile::GetFileSize(FILE *fptrDef) +{ + int fileSize,status; + + status=fseek(fptrDef, 0, SEEK_END); + if(status!=0) + { + throw FileError(FILEREADERROR,iFileName); + } + fileSize=ftell(fptrDef); + rewind(fptrDef); + + return fileSize; + +} + +/** +Function to Open File and read it in memory. +@param defFile - DEF File name +@internalComponent +@released +*/ +char* DefFile::OpenDefFile(char * defFile) +{ + int fileSize; + char *defFileEntries; + FILE *fptrDef; + + iFileName=defFile; + if((fptrDef=fopen(defFile,"rb"))==NULL) + { + throw FileError(FILEOPENERROR,defFile); + } + + fileSize=GetFileSize(fptrDef); + + if((defFileEntries= new char[fileSize+2]) ==NULL) + { + throw MemoryAllocationError(MEMORYALLOCATIONERROR,defFile); + } + + //Getting whole file in memory + if(!fread(defFileEntries, fileSize, 1, fptrDef)) + { + throw FileError(FILEREADERROR,defFile); + } + + //Adding ENTER at end + *(defFileEntries+fileSize)='\n'; + //Adding '\0' at end + *(defFileEntries+fileSize+1)='\0'; + + fclose(fptrDef); + + return defFileEntries; + +} + +/** +Function to Parse Def File which has been read in buffer. +@param defFileEntries - pointer to def file entries which has been read in buffer +@internalComponent +@released +*/ +void DefFile::ParseDefFile(char *defFileEntries) +{ + iSymbolList = new SymbolList; + + int ordinalNo = 0; + int symbolType=SymbolTypeCode; + int PreviousOrdinal=0; + char MultiLineStatement[1024]=""; + bool NAMEorLIBRARYallowed=true; + int LineNum = 0; + bool isComment; + + char *lineToken; + int aLineLength = 0, width = 0; + unsigned i; + char *ptrEntry,*ptrEntryType; + char entryType[256]; + bool entryFlag; + + + lineToken=strtok(defFileEntries,"\n"); + while(lineToken != NULL) + { + symbolType=SymbolTypeCode; + isComment=false; + entryType[0]='\0'; + aLineLength = strlen(lineToken); + LineNum++; + + if (lineToken == NULL || lineToken[0]==13) + { + lineToken=strtok(NULL,"\n"); + continue; + } + + // comment lines + if (lineToken[0] == ';') + { + lineToken=strtok(NULL,"\n"); + continue; + } + + ptrEntry=lineToken; + + if((!strstr(lineToken, "NONAME") && ((ptrEntryType=strstr(lineToken, "NAME")) != NULL)) || + ((ptrEntryType=strstr(lineToken, "EXPORTS")) != NULL) || + ((ptrEntryType=strstr(lineToken, "IMPORTS")) != NULL) || + ((ptrEntryType=strstr(lineToken, "SECTIONS")) != NULL) || + ((ptrEntryType=strstr(lineToken, "LIBRARY")) != NULL) || + ((ptrEntryType=strstr(lineToken, "DESCRIPTION")) != NULL)|| + ((ptrEntryType=strstr(lineToken, "STACKSIZE")) != NULL)|| + ((ptrEntryType=strstr(lineToken, "VERSION")) != NULL) + ) + { + entryFlag=true; + + for(i=0; ptrEntry!=ptrEntryType; i++,ptrEntry++) + { + switch(lineToken[i]) + { + case ' ': + case '\t': + continue; + default: + entryFlag=false; + break; + } + if(entryFlag==false) + break; + } + + if(entryFlag==false && !strcmp(MultiLineStatement,"")) + { + throw DEFFileError(UNRECOGNIZEDTOKEN,iFileName,LineNum,lineToken); + } + + if(entryFlag==true) + { + switch(ptrEntryType[0]) + { + case 'E': + case 'I': + case 'L': + case 'V': + width=7; + break; + case 'S': + if(ptrEntryType[1]=='E') + width=8; + else + width=9; + break; + case 'N': + width=4; + break; + case 'D': + width=11; + break; + } + } + + if(entryFlag==true) + { + for(i=i+width; ipush_back(newSymbolEntry); + + ordinalNo = aSymbol.OrdNum(); + //Check for ordinal sequence + if (ordinalNo != PreviousOrdinal+1) + { + throw DEFFileError(ORDINALSEQUENCEERROR,iFileName,LineNum,(char*)aSymbol.SymbolName()); + } + + PreviousOrdinal = ordinalNo; + + } + lineToken=strtok(NULL,"\n"); + continue; + } + else if(strcmp(MultiLineStatement,"")!=0)//For entry other than exports + lineToken = strtok(NULL, "\n" ); // Get the next line + + }//End of while +} + +/** +This Function calls LineToken's Tokenize function. +@param aTokens - Input string at the current line number +@param aLineNum - Current line number +@param aSymbol - Symbol to be populated while parsing the line. +Return value - It returns true if a valid def file entry is found. +@internalComponent +@released +*/ +bool DefFile::Tokenize(char* aTokens, int aLineNum, Symbol& aSymbol) +{ + /* + * Pattern to match is: + * START\s*(\S+)\s+@\s*(d+)\s*(NONAME)?\s*(R3UNUSED)?\s*(ABSENT)?\s*(;\s*(.*))END + */ + LineToken aLine(iFileName, aLineNum, aTokens, &aSymbol); + return aLine.Tokenize(); +} + + +char * DefFilePatterns[] = + { + "NONAME",//index 0 + "DATA", + "R3UNUSED", + "ABSENT" + }; + +#define DEF_NONAME 0 +#define DEF_DATA 1 +#define DEF_R3UNUSED 2 +#define DEF_ABSENT 3 + +/** +This constructor creates an instance of LineToken class. +@param aFileName - Def File Name. +@param aLineNum - Current line number +@param aLn - Input string at the current line number +@param aSym - Symbol to be populated while parsing the line. +@internalComponent +@released +*/ +LineToken::LineToken(char* aFileName, int aLineNum, char *aLn, Symbol* aSym) : \ + iLine(aLn) , iSymbol(aSym) , iOffset(0), iState(EInitState),iFileName(aFileName), iLineNum(aLineNum) +{ +} + +/** +This function tokenizes the line and populates a symbol entry +if there is one. +Return Value - True, if the current line has a valid def entry. +@internalComponent +@released +*/ +bool LineToken::Tokenize() +{ + while (1) + { + switch( iState ) + { + case EFinalState: + return true; + case EInitState: + if( *(iLine + iOffset) == '\0' || + *(iLine + iOffset) == '\r' || + *(iLine + iOffset) == '\n') + { + /* + * Skip empty lines. + */ + return false; + } + else + { + NextToken(); + } + break; + default: + NextToken(); + break; + } + } + return false; +} + +/** +This function parses a line of the def file based on the current +state it is in. +@internalComponent +@released +*/ +void LineToken::NextToken() +{ + int aCurrentPos = 0; + char *aSymbolName; + + switch( iState ) + { + case EInitState: + if(IsWhiteSpace((iLine + iOffset), aCurrentPos)) + { + IncrOffset(aCurrentPos); + } + + if(IsWord(iLine + iOffset, aCurrentPos)) + { + SetState(ESymbolName); + } + break; + + case ESymbolName: + { + // Get the length of the symbol + IsWord(iLine + iOffset, aCurrentPos); + + char *cmt = strchr(iLine + iOffset, ';'); + char *aAlias = strchr(iLine + iOffset, '='); + + if( aAlias && (!cmt || (aAlias < cmt)) ) + { + int aAliasPos = aAlias - (iLine+ iOffset); + + //Check if alias name is also supplied, they should be separated + // by whitespace, i.e., SymbolName=AliasName is valid while, + // SymbolName =AliasName is invalid. + if( aAliasPos > aCurrentPos) + { + char *aToken = (iLine + iOffset + aCurrentPos); + throw DEFFileError(UNRECOGNIZEDTOKEN, iFileName, iLineNum, aToken); + } + + aSymbolName = new char[aAliasPos+1]; + strncpy(aSymbolName, iLine + iOffset, aAliasPos); + aSymbolName[aAliasPos] = '\0'; + char *aExportName = new char[aCurrentPos - aAliasPos + 1]; + strncpy(aExportName, aAlias +1, (aCurrentPos - aAliasPos)); + aExportName[(aCurrentPos - aAliasPos)] = '\0'; + iSymbol->ExportName(aExportName); + } + else + { + aSymbolName = new char[aCurrentPos+1]; + strncpy(aSymbolName, iLine+ iOffset, aCurrentPos); + aSymbolName[aCurrentPos] = '\0'; + } + iSymbol->SymbolName(aSymbolName); + + IncrOffset(aCurrentPos); + + if(IsWhiteSpace((iLine + iOffset), aCurrentPos)) + { + IncrOffset(aCurrentPos); + } + + if(*(iLine+iOffset) == '@') + { + SetState(EAtSymbol); + IncrOffset(1); + } + else + { + /* + * The first non-whitespace entry in a line is assumed to be the + * symbol name and a symbol name might also have a '@' char. Hence + * there MUST be a whitespace between symbol name and '@'. + */ + throw DEFFileError(ATRATEMISSING,iFileName,iLineNum,(iLine+iOffset)); + } + } + break; + + case EAtSymbol: + if(IsWhiteSpace((iLine + iOffset), aCurrentPos)) + { + IncrOffset(aCurrentPos); + } + + SetState(EOrdinal); + break; + case EOrdinal: + { + if(!IsDigit(iLine+iOffset, aCurrentPos ) ) + { + throw DEFFileError(ORDINALNOTANUMBER, iFileName, iLineNum, (iLine+iOffset)); + } + char aTmp[32]; + strncpy(aTmp, iLine+iOffset, aCurrentPos); + aTmp[aCurrentPos] = '\0'; + int aOrdinal = atoi(aTmp); + iSymbol->SetOrdinal(aOrdinal); + + IncrOffset(aCurrentPos); + + if(IsWhiteSpace((iLine + iOffset), aCurrentPos)) + { + IncrOffset(aCurrentPos); + } + SetState(EOptionals); + } + break; + + case EOptionals: + { + int aPrevPatternIndex, aPatternIdx = 0; + aPrevPatternIndex = -1; + while (*(iLine + iOffset) != '\n' || *(iLine + iOffset) != '\r') + { + if(IsPattern(iLine+iOffset, aCurrentPos, aPatternIdx) ) + { + switch(aPatternIdx) + { + case DEF_NONAME: + break; + case DEF_DATA: + iSymbol->CodeDataType(SymbolTypeData); + + IncrOffset(aCurrentPos); + if(IsWhiteSpace((iLine + iOffset), aCurrentPos)) + { + IncrOffset(aCurrentPos); + } + if(IsDigit(iLine+iOffset, aCurrentPos ) ) + { + char aSymSz[16]; + strncpy(aSymSz, (iLine + iOffset), aCurrentPos); + aSymSz[aCurrentPos] = '\0'; + iSymbol->SetSymbolSize(atoi(aSymSz)); + } + break; + case DEF_R3UNUSED: + iSymbol->R3Unused(true); + break; + case DEF_ABSENT: + iSymbol->SetAbsent(true); + break; + default: + break; + } + + /* + * NONAME , DATA, R3UNUSED and ABSENT, all the 3 are optional. But, if more than + * one of them appear, they MUST appear in that order. + * Else, it is not accepted. + */ + if( aPrevPatternIndex >= aPatternIdx) + { + throw DEFFileError(UNRECOGNIZEDTOKEN, iFileName, iLineNum,(iLine + iOffset)); + } + aPrevPatternIndex = aPatternIdx; + + IncrOffset(aCurrentPos); + + if(IsWhiteSpace((iLine + iOffset), aCurrentPos)) + { + IncrOffset(aCurrentPos); + } + } + else + { + if( *(iLine + iOffset) == ';' ) + { + SetState(EComment); + IncrOffset(1); + return; + } + else if( *(iLine + iOffset) == '\0' || + *(iLine + iOffset) == '\r' || + *(iLine + iOffset) == '\n') + { + SetState(EFinalState); + return; + } + else + { + throw DEFFileError(UNRECOGNIZEDTOKEN, iFileName, iLineNum,(iLine + iOffset)); + } + } + } + } + break; + + case EComment: + { + if(IsWhiteSpace(iLine + iOffset, aCurrentPos)) + { + IncrOffset(aCurrentPos); + } + + + int aLen = strlen(iLine + iOffset); + if( *(iLine + iOffset + aLen - 1 ) == '\n' || *(iLine + iOffset + aLen - 1 ) == '\r') + aLen -=1; + + char * aComment = new char[ aLen + 1]; + strncpy( aComment, iLine + iOffset, aLen); + aComment[aLen] = '\0'; + + IncrOffset(aLen); + + iSymbol->Comment(aComment); + SetState(EFinalState); + } + break; + + case EFinalState: + return; + default: + break; + } +} + +/** +This function returns true if the string starts with one +of the fixed patterns. +It also updates the length and index of this pattern. +@param aChar - Line Token +@param aTill - Length of the pattern +@param aTill - Index of the pattern +Return Value - True, if the string starts with one of the patterns. +@internalComponent +@released +*/ +bool LineToken::IsPattern(char* aStr, int& aTill, int& aIndex) +{ + int pos = 0; + int aLength; + int size = sizeof(DefFilePatterns)/sizeof(char*); + while(size > pos) + { + aLength = strlen(DefFilePatterns[pos]); + if(!strncmp(aStr, DefFilePatterns[pos], aLength)) + { + aTill = aLength; + aIndex = pos; + return true; + } + pos++; + } + return false; +} + +/** +This function returns true if the string starts with digits. +It also updates the length of this digit string. +@param aChar - Line Token +@param aTill - Length of the digit string +Return Value - True, if the string starts with digit(s) +@internalComponent +@released +*/ +bool LineToken::IsDigit(char *aChar, int &aTill) +{ + int pos = 0; + if( aChar[pos] - '0' >= 0 && aChar[pos] - '0' <= 9) + { + pos++; + while(aChar[pos] - '0' >= 0 && aChar[pos] - '0' <= 9) + { + pos++; + } + aTill = pos; + return true; + } + else + { + return false; + } +} + +/** +This function returns true if the string starts with white space. +It also updates the length of this white string! +@param aStr - Line Token +@param aTill - Length of the white string +Return Value - True, if the string starts with whitespace +@internalComponent +@released +*/ +bool LineToken::IsWhiteSpace(char *aStr, int &aTill) +{ + int pos = 0; + switch( aStr[pos] ) + { + case ' ': + case '\t': + break; + default: + return false; + } + + pos++; + while( aStr[pos]) + { + switch(aStr[pos]) + { + case ' ': + case '\t': + pos++; + break; + default: + aTill = pos; + return true; + } + + } + aTill = pos; + return true; +} + +/** +This function returns true if the string starts with non-whitespace. +It also updates the length of this word. +@param aStr - Line Token +@param aTill - Length of the word +Return Value - True, if the string starts with non-whitespace chars. +It also updates the length of the word. +@internalComponent +@released +*/ +bool LineToken::IsWord(char *aStr, int &aTill) +{ + int pos = 0; + switch( aStr[pos] ) + { + case '\0': + case ' ': + case '\t': + case '\r': + case '\n': + return false; + default: + break; + } + + pos++; + while( aStr[pos]) + { + switch(aStr[pos]) + { + case ' ': + case '\t': + case '\r': + case '\n': + aTill = pos; + return true; + default: + pos++; + break; + } + + } + aTill = pos; + return true; +} + +/** +This function increments the current offset. +@param aOff - increment by this value +@internalComponent +@released +*/ +void LineToken::IncrOffset(int aOff) +{ + iOffset += aOff; +} + +/** +This function sets the state of the tokenizer that is parsing +the line. +@param aState - next state +@internalComponent +@released +*/ +void LineToken::SetState(DefStates aState) +{ + iState = aState; +} + +/** +Function to Read def file and get the internal representation in structure. +@param defFile - DEF File name +@internalComponent +@released +*/ +SymbolList* DefFile::ReadDefFile(char *defFile) +{ + char *defFileEntries; + + defFileEntries=OpenDefFile(defFile); + ParseDefFile(defFileEntries); + + delete [] defFileEntries;//Free the memory which was required to read def file + + return iSymbolList; + +} + +/** +Function to get the internal representation of Def File. +@param defFile - DEF File name +@internalComponent +@released +*/ +SymbolList* DefFile::GetSymbolEntryList(char *defFile) +{ + if(iSymbolList) + { + return iSymbolList; + } + else + { + iSymbolList=ReadDefFile(defFile); + return iSymbolList; + } + +} + +/** +Function to write DEF file from symbol entry List. +@param fileName - Def file name +@param newSymbolList - pointer to SymbolList which we get as an input for writing in DEF File +@internalComponent +@released +*/ +void DefFile::WriteDefFile(char *fileName, SymbolList * newSymbolList) +{ + + char ordinal[6]; + int newDefEntry=0; + FILE *fptr; + + if((fptr=fopen(fileName,"wb"))==NULL) + { + throw FileError(FILEOPENERROR,fileName); + } + else + { + SymbolList::iterator aItr = newSymbolList->begin(); + SymbolList::iterator last = newSymbolList->end(); + Symbol *aSym; + + fputs("EXPORTS",fptr); + fputs("\r\n",fptr); + while( aItr != last) + { + aSym = *aItr; + //Do not write now if its a new entry + if(aSym->GetSymbolStatus()==New) + { + newDefEntry=1; + aItr++; + continue; + } + + //Make it comment if its missing def entry + if(aSym->GetSymbolStatus()==Missing) + fputs("; MISSING:",fptr); + + fputs("\t",fptr); + if((aSym->ExportName()) && strcmp(aSym->SymbolName(),aSym->ExportName())!=0) + { + fputs(aSym->ExportName(),fptr); + fputs("=",fptr); + } + fputs(aSym->SymbolName(),fptr); + fputs(" @ ",fptr); + sprintf(ordinal,"%d",aSym->OrdNum()); + fputs(ordinal,fptr); + fputs(" NONAME",fptr); + if(aSym->CodeDataType()==SymbolTypeData) { + fputs(" DATA",fptr); + fputs(" ",fptr); + char aSymSize[16]; + sprintf(aSymSize, "%d", aSym->SymbolSize()); + fputs(aSymSize,fptr); + } + if(aSym->R3unused()) + fputs(" R3UNUSED",fptr); + if(aSym->Absent()) + fputs(" ABSENT",fptr); + + if(aSym->Comment()!=NULL) + { + fputs(" ; ",fptr); + fputs(aSym->Comment(),fptr); + } + fputs("\r\n",fptr); + aItr++; + } + + //This is for writing new def entry in DEF File + if(newDefEntry) + { + fputs("; NEW:",fptr); + fputs("\r\n",fptr); + aItr = newSymbolList->begin(); + last = newSymbolList->end(); + + while( aItr != last) + { + aSym = *aItr; + if(aSym->GetSymbolStatus()!=New) + { + aItr++; + continue; + } + fputs("\t",fptr); + if((aSym->ExportName()) && strcmp(aSym->SymbolName(),aSym->ExportName())!=0) + { + fputs(aSym->ExportName(),fptr); + fputs("=",fptr); + } + fputs(aSym->SymbolName(),fptr); + fputs(" @ ",fptr); + sprintf(ordinal,"%d",aSym->OrdNum()); + fputs(ordinal,fptr); + fputs(" NONAME",fptr); + + if(aSym->CodeDataType()==SymbolTypeData) { + fputs(" DATA",fptr); + fputs(" ",fptr); + char aSymSize[16]; + sprintf(aSymSize, "%d", aSym->SymbolSize()); + fputs(aSymSize,fptr); + } + + if(aSym->R3unused()) + fputs(" R3UNUSED",fptr); + if(aSym->Absent()) + fputs(" ABSENT",fptr); + + if(aSym->Comment()!=NULL) + { + if(aSym->CodeDataType()!=SymbolTypeCode && + aSym->CodeDataType()!=SymbolTypeData) + { + fputs(" ; ",fptr); + fputs(aSym->Comment(),fptr); + } + else + { + fputs(" ",fptr); + fputs(aSym->Comment(),fptr); + } + } + fputs("\r\n",fptr); + aItr++; + } + } + fputs("\r\n",fptr); + fclose(fptr); + } +}