https://bugzilla.tianocore.org/show_bug.cgi?id=1373 Replace BSD 2-Clause License with BSD+Patent License. This change is based on the following emails: https://lists.01.org/pipermail/edk2-devel/2019-February/036260.html https://lists.01.org/pipermail/edk2-devel/2018-October/030385.html RFCs with detailed process for the license change: V3: https://lists.01.org/pipermail/edk2-devel/2019-March/038116.html V2: https://lists.01.org/pipermail/edk2-devel/2019-March/037669.html V1: https://lists.01.org/pipermail/edk2-devel/2019-March/037500.html Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Bob Feng <bob.c.feng@intel.com>
		
			
				
	
	
		
			384 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			384 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
## @file
 | 
						|
# preprocess source file
 | 
						|
#
 | 
						|
#  Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
 | 
						|
#
 | 
						|
#  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
#
 | 
						|
 | 
						|
##
 | 
						|
# Import Modules
 | 
						|
#
 | 
						|
from __future__ import print_function
 | 
						|
from __future__ import absolute_import
 | 
						|
import sys
 | 
						|
import Common.LongFilePathOs as os
 | 
						|
import re
 | 
						|
from . import CodeFragmentCollector
 | 
						|
from . import FileProfile
 | 
						|
from CommonDataClass import DataClass
 | 
						|
from Common import EdkLogger
 | 
						|
from .EotToolError import *
 | 
						|
from . import EotGlobalData
 | 
						|
 | 
						|
# Global Dicts
 | 
						|
IncludeFileListDict = {}
 | 
						|
IncludePathListDict = {}
 | 
						|
ComplexTypeDict = {}
 | 
						|
SUDict = {}
 | 
						|
 | 
						|
## GetFuncDeclPattern() method
 | 
						|
#
 | 
						|
#  Get the pattern of function declaration
 | 
						|
#
 | 
						|
#  @return p:    the pattern of function declaration
 | 
						|
#
 | 
						|
def GetFuncDeclPattern():
 | 
						|
    p = re.compile(r'(EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\).*', re.DOTALL)
 | 
						|
    return p
 | 
						|
 | 
						|
## GetArrayPattern() method
 | 
						|
#
 | 
						|
#  Get the pattern of array
 | 
						|
#
 | 
						|
#  @return p:    the pattern of array
 | 
						|
#
 | 
						|
def GetArrayPattern():
 | 
						|
    p = re.compile(r'[_\w]*\s*[\[.*\]]+')
 | 
						|
    return p
 | 
						|
 | 
						|
## GetTypedefFuncPointerPattern() method
 | 
						|
#
 | 
						|
#  Get the pattern of function pointer
 | 
						|
#
 | 
						|
#  @return p:    the pattern of function pointer
 | 
						|
#
 | 
						|
def GetTypedefFuncPointerPattern():
 | 
						|
    p = re.compile('[_\w\s]*\([\w\s]*\*+\s*[_\w]+\s*\)\s*\(.*\)', re.DOTALL)
 | 
						|
    return p
 | 
						|
 | 
						|
## GetDB() method
 | 
						|
#
 | 
						|
#  Get global database instance
 | 
						|
#
 | 
						|
#  @return EotGlobalData.gDb:    the global database instance
 | 
						|
#
 | 
						|
def GetDB():
 | 
						|
    return EotGlobalData.gDb
 | 
						|
 | 
						|
## PrintErrorMsg() method
 | 
						|
#
 | 
						|
#  print error message
 | 
						|
#
 | 
						|
#  @param ErrorType: Type of error
 | 
						|
#  @param Msg: Error message
 | 
						|
#  @param TableName: table name of error found
 | 
						|
#  @param ItemId: id of item
 | 
						|
#
 | 
						|
def PrintErrorMsg(ErrorType, Msg, TableName, ItemId):
 | 
						|
    Msg = Msg.replace('\n', '').replace('\r', '')
 | 
						|
    MsgPartList = Msg.split()
 | 
						|
    Msg = ''
 | 
						|
    for Part in MsgPartList:
 | 
						|
        Msg += Part
 | 
						|
        Msg += ' '
 | 
						|
    GetDB().TblReport.Insert(ErrorType, OtherMsg = Msg, BelongsToTable = TableName, BelongsToItem = ItemId)
 | 
						|
 | 
						|
