diff -r 000000000000 -r dfb7c4ff071f commsfwtools/commstools/utracedecoder/src/messagedefparser/definitionparser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commsfwtools/commstools/utracedecoder/src/messagedefparser/definitionparser.cpp Thu Dec 17 09:22:25 2009 +0200 @@ -0,0 +1,507 @@ +// Copyright (c) 2007-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: +// + + +#include +#include +#include +#include +#include + +#include "messagedefparser\statebase.h" +#include "messagedefparser\definitionparser.h" +#include "messagedefparser\constidentifier.h" +#include "messagedefparser\contextidentifier.h" +#include "messagedefparser\enumidentifier.h" +#include "messagedefparser\integeridentifier.h" +#include "messagedefparser\messageidentifier.h" +#include "messagedefparser\padidentifier.h" +#include "messagedefparser\signatureidentifier.h" +#include "messagedefparser\structidentifier.h" +#include "messagedefparser\initialstate.h" +#include "messagedefparser\messageidtypeidentifier.h" +#include "util.h" +#include "version.h" + +namespace Parser +{ + +// aFilename must be an absolute filename +CDefinitionFile::CDefinitionFile(const std::string& aFilename) + { + iTokenizer = new Tokens::CDefinitionTokenizer(); + iFilename = aFilename; + size_t sep = iFilename.find_last_of("\\"); + + assert(sep != std::string::npos && iFilename[0] != '\\'); + iFilePath = iFilename.substr(0, sep); + } + +CDefinitionFile::~CDefinitionFile() + { + delete iTokenizer; + } + + + +CDefinitionParser::CDefinitionParser() + { + iTesting = false; + iAllIdentifiers.push_back(new CIntegerTypeIdentifier("UINT32", 4)); + iAllIdentifiers.push_back(new CIntegerTypeIdentifier("UINT16", 2)); + iAllIdentifiers.push_back(new CIntegerTypeIdentifier("UINT8", 1)); + iAllIdentifiers.push_back(new CIntegerTypeIdentifier("INT32", 4, true)); + iAllIdentifiers.push_back(new CIntegerTypeIdentifier("INT16", 2, true)); + iAllIdentifiers.push_back(new CIntegerTypeIdentifier("INT8", 1, true)); + iAllIdentifiers.push_back(new CPadTypeIdentifier("PAD")); + + // Complex built-in types + iAllIdentifiers.push_back(new CMessageIdTypeIdentifier(*this)); + } + +CDefinitionParser::~CDefinitionParser() + { + while (!iFileStack.empty()) + { + delete iFileStack.back(); + iFileStack.pop_back(); + } + } + + +bool CDefinitionParser::IncludeDefinitionFile(const char* aDefinitionFile) + { + std::string includeDefFile; + + if (aDefinitionFile[1] == ':') // consider it an absolute file path + { + includeDefFile = aDefinitionFile; + } + else if (iFileStack.empty()) + { + char* cwd = _getcwd(NULL, 0); + if (aDefinitionFile[0] == '\\') // consider it relative to the root of the current drive + { + includeDefFile = std::string(cwd).substr(0, 2); + } + else + { + includeDefFile = cwd; + includeDefFile += "\\"; + } + includeDefFile += aDefinitionFile; + free(cwd); + } + else + { + if (aDefinitionFile[0] == '\\') + { + // needs a drive + includeDefFile = CurrentFile().FilePath().substr(0, 2); + } + else + { + includeDefFile = CurrentFile().FilePath(); + } + includeDefFile += "\\"; + includeDefFile += aDefinitionFile; + } + + // TODO: get absolute filename for aDefinitionfile based on original def file + for (unsigned int i=0; iFilePath() + "\\" + iFileStack.at(i)->Filename(); + if (!_strcmpi(includedFile.c_str(), includeDefFile.c_str())) + { + std::cerr << "Error: Circular inclusion of " << includeDefFile << " from "; + std::cerr << CurrentFile().FilePath() << "\\" << CurrentFile().Filename() << " at line "; + std::cerr << CurrentFile().Tokenizer().Line() << std::endl; + iError = Parser::ECircularInclusion; + return false; + } + } + + bool loadSuccess; + CDefinitionFile* defFile = new CDefinitionFile(includeDefFile); + loadSuccess = (defFile->Tokenizer().LoadDefinitionFile(includeDefFile) == Tokens::ENoError); + if (!loadSuccess) + { + // if loading the first (the specified initial definition file) and it failed + // and the file isn't root relative or absolute try looking in the exe dir + if (iFileStack.empty() && aDefinitionFile[0] != '\\' && aDefinitionFile[1] != ':') + { + includeDefFile = ::__argv[0]; + size_t sep; + sep = includeDefFile.find_last_of('\\'); + if (sep != std::string::npos) + { + includeDefFile.erase(sep + 1); + includeDefFile += aDefinitionFile; + } + + delete defFile; + defFile = new CDefinitionFile(includeDefFile); + loadSuccess = (defFile->Tokenizer().LoadDefinitionFile(includeDefFile) == Tokens::ENoError); + } + + if (!loadSuccess) + { + delete defFile; + if (iFileStack.empty()) + { + std::cerr << "Error loading definition file: " << aDefinitionFile << std::endl; + } + else + { + std::cerr << "Error loading definition file: " << includeDefFile + << " included from " + << CurrentFile().FilePath() << "\\" << CurrentFile().Filename() + << " at line " + << CurrentFile().Tokenizer().Line() << std::endl; + } + + iError = EFileError; + return false; + } + } + + iFileStack.push_back(defFile); + return true; + } + + +void CDefinitionParser::CloseCurrentFile() + { + assert(!iFileStack.empty()); + CDefinitionFile* defFile = iFileStack.back(); + iFileStack.pop_back(); + delete defFile; + } + + +CDefinitionFile& CDefinitionParser::CurrentFile() + { + assert(!iFileStack.empty()); + return *(iFileStack.back()); + } + + +Parser::TResult CDefinitionParser::ParseDefinitionFile(const char* aDefinitionFile) + { + iError = ENoError; + if (!IncludeDefinitionFile(aDefinitionFile)) + { + return iError; + } + + SetState(new CInitialState(*this)); + + do + { + while (CurrentFile().Tokenizer().GetNextToken() == Tokens::ETokenFound) + { + State().ProcessState(); + + if (iError != Parser::ENoError && !iTesting) + { + return iError; + } + } + + if (State().StateId() != Parser::EStateInitial) + { + std::cerr << "Error: Unexpected end of file "; + std::cerr << CurrentFile().Filename() << " at line "; + std::cerr << CurrentFile().Tokenizer().Line() << std::endl; + if (!iTesting) + { + return Parser::EUnexpectedEndOfFile; + } + } + + // finished with current file + CloseCurrentFile(); + + } while (iFileStack.size() > 0); + + return iError; + } + + +void CDefinitionParser::DumpIdentifiers() const + { + unsigned int i; + std::cout << "utracedecoder " APPVERSION << std::endl; + std::cout << "Identifier List" << std::endl << "===============" << std::endl; + for (i=0; iType()) + { + case EConstIdentifier: + { + const CConstIdentifier* ident = static_cast(iAllIdentifiers.at(i)); + std::cout << "CONST " << ident->Name() << " = " << ident->iValue << std::endl; + } + break; + + case EEnumTypeIdentifier: + { + const CEnumTypeIdentifier* ident = static_cast(iAllIdentifiers.at(i)); + std::cout << "ENUM " << ident->Name() << "(size="; + std::cout << ident->Size(); + std::cout << ")" << std::endl; + unsigned int j; + for (j=0; jiEnumValues.size(); j++) + { + std::cout << " " << ident->iEnumValues.at(j)->Name() << " = " << ident->iEnumValues.at(j)->iValue << std::endl; + } + std::cout << std::endl; + } + break; + + case EStructIdentifier: + case EMessageIdTypeIdentifier: + { + const CStructIdentifier* ident = static_cast(iAllIdentifiers.at(i)); + std::cout << "STRUCT " << ident->Name() << "(size="; + std::cout << ident->TotalSize(); + std::cout << ")" << std::endl; + unsigned int j; + for (j=0; jiMembers.size(); j++) + { + std::cout << " " << ident->iMembers.at(j)->iOffset << ": "; + std::cout << " " << ident->iMembers.at(j)->iMemberType->Name() << " " + << ident->iMembers.at(j)->iMemberName + << " (" << ident->iMembers.at(j)->iArraySize * ident->iMembers.at(j)->iMemberType->TotalSize() + << ")" << std::endl; + } + std::cout << std::endl; + } + break; + + case ESignatureIdentifier: + { + if (iAllIdentifiers.at(i)->Flags() & KAliasIdentifier) + { + const CSignatureAliasIdentifier* ident = static_cast(iAllIdentifiers.at(i)); + std::cout << "ALIAS SIGNATURE " << ident->Name() + << " = " << ident->RealName() << std::endl; + } + else + { + const CSignatureIdentifier* ident = static_cast(iAllIdentifiers.at(i)); + std::cout << "SIGNATURE " << ident->Name() << "(size="; + std::cout << ident->TotalSize(); + std::cout << ")" << std::endl; + if (ident->BaseSignature()) + { + std::cout << " BASE SIGNATURE = " << ident->BaseSignature()->Name() + << " (size=" << ident->BaseSignature()->TotalSize() << ")" << std::endl; + } + std::cout << " STYPEID = (0x" << std::setw(8) << std::noshowbase + << std::nouppercase << std::hex << std::setfill('0') << ident->TypeId().iUid + << ", " << std::dec << ident->TypeId().iType << ")" << std::endl; + + unsigned int j; + for (j=0; jiMembers.size(); j++) + { + std::cout << " " << ident->iMembers.at(j)->iOffset << ": "; + std::cout << ident->iMembers.at(j)->iMemberType->Name() << " " + << ident->iMembers.at(j)->iMemberName + << " (size=" << ident->iMembers.at(j)->iArraySize * ident->iMembers.at(j)->iMemberType->TotalSize() + << ")" << std::endl; + } + } + std::cout << std::endl; + } + break; + + case EContextIdentifier: + { + if (iAllIdentifiers.at(i)->Flags() & KAliasIdentifier) + { + const CContextAliasIdentifier* ident = static_cast(iAllIdentifiers.at(i)); + std::cout << "ALIAS CONTEXT " << ident->Name() + << " = " << ident->RealName() << std::endl << std::endl; + } + else + { + const CContextIdentifier* ident = static_cast(iAllIdentifiers.at(i)); + std::cout << "CONTEXT " << ident->Name() << "(size="; + std::cout << ident->TotalSize(); + std::cout << ")" << std::endl; + if (ident->BaseContext()) + { + std::cout << " BASE CONTEXT = " << ident->BaseContext()->Name() + << " (size=" << ident->BaseContext()->TotalSize() << ")" << std::endl; + } + + unsigned int j; + for (j=0; jiMembers.size(); j++) + { + std::cout << " " << ident->iMembers.at(j)->iOffset << ": "; + std::cout << ident->iMembers.at(j)->iMemberType->Name() << " " + << ident->iMembers.at(j)->iMemberName + << " (size=" << ident->iMembers.at(j)->iArraySize * ident->iMembers.at(j)->iMemberType->TotalSize() + << ")" << std::endl; + } + } + std::cout << std::endl; + } + break; + + case EMessageIdentifier: + { + if (iAllIdentifiers.at(i)->Flags() & KAliasIdentifier) + { + const CMessageAliasIdentifier* ident = static_cast(iAllIdentifiers.at(i)); + std::cout << "ALIAS MESSAGE " << ident->Name() + << " = " << ident->RealName() << std::endl << std::endl; + } + else + { + const CMessageIdentifier* ident = static_cast(iAllIdentifiers.at(i)); + std::cout << "MESSAGE " << ident->Name() << std::endl; + if (ident->iSignature) + { + std::cout << " SIGNATURE = " << ident->iSignature->Name() << std::endl; + } + std::cout << " ID = (" << ident->iMessageId.iRealmId << ", " << ident->iMessageId.iMessageId << ")" << std::endl; + } + std::cout << std::endl; + } + break; + + default: + std::cout << iAllIdentifiers.at(i)->Name() << " (identifier type=" << iAllIdentifiers.at(i)->Type() << ")" << std::endl; + break; + } + } + } + +const CIdentifierBase* CDefinitionParser::FindIdentifier(const char* aIdentifierName) const + { + unsigned int i; + const CIdentifierBase* ident; + for (i=0; iName(), aIdentifierName)) + { + return ident; + } + } + return NULL; + } + + +void CDefinitionParser::AddIdentifier(const CIdentifierBase* aIdentifier) + { + if (FindIdentifier(aIdentifier->Name())) + { + std::cerr << "ERROR: **** Adding duplicate identifier : " << aIdentifier->Name() << " ****" << std::endl; + } + assert(!FindIdentifier(aIdentifier->Name())); + iAllIdentifiers.push_back(aIdentifier); + } + +const CContextIdentifier* CDefinitionParser::FindContextBySize(unsigned int aSize) const + { + unsigned int i; + const CContextIdentifier* context; + for (i=0; i(iAllIdentifiers.at(i)); + if (context->Type() == Parser::EContextIdentifier + && context->TotalSize() == aSize) + { + return context; + } + } + return NULL; + } + +const CSignatureIdentifier* CDefinitionParser::FindSignatureByTypeId(const STypeId& aTypeId) const + { + unsigned int i; + const CSignatureIdentifier* signature; + for (i=0; i(iAllIdentifiers.at(i)); + if (signature->Type() == Parser::ESignatureIdentifier + && signature->TypeId().iUid == aTypeId.iUid + && signature->TypeId().iType == aTypeId.iType) + { + return signature; + } + } + return NULL; + } + + +const CMessageIdentifier* CDefinitionParser::FindMessageByMessageId(const TMessageId& aMessageId) const + { + unsigned int i; + const CMessageIdentifier* message; + for (i=0; i(iAllIdentifiers.at(i)); + if (message->Type() == Parser::EMessageIdentifier + && message->iMessageId.iRealmId == aMessageId.iRealmId + && message->iMessageId.iMessageId == aMessageId.iMessageId) + { + return message; + } + } + return NULL; + } + +void CDefinitionParser::SetError(TResult aError) + { + iError = aError; + switch (iError) + { + case ENoError: + return; + //break; + + case EDuplicateIdentifier: + std::cerr << "Error: Duplicate identifier \"" << CurrentFile().Tokenizer().Token() << "\" in "; + break; + + case EValueOutOfRange: + std::cerr << "Error: Value out of range \"" << CurrentFile().Tokenizer().Token() << "\" in "; + break; + + case EUnexpectedToken: + std::cerr << "Error: Unexpected token \"" << CurrentFile().Tokenizer().Token() << "\" in "; + break; + + case EUnknownIdentifier: + std::cerr << "Error: Unknown identifier \"" << CurrentFile().Tokenizer().Token() << "\" in "; + break; + + default: + std::cerr << "Error: (" << iError << ") in "; + } + + std::cerr << CurrentFile().Filename() << " at line "; + std::cerr << CurrentFile().Tokenizer().Line() << std::endl; + } + +} // namespace Parser +