commsfwtools/commstools/utracedecoder/src/messagedefparser/definitionparser.cpp
changeset 0 dfb7c4ff071f
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 
       
    17 #include <cassert>
       
    18 #include <string>
       
    19 #include <iostream>
       
    20 #include <iomanip>
       
    21 #include <direct.h>
       
    22 
       
    23 #include "messagedefparser\statebase.h"
       
    24 #include "messagedefparser\definitionparser.h"
       
    25 #include "messagedefparser\constidentifier.h"
       
    26 #include "messagedefparser\contextidentifier.h"
       
    27 #include "messagedefparser\enumidentifier.h"
       
    28 #include "messagedefparser\integeridentifier.h"
       
    29 #include "messagedefparser\messageidentifier.h"
       
    30 #include "messagedefparser\padidentifier.h"
       
    31 #include "messagedefparser\signatureidentifier.h"
       
    32 #include "messagedefparser\structidentifier.h"
       
    33 #include "messagedefparser\initialstate.h"
       
    34 #include "messagedefparser\messageidtypeidentifier.h"
       
    35 #include "util.h"
       
    36 #include "version.h"
       
    37 
       
    38 namespace Parser
       
    39 {
       
    40 
       
    41 // aFilename must be an absolute filename
       
    42 CDefinitionFile::CDefinitionFile(const std::string& aFilename)
       
    43     {
       
    44     iTokenizer = new Tokens::CDefinitionTokenizer();
       
    45     iFilename = aFilename;
       
    46     size_t sep = iFilename.find_last_of("\\");
       
    47 
       
    48     assert(sep != std::string::npos && iFilename[0] != '\\');
       
    49     iFilePath = iFilename.substr(0, sep);
       
    50     }
       
    51 
       
    52 CDefinitionFile::~CDefinitionFile()
       
    53     {
       
    54     delete iTokenizer;
       
    55     }
       
    56 
       
    57 
       
    58 
       
    59 CDefinitionParser::CDefinitionParser()
       
    60     {
       
    61     iTesting = false;
       
    62     iAllIdentifiers.push_back(new CIntegerTypeIdentifier("UINT32", 4));
       
    63     iAllIdentifiers.push_back(new CIntegerTypeIdentifier("UINT16", 2));
       
    64     iAllIdentifiers.push_back(new CIntegerTypeIdentifier("UINT8", 1));
       
    65     iAllIdentifiers.push_back(new CIntegerTypeIdentifier("INT32", 4, true));
       
    66     iAllIdentifiers.push_back(new CIntegerTypeIdentifier("INT16", 2, true));
       
    67     iAllIdentifiers.push_back(new CIntegerTypeIdentifier("INT8", 1, true));
       
    68     iAllIdentifiers.push_back(new CPadTypeIdentifier("PAD"));
       
    69 
       
    70     // Complex built-in types
       
    71     iAllIdentifiers.push_back(new CMessageIdTypeIdentifier(*this));
       
    72     }
       
    73 
       
    74 CDefinitionParser::~CDefinitionParser()
       
    75     {
       
    76     while (!iFileStack.empty())
       
    77         {
       
    78         delete iFileStack.back();
       
    79         iFileStack.pop_back();
       
    80         }
       
    81     }
       
    82 
       
    83 
       
    84 bool CDefinitionParser::IncludeDefinitionFile(const char* aDefinitionFile)
       
    85     {
       
    86     std::string includeDefFile;
       
    87 
       
    88     if (aDefinitionFile[1] == ':') // consider it an absolute file path
       
    89         {
       
    90         includeDefFile = aDefinitionFile;
       
    91         }
       
    92     else if (iFileStack.empty())
       
    93         {
       
    94         char* cwd = _getcwd(NULL, 0);
       
    95         if (aDefinitionFile[0] == '\\') // consider it relative to the root of the current drive
       
    96             {
       
    97             includeDefFile = std::string(cwd).substr(0, 2);
       
    98             }
       
    99         else
       
   100             {
       
   101             includeDefFile = cwd;
       
   102             includeDefFile += "\\";
       
   103             }
       
   104         includeDefFile += aDefinitionFile;
       
   105         free(cwd);
       
   106         }
       
   107     else
       
   108         {
       
   109         if (aDefinitionFile[0] == '\\')
       
   110             {
       
   111             // needs a drive
       
   112             includeDefFile = CurrentFile().FilePath().substr(0, 2);
       
   113             }
       
   114         else
       
   115             {
       
   116             includeDefFile = CurrentFile().FilePath();
       
   117             }
       
   118         includeDefFile += "\\";
       
   119         includeDefFile += aDefinitionFile;
       
   120         }
       
   121     
       
   122     // TODO: get absolute filename for aDefinitionfile based on original def file
       
   123     for (unsigned int i=0; i<iFileStack.size(); i++)
       
   124         {
       
   125         std::string includedFile = iFileStack.at(i)->FilePath() + "\\" + iFileStack.at(i)->Filename();
       
   126         if (!_strcmpi(includedFile.c_str(), includeDefFile.c_str()))
       
   127             {
       
   128             std::cerr << "Error: Circular inclusion of " << includeDefFile << " from ";
       
   129             std::cerr << CurrentFile().FilePath() << "\\" << CurrentFile().Filename() << " at line ";
       
   130             std::cerr << CurrentFile().Tokenizer().Line() << std::endl;
       
   131             iError = Parser::ECircularInclusion;
       
   132             return false;
       
   133             }
       
   134         }
       
   135 
       
   136     bool loadSuccess;
       
   137     CDefinitionFile* defFile = new CDefinitionFile(includeDefFile);
       
   138     loadSuccess = (defFile->Tokenizer().LoadDefinitionFile(includeDefFile) == Tokens::ENoError);
       
   139     if (!loadSuccess)
       
   140         {
       
   141         // if loading the first (the specified initial definition file) and it failed
       
   142         // and the file isn't root relative or absolute try looking in the exe dir
       
   143         if (iFileStack.empty() && aDefinitionFile[0] != '\\' && aDefinitionFile[1] != ':') 
       
   144             {
       
   145             includeDefFile = ::__argv[0];
       
   146             size_t sep;
       
   147             sep = includeDefFile.find_last_of('\\');
       
   148             if (sep != std::string::npos)
       
   149                 {
       
   150                 includeDefFile.erase(sep + 1);
       
   151                 includeDefFile += aDefinitionFile;
       
   152                 }
       
   153 
       
   154             delete defFile;
       
   155             defFile = new CDefinitionFile(includeDefFile);
       
   156             loadSuccess = (defFile->Tokenizer().LoadDefinitionFile(includeDefFile) == Tokens::ENoError);
       
   157             }
       
   158 
       
   159         if (!loadSuccess)
       
   160             {
       
   161             delete defFile;
       
   162             if (iFileStack.empty())
       
   163                 {
       
   164                 std::cerr << "Error loading definition file: " << aDefinitionFile << std::endl;
       
   165                 }
       
   166             else
       
   167                 {
       
   168                 std::cerr << "Error loading definition file: " << includeDefFile
       
   169                     << " included from "
       
   170                     << CurrentFile().FilePath() << "\\" << CurrentFile().Filename()
       
   171                     << " at line "
       
   172                     << CurrentFile().Tokenizer().Line() << std::endl;
       
   173                 }
       
   174 
       
   175             iError = EFileError;
       
   176             return false;
       
   177             }
       
   178         }
       
   179     
       
   180     iFileStack.push_back(defFile);
       
   181     return true;
       
   182     }
       
   183 
       
   184 
       
   185 void CDefinitionParser::CloseCurrentFile()
       
   186     {
       
   187     assert(!iFileStack.empty());
       
   188     CDefinitionFile* defFile = iFileStack.back();
       
   189     iFileStack.pop_back();
       
   190     delete defFile;
       
   191     }
       
   192 
       
   193 
       
   194 CDefinitionFile& CDefinitionParser::CurrentFile()
       
   195     {
       
   196     assert(!iFileStack.empty());
       
   197     return *(iFileStack.back());
       
   198     }
       
   199 
       
   200 
       
   201 Parser::TResult CDefinitionParser::ParseDefinitionFile(const char* aDefinitionFile)
       
   202     {
       
   203     iError = ENoError;
       
   204     if (!IncludeDefinitionFile(aDefinitionFile))
       
   205         {
       
   206         return iError;
       
   207         }
       
   208 
       
   209     SetState(new CInitialState(*this));
       
   210 
       
   211     do
       
   212         {
       
   213         while (CurrentFile().Tokenizer().GetNextToken() == Tokens::ETokenFound)
       
   214             {
       
   215             State().ProcessState();
       
   216 
       
   217             if (iError != Parser::ENoError && !iTesting)
       
   218                 {
       
   219                 return iError;
       
   220                 }
       
   221             }
       
   222 
       
   223         if (State().StateId() != Parser::EStateInitial)
       
   224             {
       
   225             std::cerr << "Error: Unexpected end of file ";
       
   226             std::cerr << CurrentFile().Filename() << " at line ";
       
   227             std::cerr << CurrentFile().Tokenizer().Line() << std::endl;
       
   228             if (!iTesting)
       
   229                 {
       
   230                 return Parser::EUnexpectedEndOfFile;
       
   231                 }
       
   232             }
       
   233 
       
   234         // finished with current file
       
   235         CloseCurrentFile();
       
   236 
       
   237         } while (iFileStack.size() > 0);
       
   238 
       
   239      return iError;
       
   240     }
       
   241 
       
   242 
       
   243 void CDefinitionParser::DumpIdentifiers() const
       
   244     {
       
   245     unsigned int i;
       
   246     std::cout << "utracedecoder " APPVERSION << std::endl;
       
   247     std::cout << "Identifier List" << std::endl << "===============" << std::endl;
       
   248     for (i=0; i<iAllIdentifiers.size(); i++)
       
   249         {
       
   250         std::cout << std::endl;
       
   251 
       
   252         switch (iAllIdentifiers.at(i)->Type())
       
   253             {
       
   254             case EConstIdentifier:
       
   255                 {
       
   256                 const CConstIdentifier* ident = static_cast<const CConstIdentifier*>(iAllIdentifiers.at(i));
       
   257                 std::cout << "CONST " << ident->Name() << " = " << ident->iValue << std::endl;
       
   258                 }
       
   259                 break;
       
   260 
       
   261             case EEnumTypeIdentifier:
       
   262                 {
       
   263                 const CEnumTypeIdentifier* ident = static_cast<const CEnumTypeIdentifier*>(iAllIdentifiers.at(i));
       
   264                 std::cout << "ENUM " << ident->Name() << "(size=";
       
   265                 std::cout << ident->Size();
       
   266                 std::cout << ")" << std::endl;
       
   267                 unsigned int j;
       
   268                 for (j=0; j<ident->iEnumValues.size(); j++)
       
   269                     {
       
   270                     std::cout << "   " << ident->iEnumValues.at(j)->Name() << " = " << ident->iEnumValues.at(j)->iValue << std::endl;
       
   271                     }
       
   272                 std::cout << std::endl;
       
   273                 }
       
   274                 break;
       
   275 
       
   276             case EStructIdentifier:
       
   277             case EMessageIdTypeIdentifier:
       
   278                 {
       
   279                 const CStructIdentifier* ident = static_cast<const CStructIdentifier*>(iAllIdentifiers.at(i));
       
   280                 std::cout << "STRUCT " << ident->Name() << "(size=";
       
   281                 std::cout << ident->TotalSize();
       
   282                 std::cout << ")" << std::endl;
       
   283                 unsigned int j;
       
   284                 for (j=0; j<ident->iMembers.size(); j++)
       
   285                     {
       
   286                     std::cout << "   " << ident->iMembers.at(j)->iOffset << ": ";
       
   287                     std::cout << "   " << ident->iMembers.at(j)->iMemberType->Name() << " "
       
   288                         << ident->iMembers.at(j)->iMemberName
       
   289                         << " (" << ident->iMembers.at(j)->iArraySize * ident->iMembers.at(j)->iMemberType->TotalSize()
       
   290                         << ")" << std::endl;
       
   291                     }
       
   292                 std::cout << std::endl;
       
   293                 }
       
   294                 break;
       
   295 
       
   296             case ESignatureIdentifier:
       
   297                 {
       
   298                 if (iAllIdentifiers.at(i)->Flags() & KAliasIdentifier)
       
   299                     {
       
   300                     const CSignatureAliasIdentifier* ident = static_cast<const CSignatureAliasIdentifier*>(iAllIdentifiers.at(i));
       
   301                     std::cout << "ALIAS SIGNATURE " << ident->Name()
       
   302                         << " = " << ident->RealName() << std::endl;
       
   303                     }
       
   304                 else
       
   305                     {
       
   306                     const CSignatureIdentifier* ident = static_cast<const CSignatureIdentifier*>(iAllIdentifiers.at(i));
       
   307                     std::cout << "SIGNATURE " << ident->Name() << "(size=";
       
   308                     std::cout << ident->TotalSize();
       
   309                     std::cout << ")" << std::endl;
       
   310                     if (ident->BaseSignature())
       
   311                         {
       
   312                         std::cout << "   BASE SIGNATURE = " << ident->BaseSignature()->Name()
       
   313                             << " (size=" << ident->BaseSignature()->TotalSize() << ")" << std::endl;
       
   314                         }
       
   315                     std::cout << "   STYPEID = (0x" << std::setw(8) << std::noshowbase
       
   316                         << std::nouppercase << std::hex << std::setfill('0') << ident->TypeId().iUid
       
   317                         << ", " << std::dec << ident->TypeId().iType << ")" << std::endl;
       
   318 
       
   319                     unsigned int j;
       
   320                     for (j=0; j<ident->iMembers.size(); j++)
       
   321                         {
       
   322                         std::cout << "   " << ident->iMembers.at(j)->iOffset << ": ";
       
   323                         std::cout << ident->iMembers.at(j)->iMemberType->Name() << " "
       
   324                             << ident->iMembers.at(j)->iMemberName
       
   325                             << " (size=" << ident->iMembers.at(j)->iArraySize * ident->iMembers.at(j)->iMemberType->TotalSize()
       
   326                             << ")" << std::endl;
       
   327                         }
       
   328                     }
       
   329                 std::cout << std::endl;
       
   330                 }
       
   331                 break;
       
   332 
       
   333             case EContextIdentifier:
       
   334                 {
       
   335                 if (iAllIdentifiers.at(i)->Flags() & KAliasIdentifier)
       
   336                     {
       
   337                     const CContextAliasIdentifier* ident = static_cast<const CContextAliasIdentifier*>(iAllIdentifiers.at(i));
       
   338                     std::cout << "ALIAS CONTEXT " << ident->Name()
       
   339                         << " = " << ident->RealName() << std::endl << std::endl;
       
   340                     }
       
   341                 else
       
   342                     {
       
   343                     const CContextIdentifier* ident = static_cast<const CContextIdentifier*>(iAllIdentifiers.at(i));
       
   344                     std::cout << "CONTEXT " << ident->Name() << "(size=";
       
   345                     std::cout << ident->TotalSize();
       
   346                     std::cout << ")" << std::endl;
       
   347                     if (ident->BaseContext())
       
   348                         {
       
   349                         std::cout << "   BASE CONTEXT = " << ident->BaseContext()->Name()
       
   350                             << " (size=" << ident->BaseContext()->TotalSize() << ")" << std::endl;
       
   351                         }
       
   352 
       
   353                     unsigned int j;
       
   354                     for (j=0; j<ident->iMembers.size(); j++)
       
   355                         {
       
   356                         std::cout << "   " << ident->iMembers.at(j)->iOffset << ": ";
       
   357                         std::cout << ident->iMembers.at(j)->iMemberType->Name() << " " 
       
   358                             << ident->iMembers.at(j)->iMemberName
       
   359                             << " (size=" << ident->iMembers.at(j)->iArraySize * ident->iMembers.at(j)->iMemberType->TotalSize()
       
   360                             << ")" << std::endl;
       
   361                         }
       
   362                     }
       
   363                 std::cout << std::endl;
       
   364                 }
       
   365                 break;
       
   366 
       
   367             case EMessageIdentifier:
       
   368                 {
       
   369                 if (iAllIdentifiers.at(i)->Flags() & KAliasIdentifier)
       
   370                     {
       
   371                     const CMessageAliasIdentifier* ident = static_cast<const CMessageAliasIdentifier*>(iAllIdentifiers.at(i));
       
   372                     std::cout << "ALIAS MESSAGE " << ident->Name()
       
   373                         << " = " << ident->RealName() << std::endl << std::endl;
       
   374                     }
       
   375                 else
       
   376                     {
       
   377                     const CMessageIdentifier* ident = static_cast<const CMessageIdentifier*>(iAllIdentifiers.at(i));
       
   378                     std::cout << "MESSAGE " << ident->Name() << std::endl;
       
   379                     if (ident->iSignature)
       
   380                         {
       
   381                         std::cout << "   SIGNATURE = " << ident->iSignature->Name() << std::endl;
       
   382                         }
       
   383                     std::cout << "   ID = (" << ident->iMessageId.iRealmId << ", " << ident->iMessageId.iMessageId << ")" << std::endl;
       
   384                     }
       
   385                 std::cout << std::endl;
       
   386                 }
       
   387                 break;
       
   388 
       
   389             default:
       
   390                 std::cout << iAllIdentifiers.at(i)->Name() << " (identifier type=" << iAllIdentifiers.at(i)->Type() << ")" << std::endl;
       
   391                 break;
       
   392             }
       
   393         }
       
   394     }
       
   395 
       
   396 const CIdentifierBase* CDefinitionParser::FindIdentifier(const char* aIdentifierName) const
       
   397     {
       
   398     unsigned int i;
       
   399     const CIdentifierBase* ident;
       
   400     for (i=0; i<iAllIdentifiers.size(); i++)
       
   401         {
       
   402         ident = iAllIdentifiers.at(i);
       
   403         if (!_strcmpi(ident->Name(), aIdentifierName))
       
   404             {
       
   405             return ident;
       
   406             }
       
   407         }
       
   408     return NULL;
       
   409     }
       
   410 
       
   411 
       
   412 void CDefinitionParser::AddIdentifier(const CIdentifierBase* aIdentifier)
       
   413     {
       
   414     if (FindIdentifier(aIdentifier->Name()))
       
   415         {
       
   416         std::cerr << "ERROR: **** Adding duplicate identifier : " << aIdentifier->Name() << " ****" << std::endl;
       
   417         }
       
   418     assert(!FindIdentifier(aIdentifier->Name()));
       
   419     iAllIdentifiers.push_back(aIdentifier);
       
   420     }
       
   421 
       
   422 const CContextIdentifier* CDefinitionParser::FindContextBySize(unsigned int aSize) const
       
   423     {
       
   424     unsigned int i;
       
   425     const CContextIdentifier* context;
       
   426     for (i=0; i<iAllIdentifiers.size(); i++)
       
   427         {
       
   428         context = static_cast<const CContextIdentifier*>(iAllIdentifiers.at(i));
       
   429         if (context->Type() == Parser::EContextIdentifier
       
   430             && context->TotalSize() == aSize)
       
   431             {
       
   432             return context;
       
   433             }   
       
   434         }
       
   435     return NULL;
       
   436     }
       
   437 
       
   438 const CSignatureIdentifier* CDefinitionParser::FindSignatureByTypeId(const STypeId& aTypeId) const
       
   439     {
       
   440     unsigned int i;
       
   441     const CSignatureIdentifier* signature;
       
   442     for (i=0; i<iAllIdentifiers.size(); i++)
       
   443         {
       
   444         signature = static_cast<const CSignatureIdentifier*>(iAllIdentifiers.at(i));
       
   445         if (signature->Type() == Parser::ESignatureIdentifier
       
   446             && signature->TypeId().iUid == aTypeId.iUid
       
   447             && signature->TypeId().iType == aTypeId.iType) 
       
   448             {
       
   449             return signature;
       
   450             }   
       
   451         }
       
   452     return NULL;
       
   453     }
       
   454 
       
   455 
       
   456 const CMessageIdentifier* CDefinitionParser::FindMessageByMessageId(const TMessageId& aMessageId) const
       
   457     {
       
   458     unsigned int i;
       
   459     const CMessageIdentifier* message;
       
   460     for (i=0; i<iAllIdentifiers.size(); i++)
       
   461         {
       
   462         message = static_cast<const CMessageIdentifier*>(iAllIdentifiers.at(i));
       
   463         if (message->Type() == Parser::EMessageIdentifier
       
   464             && message->iMessageId.iRealmId == aMessageId.iRealmId
       
   465             && message->iMessageId.iMessageId == aMessageId.iMessageId)
       
   466             {
       
   467             return message;
       
   468             }       
       
   469         }
       
   470     return NULL;
       
   471     }
       
   472 
       
   473 void CDefinitionParser::SetError(TResult aError)
       
   474     {
       
   475     iError = aError;
       
   476     switch (iError)
       
   477         {
       
   478         case ENoError:
       
   479             return;
       
   480             //break;
       
   481 
       
   482         case EDuplicateIdentifier:
       
   483             std::cerr << "Error: Duplicate identifier \"" << CurrentFile().Tokenizer().Token() << "\" in ";
       
   484             break;
       
   485 
       
   486         case EValueOutOfRange:
       
   487             std::cerr << "Error: Value out of range \"" << CurrentFile().Tokenizer().Token() << "\" in ";
       
   488             break;
       
   489 
       
   490         case EUnexpectedToken:
       
   491             std::cerr << "Error: Unexpected token \"" << CurrentFile().Tokenizer().Token() << "\" in ";
       
   492             break;
       
   493 
       
   494         case EUnknownIdentifier:
       
   495             std::cerr << "Error: Unknown identifier \"" << CurrentFile().Tokenizer().Token() << "\" in ";
       
   496             break;
       
   497 
       
   498         default:
       
   499             std::cerr << "Error: (" << iError << ") in ";
       
   500         }
       
   501 
       
   502     std::cerr << CurrentFile().Filename() << " at line ";
       
   503     std::cerr << CurrentFile().Tokenizer().Line() << std::endl;            
       
   504     }
       
   505 
       
   506 } // namespace Parser
       
   507