## GetIdType() method
 | 
						|
#
 | 
						|
#  Find type of input string
 | 
						|
#
 | 
						|
#  @param Str: String to be parsed
 | 
						|
#
 | 
						|
#  @return Type: The type of the string
 | 
						|
#
 | 
						|
def GetIdType(Str):
 | 
						|
    Type = DataClass.MODEL_UNKNOWN
 | 
						|
    Str = Str.replace('#', '# ')
 | 
						|
    List = Str.split()
 | 
						|
    if List[1] == 'include':
 | 
						|
        Type = DataClass.MODEL_IDENTIFIER_INCLUDE
 | 
						|
    elif List[1] == 'define':
 | 
						|
        Type = DataClass.MODEL_IDENTIFIER_MACRO_DEFINE
 | 
						|
    elif List[1] == 'ifdef':
 | 
						|
        Type = DataClass.MODEL_IDENTIFIER_MACRO_IFDEF
 | 
						|
    elif List[1] == 'ifndef':
 | 
						|
        Type = DataClass.MODEL_IDENTIFIER_MACRO_IFNDEF
 | 
						|
    elif List[1] == 'endif':
 | 
						|
        Type = DataClass.MODEL_IDENTIFIER_MACRO_ENDIF
 | 
						|
    elif List[1] == 'pragma':
 | 
						|
        Type = DataClass.MODEL_IDENTIFIER_MACRO_PROGMA
 | 
						|
    else:
 | 
						|
        Type = DataClass.MODEL_UNKNOWN
 | 
						|
    return Type
 | 
						|
 | 
						|
## GetIdentifierList() method
 | 
						|
#
 | 
						|
#  Get id of all files
 | 
						|
#
 | 
						|
#  @return IdList: The list of all id of files
 | 
						|
#
 | 
						|
