commsfwtools/commstools/utracedecoder/src/messagedefparser/definitionparser.cpp
changeset 0 dfb7c4ff071f
--- /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 <cassert>
+#include <string>
+#include <iostream>
+#include <iomanip>
+#include <direct.h>
+
+#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; i<iFileStack.size(); i++)
+        {
+        std::string includedFile = iFileStack.at(i)->FilePath() + "\\" + 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; i<iAllIdentifiers.size(); i++)
+        {
+        std::cout << std::endl;
+
+        switch (iAllIdentifiers.at(i)->Type())
+            {
+            case EConstIdentifier:
+                {
+                const CConstIdentifier* ident = static_cast<const CConstIdentifier*>(iAllIdentifiers.at(i));
+                std::cout << "CONST " << ident->Name() << " = " << ident->iValue << std::endl;
+                }
+                break;
+
+            case EEnumTypeIdentifier:
+                {
+                const CEnumTypeIdentifier* ident = static_cast<const CEnumTypeIdentifier*>(iAllIdentifiers.at(i));
+                std::cout << "ENUM " << ident->Name() << "(size=";
+                std::cout << ident->Size();
+                std::cout << ")" << std::endl;
+                unsigned int j;
+                for (j=0; j<ident->iEnumValues.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<const CStructIdentifier*>(iAllIdentifiers.at(i));
+                std::cout << "STRUCT " << ident->Name() << "(size=";
+                std::cout << ident->TotalSize();
+                std::cout << ")" << std::endl;
+                unsigned int j;
+                for (j=0; j<ident->iMembers.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<const CSignatureAliasIdentifier*>(iAllIdentifiers.at(i));
+                    std::cout << "ALIAS SIGNATURE " << ident->Name()
+                        << " = " << ident->RealName() << std::endl;
+                    }
+                else
+                    {
+                    const CSignatureIdentifier* ident = static_cast<const CSignatureIdentifier*>(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; j<ident->iMembers.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<const CContextAliasIdentifier*>(iAllIdentifiers.at(i));
+                    std::cout << "ALIAS CONTEXT " << ident->Name()
+                        << " = " << ident->RealName() << std::endl << std::endl;
+                    }
+                else
+                    {
+                    const CContextIdentifier* ident = static_cast<const CContextIdentifier*>(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; j<ident->iMembers.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<const CMessageAliasIdentifier*>(iAllIdentifiers.at(i));
+                    std::cout << "ALIAS MESSAGE " << ident->Name()
+                        << " = " << ident->RealName() << std::endl << std::endl;
+                    }
+                else
+                    {
+                    const CMessageIdentifier* ident = static_cast<const CMessageIdentifier*>(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; i<iAllIdentifiers.size(); i++)
+        {
+        ident = iAllIdentifiers.at(i);
+        if (!_strcmpi(ident->Name(), 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.size(); i++)
+        {
+        context = static_cast<const CContextIdentifier*>(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.size(); i++)
+        {
+        signature = static_cast<const CSignatureIdentifier*>(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.size(); i++)
+        {
+        message = static_cast<const CMessageIdentifier*>(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
+