Home | History | Annotate | Download | only in Eot
      1 ## @file

      2 # preprocess source file

      3 #

      4 #  Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>

      5 #

      6 #  This program and the accompanying materials

      7 #  are licensed and made available under the terms and conditions of the BSD License

      8 #  which accompanies this distribution.  The full text of the license may be found at

      9 #  http://opensource.org/licenses/bsd-license.php

     10 #

     11 #  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

     12 #  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

     13 #

     14 
     15 ##

     16 # Import Modules

     17 #

     18 import sys
     19 import Common.LongFilePathOs as os
     20 import re
     21 import CodeFragmentCollector
     22 import FileProfile
     23 from CommonDataClass import DataClass
     24 from Common import EdkLogger
     25 from EotToolError import *
     26 import EotGlobalData
     27 
     28 # Global Dicts

     29 IncludeFileListDict = {}
     30 IncludePathListDict = {}
     31 ComplexTypeDict = {}
     32 SUDict = {}
     33 
     34 ## GetFuncDeclPattern() method

     35 #

     36 #  Get the pattern of function declaration

     37 #

     38 #  @return p:    the pattern of function declaration

     39 #

     40 def GetFuncDeclPattern():
     41     p = re.compile(r'(EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\).*', re.DOTALL)
     42     return p
     43 
     44 ## GetArrayPattern() method

     45 #

     46 #  Get the pattern of array

     47 #

     48 #  @return p:    the pattern of array

     49 #

     50 def GetArrayPattern():
     51     p = re.compile(r'[_\w]*\s*[\[.*\]]+')
     52     return p
     53 
     54 ## GetTypedefFuncPointerPattern() method

     55 #

     56 #  Get the pattern of function pointer

     57 #

     58 #  @return p:    the pattern of function pointer

     59 #

     60 def GetTypedefFuncPointerPattern():
     61     p = re.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re.DOTALL)
     62     return p
     63 
     64 ## GetDB() method

     65 #

     66 #  Get global database instance

     67 #

     68 #  @return EotGlobalData.gDb:    the global database instance

     69 #

     70 def GetDB():
     71     return EotGlobalData.gDb
     72 
     73 ## PrintErrorMsg() method

     74 #

     75 #  print error message

     76 #

     77 #  @param ErrorType: Type of error

     78 #  @param Msg: Error message

     79 #  @param TableName: table name of error found

     80 #  @param ItemId: id of item

     81 #

     82 def PrintErrorMsg(ErrorType, Msg, TableName, ItemId):
     83     Msg = Msg.replace('\n', '').replace('\r', '')
     84     MsgPartList = Msg.split()
     85     Msg = ''
     86     for Part in MsgPartList:
     87         Msg += Part
     88         Msg += ' '
     89     GetDB().TblReport.Insert(ErrorType, OtherMsg = Msg, BelongsToTable = TableName, BelongsToItem = ItemId)
     90 
     91 ## GetIdType() method

     92 #

     93 #  Find type of input string

     94 #

     95 #  @param Str: String to be parsed

     96 #

     97 #  @return Type: The type of the string

     98 #

     99 def GetIdType(Str):
    100     Type = DataClass.MODEL_UNKNOWN
    101     Str = Str.replace('#', '# ')
    102     List = Str.split()
    103     if List[1] == 'include':
    104         Type = DataClass.MODEL_IDENTIFIER_INCLUDE
    105     elif List[1] == 'define':
    106         Type = DataClass.MODEL_IDENTIFIER_MACRO_DEFINE
    107     elif List[1] == 'ifdef':
    108         Type = DataClass.MODEL_IDENTIFIER_MACRO_IFDEF
    109     elif List[1] == 'ifndef':
    110         Type = DataClass.MODEL_IDENTIFIER_MACRO_IFNDEF
    111     elif List[1] == 'endif':
    112         Type = DataClass.MODEL_IDENTIFIER_MACRO_ENDIF
    113     elif List[1] == 'pragma':
    114         Type = DataClass.MODEL_IDENTIFIER_MACRO_PROGMA
    115     else:
    116         Type = DataClass.MODEL_UNKNOWN
    117     return Type
    118 
    119 ## GetIdentifierList() method

    120 #

    121 #  Get id of all files

    122 #

    123 #  @return IdList: The list of all id of files

    124 #

    125 def GetIdentifierList():
    126     IdList = []
    127 
    128     for pp in FileProfile.PPDirectiveList:
    129         Type = GetIdType(pp.Content)
    130         IdPP = DataClass.IdentifierClass(-1, '', '', '', pp.Content, Type, -1, -1, pp.StartPos[0],pp.StartPos[1],pp.EndPos[0],pp.EndPos[1])
    131         IdList.append(IdPP)
    132 
    133     for ae in FileProfile.AssignmentExpressionList:
    134         IdAE = DataClass.IdentifierClass(-1, ae.Operator, '', ae.Name, ae.Value, DataClass.MODEL_IDENTIFIER_ASSIGNMENT_EXPRESSION, -1, -1, ae.StartPos[0],ae.StartPos[1],ae.EndPos[0],ae.EndPos[1])
    135         IdList.append(IdAE)
    136 
    137     FuncDeclPattern = GetFuncDeclPattern()
    138     ArrayPattern = GetArrayPattern()
    139     for var in FileProfile.VariableDeclarationList:
    140         DeclText = var.Declarator.strip()
    141         while DeclText.startswith('*'):
    142             var.Modifier += '*'
    143             DeclText = DeclText.lstrip('*').strip()
    144         var.Declarator = DeclText
    145         if FuncDeclPattern.match(var.Declarator):
    146             DeclSplitList = var.Declarator.split('(')
    147             FuncName = DeclSplitList[0]
    148             FuncNamePartList = FuncName.split()
    149             if len(FuncNamePartList) > 1:
    150                 FuncName = FuncNamePartList[-1]
    151                 Index = 0
    152                 while Index < len(FuncNamePartList) - 1:
    153                     var.Modifier += ' ' + FuncNamePartList[Index]
    154                     var.Declarator = var.Declarator.lstrip().lstrip(FuncNamePartList[Index])
    155                     Index += 1
    156             IdVar = DataClass.IdentifierClass(-1, var.Modifier, '', var.Declarator, '', DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, -1, -1, var.StartPos[0],var.StartPos[1],var.EndPos[0],var.EndPos[1])
    157             IdList.append(IdVar)
    158             continue
    159 
    160         if var.Declarator.find('{') == -1:
    161             for decl in var.Declarator.split(','):
    162                 DeclList = decl.split('=')
    163                 Name = DeclList[0].strip()
    164                 if ArrayPattern.match(Name):
    165                     LSBPos = var.Declarator.find('[')
    166                     var.Modifier += ' ' + Name[LSBPos:]
    167                     Name = Name[0:LSBPos]
    168 
    169                 IdVar = DataClass.IdentifierClass(-1, var.Modifier, '', Name, (len(DeclList) > 1 and [DeclList[1]]or [''])[0], DataClass.MODEL_IDENTIFIER_VARIABLE, -1, -1, var.StartPos[0],var.StartPos[1],var.EndPos[0],var.EndPos[1])
    170                 IdList.append(IdVar)
    171         else:
    172             DeclList = var.Declarator.split('=')
    173             Name = DeclList[0].strip()
    174             if ArrayPattern.match(Name):
    175                 LSBPos = var.Declarator.find('[')
    176                 var.Modifier += ' ' + Name[LSBPos:]
    177                 Name = Name[0:LSBPos]
    178             IdVar = DataClass.IdentifierClass(-1, var.Modifier, '', Name, (len(DeclList) > 1 and [DeclList[1]]or [''])[0], DataClass.MODEL_IDENTIFIER_VARIABLE, -1, -1, var.StartPos[0],var.StartPos[1],var.EndPos[0],var.EndPos[1])
    179             IdList.append(IdVar)
    180 
    181     for enum in FileProfile.EnumerationDefinitionList:
    182         LBPos = enum.Content.find('{')
    183         RBPos = enum.Content.find('}')
    184         Name = enum.Content[4:LBPos].strip()
    185         Value = enum.Content[LBPos+1:RBPos]
    186         IdEnum = DataClass.IdentifierClass(-1, '', '', Name, Value, DataClass.MODEL_IDENTIFIER_ENUMERATE, -1, -1, enum.StartPos[0],enum.StartPos[1],enum.EndPos[0],enum.EndPos[1])
    187         IdList.append(IdEnum)
    188 
    189     for su in FileProfile.StructUnionDefinitionList:
    190         Type = DataClass.MODEL_IDENTIFIER_STRUCTURE
    191         SkipLen = 6
    192         if su.Content.startswith('union'):
    193             Type = DataClass.MODEL_IDENTIFIER_UNION
    194             SkipLen = 5
    195         LBPos = su.Content.find('{')
    196         RBPos = su.Content.find('}')
    197         if LBPos == -1 or RBPos == -1:
    198             Name = su.Content[SkipLen:].strip()
    199             Value = ''
    200         else:
    201             Name = su.Content[SkipLen:LBPos].strip()
    202             Value = su.Content[LBPos+1:RBPos]
    203         IdPE = DataClass.IdentifierClass(-1, '', '', Name, Value, Type, -1, -1, su.StartPos[0],su.StartPos[1],su.EndPos[0],su.EndPos[1])
    204         IdList.append(IdPE)
    205 
    206     TdFuncPointerPattern = GetTypedefFuncPointerPattern()
    207     for td in FileProfile.TypedefDefinitionList:
    208         Modifier = ''
    209         Name = td.ToType
    210         Value = td.FromType
    211         if TdFuncPointerPattern.match(td.ToType):
    212             Modifier = td.FromType
    213             LBPos = td.ToType.find('(')
    214             TmpStr = td.ToType[LBPos+1:].strip()
    215             StarPos = TmpStr.find('*')
    216             if StarPos != -1:
    217                 Modifier += ' ' + TmpStr[0:StarPos]
    218             while TmpStr[StarPos] == '*':
    219                 Modifier += ' ' + '*'
    220                 StarPos += 1
    221             TmpStr = TmpStr[StarPos:].strip()
    222             RBPos = TmpStr.find(')')
    223             Name = TmpStr[0:RBPos]
    224             Value = 'FP' + TmpStr[RBPos + 1:]
    225 
    226         IdTd = DataClass.IdentifierClass(-1, Modifier, '', Name, Value, DataClass.MODEL_IDENTIFIER_TYPEDEF, -1, -1, td.StartPos[0],td.StartPos[1],td.EndPos[0],td.EndPos[1])
    227         IdList.append(IdTd)
    228 
    229     for funcCall in FileProfile.FunctionCallingList:
    230         IdFC = DataClass.IdentifierClass(-1, '', '', funcCall.FuncName, funcCall.ParamList, DataClass.MODEL_IDENTIFIER_FUNCTION_CALLING, -1, -1, funcCall.StartPos[0],funcCall.StartPos[1],funcCall.EndPos[0],funcCall.EndPos[1])
    231         IdList.append(IdFC)
    232     return IdList
    233 
    234 ## GetParamList() method

    235 #

    236 #  Get a list of parameters

    237 #

    238 #  @param FuncDeclarator: Function declarator

    239 #  @param FuncNameLine: Line number of function name

    240 #  @param FuncNameOffset: Offset of function name

    241 #

    242 #  @return ParamIdList: A list of parameters

    243 #

    244 def GetParamList(FuncDeclarator, FuncNameLine = 0, FuncNameOffset = 0):
    245     ParamIdList = []
    246     DeclSplitList = FuncDeclarator.split('(')
    247     if len(DeclSplitList) < 2:
    248         return ParamIdList
    249     FuncName = DeclSplitList[0]
    250     ParamStr = DeclSplitList[1].rstrip(')')
    251     LineSkipped = 0
    252     OffsetSkipped = 0
    253     Start = 0
    254     while FuncName.find('\n', Start) != -1:
    255         LineSkipped += 1
    256         OffsetSkipped = 0
    257         Start += FuncName.find('\n', Start)
    258         Start += 1
    259     OffsetSkipped += len(FuncName[Start:])
    260     OffsetSkipped += 1 #skip '('

    261     ParamBeginLine = FuncNameLine + LineSkipped
    262     ParamBeginOffset = OffsetSkipped
    263     for p in ParamStr.split(','):
    264         ListP = p.split()
    265         if len(ListP) == 0:
    266             continue
    267         ParamName = ListP[-1]
    268         DeclText = ParamName.strip()
    269         RightSpacePos = p.rfind(ParamName)
    270         ParamModifier = p[0:RightSpacePos]
    271         if ParamName == 'OPTIONAL':
    272             if ParamModifier == '':
    273                 ParamModifier += ' ' + 'OPTIONAL'
    274                 DeclText = ''
    275             else:
    276                 ParamName = ListP[-2]
    277                 DeclText = ParamName.strip()
    278                 RightSpacePos = p.rfind(ParamName)
    279                 ParamModifier = p[0:RightSpacePos]
    280                 ParamModifier += 'OPTIONAL'
    281         while DeclText.startswith('*'):
    282             ParamModifier += ' ' + '*'
    283             DeclText = DeclText.lstrip('*').strip()
    284         ParamName = DeclText
    285 
    286         Start = 0
    287         while p.find('\n', Start) != -1:
    288             LineSkipped += 1
    289             OffsetSkipped = 0
    290             Start += p.find('\n', Start)
    291             Start += 1
    292         OffsetSkipped += len(p[Start:])
    293 
    294         ParamEndLine = ParamBeginLine + LineSkipped
    295         ParamEndOffset = OffsetSkipped
    296         IdParam = DataClass.IdentifierClass(-1, ParamModifier, '', ParamName, '', DataClass.MODEL_IDENTIFIER_PARAMETER, -1, -1, ParamBeginLine, ParamBeginOffset, ParamEndLine, ParamEndOffset)
    297         ParamIdList.append(IdParam)
    298         ParamBeginLine = ParamEndLine
    299         ParamBeginOffset = OffsetSkipped + 1 #skip ','

    300 
    301     return ParamIdList
    302 
    303 ## GetFunctionList()

    304 #

    305 #  Get a list of functions

    306 #

    307 #  @return FuncObjList: A list of function objects

    308 #

    309 def GetFunctionList():
    310     FuncObjList = []
    311     for FuncDef in FileProfile.FunctionDefinitionList:
    312         ParamIdList = []
    313         DeclText = FuncDef.Declarator.strip()
    314         while DeclText.startswith('*'):
    315             FuncDef.Modifier += '*'
    316             DeclText = DeclText.lstrip('*').strip()
    317 
    318         FuncDef.Declarator = FuncDef.Declarator.lstrip('*')
    319         DeclSplitList = FuncDef.Declarator.split('(')
    320         if len(DeclSplitList) < 2:
    321             continue
    322 
    323         FuncName = DeclSplitList[0]
    324         FuncNamePartList = FuncName.split()
    325         if len(FuncNamePartList) > 1:
    326             FuncName = FuncNamePartList[-1]
    327             Index = 0
    328             while Index < len(FuncNamePartList) - 1:
    329                 FuncDef.Modifier += ' ' + FuncNamePartList[Index]
    330                 Index += 1
    331 
    332         FuncObj = DataClass.FunctionClass(-1, FuncDef.Declarator, FuncDef.Modifier, FuncName.strip(), '', FuncDef.StartPos[0],FuncDef.StartPos[1],FuncDef.EndPos[0],FuncDef.EndPos[1], FuncDef.LeftBracePos[0], FuncDef.LeftBracePos[1], -1, ParamIdList, [])
    333         FuncObjList.append(FuncObj)
    334 
    335     return FuncObjList
    336 
    337 ## CreateCCodeDB() method

    338 #

    339 #  Create database for all c code

    340 #

    341 #  @param FileNameList: A list of all c code file names

    342 #

    343 def CreateCCodeDB(FileNameList):
    344     FileObjList = []
    345     ParseErrorFileList = []
    346     ParsedFiles = {}
    347     for FullName in FileNameList:
    348         if os.path.splitext(FullName)[1] in ('.h', '.c'):
    349             if FullName.lower() in ParsedFiles:
    350                 continue
    351             ParsedFiles[FullName.lower()] = 1
    352             EdkLogger.info("Parsing " + FullName)
    353             model = FullName.endswith('c') and DataClass.MODEL_FILE_C or DataClass.MODEL_FILE_H
    354             collector = CodeFragmentCollector.CodeFragmentCollector(FullName)
    355             try:
    356                 collector.ParseFile()
    357             except:
    358                 ParseErrorFileList.append(FullName)
    359             BaseName = os.path.basename(FullName)
    360             DirName = os.path.dirname(FullName)
    361             Ext = os.path.splitext(BaseName)[1].lstrip('.')
    362             ModifiedTime = os.path.getmtime(FullName)
    363             FileObj = DataClass.FileClass(-1, BaseName, Ext, DirName, FullName, model, ModifiedTime, GetFunctionList(), GetIdentifierList(), [])
    364             FileObjList.append(FileObj)
    365             collector.CleanFileProfileBuffer()
    366 
    367     if len(ParseErrorFileList) > 0:
    368         EdkLogger.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList))
    369 
    370     Db = EotGlobalData.gDb
    371     for file in FileObjList:
    372         Db.InsertOneFile(file)
    373 
    374     Db.UpdateIdentifierBelongsToFunction()
    375 
    376 ##

    377 #

    378 # This acts like the main() function for the script, unless it is 'import'ed into another

    379 # script.

    380 #

    381 if __name__ == '__main__':
    382 
    383     EdkLogger.Initialize()
    384     EdkLogger.SetLevel(EdkLogger.QUIET)
    385     CollectSourceCodeDataIntoDB(sys.argv[1])
    386 
    387     print 'Done!'
    388