def GetIdentifierList():
 | 
						|
    IdList = []
 | 
						|
 | 
						|
    for pp in FileProfile.PPDirectiveList:
 | 
						|
        Type = GetIdType(pp.Content)
 | 
						|
        IdPP = DataClass.IdentifierClass(-1, '', '', '', pp.Content, Type, -1, -1, pp.StartPos[0], pp.StartPos[1], pp.EndPos[0], pp.EndPos[1])
 | 
						|
        IdList.append(IdPP)
 | 
						|
 | 
						|
    for ae in FileProfile.AssignmentExpressionList:
 | 
						|
        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])
 | 
						|
        IdList.append(IdAE)
 | 
						|
 | 
						|
    FuncDeclPattern = GetFuncDeclPattern()
 | 
						|
    ArrayPattern = GetArrayPattern()
 | 
						|
    for var in FileProfile.VariableDeclarationList:
 | 
						|
        DeclText = var.Declarator.strip()
 | 
						|
        while DeclText.startswith('*'):
 | 
						|
            var.Modifier += '*'
 | 
						|
            DeclText = DeclText.lstrip('*').strip()
 | 
						|
        var.Declarator = DeclText
 | 
						|
        if FuncDeclPattern.match(var.Declarator):
 | 
						|
            DeclSplitList = var.Declarator.split('(')
 | 
						|
            FuncName = DeclSplitList[0]
 | 
						|
            FuncNamePartList = FuncName.split()
 | 
						|
            if len(FuncNamePartList) > 1:
 | 
						|
                FuncName = FuncNamePartList[-1]
 | 
						|
                Index = 0
 | 
						|
                while Index < len(FuncNamePartList) - 1:
 | 
						|
                    var.Modifier += ' ' + FuncNamePartList[Index]
 | 
						|
                    var.Declarator = var.Declarator.lstrip().lstrip(FuncNamePartList[Index])
 | 
						|
                    Index += 1
 | 
						|
            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])
 | 
						|
            IdList.append(IdVar)
 | 
						|
            continue
 | 
						|
 | 
						|
        if var.Declarator.find('{') == -1:
 | 
						|
            for decl in var.Declarator.split(','):
 | 
						|
                DeclList = decl.split('=')
 | 
						|
                Name = DeclList[0].strip()
 | 
						|
                if ArrayPattern.match(Name):
 | 
						|
                    LSBPos = var.Declarator.find('[')
 | 
						|
                    var.Modifier += ' ' + Name[LSBPos:]
 | 
						|
                    Name = Name[0:LSBPos]
 | 
						|
 | 
						|
                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])
 | 
						|
                IdList.append(IdVar)
 | 
						|
        else:
 | 
						|
            DeclList = var.Declarator.split('=')
 | 
						|
            Name = DeclList[0].strip()
 | 
						|
            if ArrayPattern.match(Name):
 | 
						|
                LSBPos = var.Declarator.find('[')
 | 
						|
                var.Modifier += ' ' + Name[LSBPos:]
 | 
						|
                Name = Name[0:LSBPos]
 | 
						|
            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])
 | 
						|
            IdList.append(IdVar)
 | 
						|
 | 
						|
    for enum in FileProfile.EnumerationDefinitionList:
 | 
						|
        LBPos = enum.Content.find('{')
 | 
						|
        RBPos = enum.Content.find('}')
 | 
						|
        Name = enum.Content[4:LBPos].strip()
 | 
						|
        Value = enum.Content[LBPos+1:RBPos]
 | 
						|
        IdEnum = DataClass.IdentifierClass(-1, '', '', Name, Value, DataClass.MODEL_IDENTIFIER_ENUMERATE, -1, -1, enum.StartPos[0], enum.StartPos[1], enum.EndPos[0], enum.EndPos[1])
 | 
						|
        IdList.append(IdEnum)
 | 
						|
 | 
						|
    for su in FileProfile.StructUnionDefinitionList:
 | 
						|
        Type = DataClass.MODEL_IDENTIFIER_STRUCTURE
 | 
						|
        SkipLen = 6
 | 
						|
        if su.Content.startswith('union'):
 | 
						|
            Type = DataClass.MODEL_IDENTIFIER_UNION
 | 
						|
            SkipLen = 5
 | 
						|
        LBPos = su.Content.find('{')
 | 
						|
        RBPos = su.Content.find('}')
 | 
						|
        if LBPos == -1 or RBPos == -1:
 | 
						|
            Name = su.Content[SkipLen:].strip()
 | 
						|
            Value = ''
 | 
						|
        else:
 | 
						|
            Name = su.Content[SkipLen:LBPos].strip()
 | 
						|
            Value = su.Content[LBPos+1:RBPos]
 | 
						|
        IdPE = DataClass.IdentifierClass(-1, '', '', Name, Value, Type, -1, -1, su.StartPos[0], su.StartPos[1], su.EndPos[0], su.EndPos[1])
 | 
						|
        IdList.append(IdPE)
 | 
						|
 | 
						|
    TdFuncPointerPattern = GetTypedefFuncPointerPattern()
 | 
						|
    for td in FileProfile.TypedefDefinitionList:
 | 
						|
        Modifier = ''
 | 
						|
        Name = td.ToType
 | 
						|
        Value = td.FromType
 | 
						|
        if TdFuncPointerPattern.match(td.ToType):
 | 
						|
            Modifier = td.FromType
 | 
						|
            LBPos = td.ToType.find('(')
 | 
						|
            TmpStr = td.ToType[LBPos+1:].strip()
 | 
						|
            StarPos = TmpStr.find('*')
 | 
						|
            if StarPos != -1:
 | 
						|
                Modifier += ' ' + TmpStr[0:StarPos]
 | 
						|
            while TmpStr[StarPos] == '*':
 | 
						|
                Modifier += ' ' + '*'
 | 
						|
                StarPos += 1
 | 
						|
            TmpStr = TmpStr[StarPos:].strip()
 | 
						|
            RBPos = TmpStr.find(')')
 | 
						|
            Name = TmpStr[0:RBPos]
 | 
						|
            Value = 'FP' + TmpStr[RBPos + 1:]
 | 
						|
 | 
						|
        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])
 | 
						|
        IdList.append(IdTd)
 | 
						|
 | 
						|
    for funcCall in FileProfile.FunctionCallingList:
 | 
						|
        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])
 | 
						|
        IdList.append(IdFC)
 | 
						|
    return IdList
 | 
						|
 | 
						|
## GetParamList() method
 | 
						|
#
 | 
						|
#  Get a list of parameters
 | 
						|
#
 | 
						|
#  @param FuncDeclarator: Function declarator
 | 
						|
#  @param FuncNameLine: Line number of function name
 | 
						|
#  @param FuncNameOffset: Offset of function name
 | 
						|
#
 | 
						|
#  @return ParamIdList: A list of parameters
 | 
						|
#
 | 
						|
def GetParamList(FuncDeclarator, FuncNameLine = 0, FuncNameOffset = 0):
 | 
						|
    ParamIdList = []
 | 
						|
    DeclSplitList = FuncDeclarator.split('(')
 | 
						|
    if len(DeclSplitList) < 2:
 | 
						|
        return ParamIdList
 | 
						|
    FuncName = DeclSplitList[0]
 | 
						|
    ParamStr = DeclSplitList[1].rstrip(')')
 | 
						|
    LineSkipped = 0
 | 
						|
    OffsetSkipped = 0
 | 
						|
    Start = 0
 | 
						|
    while FuncName.find('\n', Start) != -1:
 | 
						|
        LineSkipped += 1
 | 
						|
        OffsetSkipped = 0
 | 
						|
        Start += FuncName.find('\n', Start)
 | 
						|
        Start += 1
 | 
						|
    OffsetSkipped += len(FuncName[Start:])
 | 
						|
    OffsetSkipped += 1 #skip '('
 | 
						|
    ParamBeginLine = FuncNameLine + LineSkipped
 | 
						|
    ParamBeginOffset = OffsetSkipped
 | 
						|
    for p in ParamStr.split(','):
 | 
						|
        ListP = p.split()
 | 
						|
        if len(ListP) == 0:
 | 
						|
            continue
 | 
						|
        ParamName = ListP[-1]
 | 
						|
        DeclText = ParamName.strip()
 | 
						|
        RightSpacePos = p.rfind(ParamName)
 | 
						|
        ParamModifier = p[0:RightSpacePos]
 | 
						|
        if ParamName == 'OPTIONAL':
 | 
						|
            if ParamModifier == '':
 | 
						|
                ParamModifier += ' ' + 'OPTIONAL'
 | 
						|
                DeclText = ''
 | 
						|
            else:
 | 
						|
                ParamName = ListP[-2]
 | 
						|
                DeclText = ParamName.strip()
 | 
						|
                RightSpacePos = p.rfind(ParamName)
 | 
						|
                ParamModifier = p[0:RightSpacePos]
 | 
						|
                ParamModifier += 'OPTIONAL'
 | 
						|
        while DeclText.startswith('*'):
 | 
						|
            ParamModifier += ' ' + '*'
 | 
						|
            DeclText = DeclText.lstrip('*').strip()
 | 
						|
        ParamName = DeclText
 | 
						|
 | 
						|
        Start = 0
 | 
						|
        while p.find('\n', Start) != -1:
 | 
						|
            LineSkipped += 1
 | 
						|
            OffsetSkipped = 0
 | 
						|
            Start += p.find('\n', Start)
 | 
						|
            Start += 1
 | 
						|
        OffsetSkipped += len(p[Start:])
 | 
						|
 | 
						|
        ParamEndLine = ParamBeginLine + LineSkipped
 | 
						|
        ParamEndOffset = OffsetSkipped
 | 
						|
        IdParam = DataClass.IdentifierClass(-1, ParamModifier, '', ParamName, '', DataClass.MODEL_IDENTIFIER_PARAMETER, -1, -1, ParamBeginLine, ParamBeginOffset, ParamEndLine, ParamEndOffset)
 | 
						|
        ParamIdList.append(IdParam)
 | 
						|
        ParamBeginLine = ParamEndLine
 | 
						|
        ParamBeginOffset = OffsetSkipped + 1 #skip ','
 | 
						|
 | 
						|
    return ParamIdList
 | 
						|
 | 
						|
## GetFunctionList()
 | 
						|
#
 | 
						|
#  Get a list of functions
 | 
						|
#
 | 
						|
#  @return FuncObjList: A list of function objects
 | 
						|
#
 | 
						|
def GetFunctionList():
 | 
						|
    FuncObjList = []
 | 
						|
    for FuncDef in FileProfile.FunctionDefinitionList:
 | 
						|
        ParamIdList = []
 | 
						|
        DeclText = FuncDef.Declarator.strip()
 | 
						|
        while DeclText.startswith('*'):
 | 
						|
            FuncDef.Modifier += '*'
 | 
						|
            DeclText = DeclText.lstrip('*').strip()
 | 
						|
 | 
						|
        FuncDef.Declarator = FuncDef.Declarator.lstrip('*')
 | 
						|
        DeclSplitList = FuncDef.Declarator.split('(')
 | 
						|
        if len(DeclSplitList) < 2:
 | 
						|
            continue
 | 
						|
 | 
						|
        FuncName = DeclSplitList[0]
 | 
						|
        FuncNamePartList = FuncName.split()
 | 
						|
        if len(FuncNamePartList) > 1:
 | 
						|
            FuncName = FuncNamePartList[-1]
 | 
						|
            Index = 0
 | 
						|
            while Index < len(FuncNamePartList) - 1:
 | 
						|
                FuncDef.Modifier += ' ' + FuncNamePartList[Index]
 | 
						|
                Index += 1
 | 
						|
 | 
						|
        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, [])
 | 
						|
        FuncObjList.append(FuncObj)
 | 
						|
 | 
						|
    return FuncObjList
 | 
						|
 | 
						|
## CreateCCodeDB() method
 | 
						|
#
 | 
						|
#  Create database for all c code
 | 
						|
#
 | 
						|
#  @param FileNameList: A list of all c code file names
 | 
						|
#
 | 
						|
def CreateCCodeDB(FileNameList):
 | 
						|
    FileObjList = []
 | 
						|
    ParseErrorFileList = []
 | 
						|
    ParsedFiles = {}
 | 
						|
    for FullName in FileNameList:
 | 
						|
        if os.path.splitext(FullName)[1] in ('.h', '.c'):
 | 
						|
            if FullName.lower() in ParsedFiles:
 | 
						|
                continue
 | 
						|
            ParsedFiles[FullName.lower()] = 1
 | 
						|
            EdkLogger.info("Parsing " + FullName)
 | 
						|
            model = FullName.endswith('c') and DataClass.MODEL_FILE_C or DataClass.MODEL_FILE_H
 | 
						|
            collector = CodeFragmentCollector.CodeFragmentCollector(FullName)
 | 
						|
            try:
 | 
						|
                collector.ParseFile()
 | 
						|
            except:
 | 
						|
                ParseErrorFileList.append(FullName)
 | 
						|
            BaseName = os.path.basename(FullName)
 | 
						|
            DirName = os.path.dirname(FullName)
 | 
						|
            Ext = os.path.splitext(BaseName)[1].lstrip('.')
 | 
						|
            ModifiedTime = os.path.getmtime(FullName)
 | 
						|
            FileObj = DataClass.FileClass(-1, BaseName, Ext, DirName, FullName, model, ModifiedTime, GetFunctionList(), GetIdentifierList(), [])
 | 
						|
            FileObjList.append(FileObj)
 | 
						|
            collector.CleanFileProfileBuffer()
 | 
						|
 | 
						|
    if len(ParseErrorFileList) > 0:
 | 
						|
        EdkLogger.info("Found unrecoverable error during parsing:\n\t%s\n" % "\n\t".join(ParseErrorFileList))
 | 
						|
 | 
						|
    Db = EotGlobalData.gDb
 | 
						|
    for file in FileObjList:
 | 
						|
        Db.InsertOneFile(file)
 | 
						|
 | 
						|
    Db.UpdateIdentifierBelongsToFunction()
 | 
						|
 | 
						|
##
 | 
						|
#
 | 
						|
# This acts like the main() function for the script, unless it is 'import'ed into another
 | 
						|
# script.
 | 
						|
#
 | 
						|
if __name__ == '__main__':
 | 
						|
 | 
						|
    EdkLogger.Initialize()
 | 
						|
    EdkLogger.SetLevel(EdkLogger.QUIET)
 | 
						|
    CollectSourceCodeDataIntoDB(sys.argv[1])
 | 
						|
 | 
						|
    print('Done!')
 |