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

      2 # This file is used to define common parsing related functions used in parsing 

      3 # INF/DEC/DSC process

      4 #

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

      6 #

      7 # This program and the accompanying materials are licensed and made available 

      8 # under the terms and conditions of the BSD License which accompanies this 

      9 # distribution. The full text of the license may be found at 

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

     11 #

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

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

     14 #

     15 
     16 '''
     17 Parsing
     18 '''
     19 
     20 ##

     21 # Import Modules

     22 #

     23 import os.path
     24 import re
     25 
     26 from Library.String import RaiseParserError
     27 from Library.String import GetSplitValueList
     28 from Library.String import CheckFileType
     29 from Library.String import CheckFileExist
     30 from Library.String import CleanString
     31 from Library.String import NormPath
     32 
     33 from Logger.ToolError import FILE_NOT_FOUND
     34 from Logger.ToolError import FatalError
     35 from Logger.ToolError import FORMAT_INVALID
     36 
     37 from Library import DataType
     38 
     39 from Library.Misc import GuidStructureStringToGuidString
     40 from Library.Misc import CheckGuidRegFormat
     41 from Logger import StringTable as ST
     42 import Logger.Log as Logger
     43 
     44 from Parser.DecParser import Dec
     45 import GlobalData
     46 
     47 gPKG_INFO_DICT = {}
     48 
     49 ## GetBuildOption

     50 #

     51 # Parse a string with format "[<Family>:]<ToolFlag>=Flag"

     52 # Return (Family, ToolFlag, Flag)

     53 #

     54 # @param String:  String with BuildOption statement

     55 # @param File:    The file which defines build option, used in error report

     56 #

     57 def GetBuildOption(String, File, LineNo= -1):
     58     (Family, ToolChain, Flag) = ('', '', '')
     59     if String.find(DataType.TAB_EQUAL_SPLIT) < 0:
     60         RaiseParserError(String, 'BuildOptions', File, \
     61                          '[<Family>:]<ToolFlag>=Flag', LineNo)
     62     else:
     63         List = GetSplitValueList(String, DataType.TAB_EQUAL_SPLIT, MaxSplit=1)
     64         if List[0].find(':') > -1:
     65             Family = List[0][ : List[0].find(':')].strip()
     66             ToolChain = List[0][List[0].find(':') + 1 : ].strip()
     67         else:
     68             ToolChain = List[0].strip()
     69         Flag = List[1].strip()
     70     return (Family, ToolChain, Flag)
     71 
     72 ## Get Library Class

     73 #

     74 # Get Library of Dsc as <LibraryClassKeyWord>|<LibraryInstance>

     75 #

     76 # @param Item:           String as <LibraryClassKeyWord>|<LibraryInstance>

     77 # @param ContainerFile:  The file which describes the library class, used for 

     78 #                        error report

     79 #

     80 def GetLibraryClass(Item, ContainerFile, WorkspaceDir, LineNo= -1):
     81     List = GetSplitValueList(Item[0])
     82     SupMod = DataType.SUP_MODULE_LIST_STRING
     83     if len(List) != 2:
     84         RaiseParserError(Item[0], 'LibraryClasses', ContainerFile, \
     85                          '<LibraryClassKeyWord>|<LibraryInstance>')
     86     else:
     87         CheckFileType(List[1], '.Inf', ContainerFile, \
     88                       'library class instance', Item[0], LineNo)
     89         CheckFileExist(WorkspaceDir, List[1], ContainerFile, \
     90                        'LibraryClasses', Item[0], LineNo)
     91         if Item[1] != '':
     92             SupMod = Item[1]
     93 
     94     return (List[0], List[1], SupMod)
     95 
     96 ## Get Library Class

     97 #

     98 # Get Library of Dsc as <LibraryClassKeyWord>[|<LibraryInstance>]

     99 # [|<TokenSpaceGuidCName>.<PcdCName>]

    100 #

    101 # @param Item:           String as <LibraryClassKeyWord>|<LibraryInstance>

    102 # @param ContainerFile:  The file which describes the library class, used for 

    103 #                        error report

    104 #

    105 def GetLibraryClassOfInf(Item, ContainerFile, WorkspaceDir, LineNo= -1):
    106     ItemList = GetSplitValueList((Item[0] + DataType.TAB_VALUE_SPLIT * 2))
    107     SupMod = DataType.SUP_MODULE_LIST_STRING
    108 
    109     if len(ItemList) > 5:
    110         RaiseParserError\
    111         (Item[0], 'LibraryClasses', ContainerFile, \
    112          '<LibraryClassKeyWord>[|<LibraryInstance>]\
    113          [|<TokenSpaceGuidCName>.<PcdCName>]')
    114     else:
    115         CheckFileType(ItemList[1], '.Inf', ContainerFile, 'LibraryClasses', \
    116                       Item[0], LineNo)
    117         CheckFileExist(WorkspaceDir, ItemList[1], ContainerFile, \
    118                        'LibraryClasses', Item[0], LineNo)
    119         if ItemList[2] != '':
    120             CheckPcdTokenInfo(ItemList[2], 'LibraryClasses', \
    121                               ContainerFile, LineNo)
    122         if Item[1] != '':
    123             SupMod = Item[1]
    124 
    125     return (ItemList[0], ItemList[1], ItemList[2], SupMod)
    126 
    127 ## CheckPcdTokenInfo

    128 #

    129 # Check if PcdTokenInfo is following <TokenSpaceGuidCName>.<PcdCName>

    130 #

    131 # @param TokenInfoString:  String to be checked

    132 # @param Section:          Used for error report

    133 # @param File:             Used for error report

    134 #

    135 def CheckPcdTokenInfo(TokenInfoString, Section, File, LineNo= -1):
    136     Format = '<TokenSpaceGuidCName>.<PcdCName>'
    137     if TokenInfoString != '' and TokenInfoString != None:
    138         TokenInfoList = GetSplitValueList(TokenInfoString, DataType.TAB_SPLIT)
    139         if len(TokenInfoList) == 2:
    140             return True
    141 
    142     RaiseParserError(TokenInfoString, Section, File, Format, LineNo)
    143 
    144 ## Get Pcd

    145 #

    146 # Get Pcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|<Value>

    147 # [|<Type>|<MaximumDatumSize>]

    148 #

    149 # @param Item:           String as <PcdTokenSpaceGuidCName>.<TokenCName>|

    150 #                        <Value>[|<Type>|<MaximumDatumSize>]

    151 # @param ContainerFile:  The file which describes the pcd, used for error 

    152 #                        report

    153 
    154 #

    155 def GetPcd(Item, Type, ContainerFile, LineNo= -1):
    156     TokenGuid, TokenName, Value, MaximumDatumSize, Token = '', '', '', '', ''
    157     List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT * 2)
    158 
    159     if len(List) < 4 or len(List) > 6:
    160         RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \
    161                          '<PcdTokenSpaceGuidCName>.<TokenCName>|<Value>\
    162                          [|<Type>|<MaximumDatumSize>]', LineNo)
    163     else:
    164         Value = List[1]
    165         MaximumDatumSize = List[2]
    166         Token = List[3]
    167 
    168     if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):
    169         (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)
    170 
    171     return (TokenName, TokenGuid, Value, MaximumDatumSize, Token, Type)
    172 
    173 ## Get FeatureFlagPcd

    174 #

    175 # Get FeatureFlagPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE

    176 #

    177 # @param Item:           String as <PcdTokenSpaceGuidCName>

    178 #                        .<TokenCName>|TRUE/FALSE

    179 # @param ContainerFile:  The file which describes the pcd, used for error 

    180 #                        report

    181 #

    182 def GetFeatureFlagPcd(Item, Type, ContainerFile, LineNo= -1):
    183     TokenGuid, TokenName, Value = '', '', ''
    184     List = GetSplitValueList(Item)
    185     if len(List) != 2:
    186         RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \
    187                          '<PcdTokenSpaceGuidCName>.<TokenCName>|TRUE/FALSE', \
    188                          LineNo)
    189     else:
    190         Value = List[1]
    191     if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):
    192         (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)
    193 
    194     return (TokenName, TokenGuid, Value, Type)
    195 
    196 ## Get DynamicDefaultPcd

    197 #

    198 # Get DynamicDefaultPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>

    199 # |<Value>[|<DatumTyp>[|<MaxDatumSize>]]

    200 #

    201 # @param Item:           String as <PcdTokenSpaceGuidCName>.<TokenCName>|

    202 #                        TRUE/FALSE

    203 # @param ContainerFile:  The file which describes the pcd, used for error 

    204 #                        report

    205 #

    206 def GetDynamicDefaultPcd(Item, Type, ContainerFile, LineNo= -1):
    207     TokenGuid, TokenName, Value, DatumTyp, MaxDatumSize = '', '', '', '', ''
    208     List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT * 2)
    209     if len(List) < 4 or len(List) > 8:
    210         RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \
    211                          '<PcdTokenSpaceGuidCName>.<TokenCName>|<Value>\
    212                          [|<DatumTyp>[|<MaxDatumSize>]]', LineNo)
    213     else:
    214         Value = List[1]
    215         DatumTyp = List[2]
    216         MaxDatumSize = List[3]
    217     if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):
    218         (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)
    219 
    220     return (TokenName, TokenGuid, Value, DatumTyp, MaxDatumSize, Type)
    221 
    222 ## Get DynamicHiiPcd

    223 #

    224 # Get DynamicHiiPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|<String>|

    225 # <VariableGuidCName>|<VariableOffset>[|<DefaultValue>[|<MaximumDatumSize>]]

    226 #

    227 # @param Item:           String as <PcdTokenSpaceGuidCName>.<TokenCName>|

    228 #                        TRUE/FALSE

    229 # @param ContainerFile:  The file which describes the pcd, used for error 

    230 #                        report

    231 #

    232 def GetDynamicHiiPcd(Item, Type, ContainerFile, LineNo= -1):
    233     TokenGuid, TokenName, List1, List2, List3, List4, List5 = \
    234     '', '', '', '', '', '', ''
    235     List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT * 2)
    236     if len(List) < 6 or len(List) > 8:
    237         RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \
    238                          '<PcdTokenSpaceGuidCName>.<TokenCName>|<String>|\
    239                          <VariableGuidCName>|<VariableOffset>[|<DefaultValue>\
    240                          [|<MaximumDatumSize>]]', LineNo)
    241     else:
    242         List1, List2, List3, List4, List5 = \
    243         List[1], List[2], List[3], List[4], List[5]
    244     if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):
    245         (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)
    246 
    247     return (TokenName, TokenGuid, List1, List2, List3, List4, List5, Type)
    248 
    249 ## Get DynamicVpdPcd

    250 #

    251 # Get DynamicVpdPcd of Dsc as <PcdTokenSpaceGuidCName>.<TokenCName>|

    252 # <VpdOffset>[|<MaximumDatumSize>]

    253 #

    254 # @param Item:           String as <PcdTokenSpaceGuidCName>.<TokenCName>

    255 #                        |TRUE/FALSE

    256 # @param ContainerFile:  The file which describes the pcd, used for error 

    257 #                        report

    258 #

    259 def GetDynamicVpdPcd(Item, Type, ContainerFile, LineNo= -1):
    260     TokenGuid, TokenName, List1, List2 = '', '', '', ''
    261     List = GetSplitValueList(Item + DataType.TAB_VALUE_SPLIT)
    262     if len(List) < 3 or len(List) > 4:
    263         RaiseParserError(Item, 'Pcds' + Type, ContainerFile, \
    264                          '<PcdTokenSpaceGuidCName>.<TokenCName>|<VpdOffset>\
    265                          [|<MaximumDatumSize>]', LineNo)
    266     else:
    267         List1, List2 = List[1], List[2]
    268     if CheckPcdTokenInfo(List[0], 'Pcds' + Type, ContainerFile, LineNo):
    269         (TokenGuid, TokenName) = GetSplitValueList(List[0], DataType.TAB_SPLIT)
    270 
    271     return (TokenName, TokenGuid, List1, List2, Type)
    272 
    273 ## GetComponent

    274 #

    275 # Parse block of the components defined in dsc file

    276 # Set KeyValues as [ ['component name', [lib1, lib2, lib3], 

    277 # [bo1, bo2, bo3], [pcd1, pcd2, pcd3]], ...]

    278 #

    279 # @param Lines:             The content to be parsed

    280 # @param KeyValues:         To store data after parsing

    281 #

    282 def GetComponent(Lines, KeyValues):
    283     (FindBlock, FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
    284      FindPcdsPatchableInModule, FindPcdsFixedAtBuild, FindPcdsDynamic, \
    285      FindPcdsDynamicEx) = (False, False, False, False, False, False, False, \
    286                            False)
    287     ListItem = None
    288     LibraryClassItem = []
    289     BuildOption = []
    290     Pcd = []
    291 
    292     for Line in Lines:
    293         Line = Line[0]
    294         #

    295         # Ignore !include statement

    296         #

    297         if Line.upper().find(DataType.TAB_INCLUDE.upper() + ' ') > -1 or \
    298         Line.upper().find(DataType.TAB_DEFINE + ' ') > -1:
    299             continue
    300 
    301         if FindBlock == False:
    302             ListItem = Line
    303             #

    304             # find '{' at line tail

    305             #

    306             if Line.endswith('{'):
    307                 FindBlock = True
    308                 ListItem = CleanString(Line.rsplit('{', 1)[0], \
    309                                        DataType.TAB_COMMENT_SPLIT)
    310 
    311         #

    312         # Parse a block content

    313         #

    314         if FindBlock:
    315             if Line.find('<LibraryClasses>') != -1:
    316                 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
    317                  FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
    318                  FindPcdsDynamic, FindPcdsDynamicEx) = \
    319                  (True, False, False, False, False, False, False)
    320                 continue
    321             if Line.find('<BuildOptions>') != -1:
    322                 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
    323                  FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
    324                  FindPcdsDynamic, FindPcdsDynamicEx) = \
    325                  (False, True, False, False, False, False, False)
    326                 continue
    327             if Line.find('<PcdsFeatureFlag>') != -1:
    328                 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
    329                  FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
    330                  FindPcdsDynamic, FindPcdsDynamicEx) = \
    331                  (False, False, True, False, False, False, False)
    332                 continue
    333             if Line.find('<PcdsPatchableInModule>') != -1:
    334                 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
    335                  FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
    336                  FindPcdsDynamic, FindPcdsDynamicEx) = \
    337                  (False, False, False, True, False, False, False)
    338                 continue
    339             if Line.find('<PcdsFixedAtBuild>') != -1:
    340                 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
    341                  FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
    342                  FindPcdsDynamic, FindPcdsDynamicEx) = \
    343                  (False, False, False, False, True, False, False)
    344                 continue
    345             if Line.find('<PcdsDynamic>') != -1:
    346                 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
    347                  FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
    348                  FindPcdsDynamic, FindPcdsDynamicEx) = \
    349                  (False, False, False, False, False, True, False)
    350                 continue
    351             if Line.find('<PcdsDynamicEx>') != -1:
    352                 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
    353                  FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
    354                  FindPcdsDynamic, FindPcdsDynamicEx) = \
    355                  (False, False, False, False, False, False, True)
    356                 continue
    357             if Line.endswith('}'):
    358                 #

    359                 # find '}' at line tail

    360                 #

    361                 KeyValues.append([ListItem, LibraryClassItem, \
    362                                   BuildOption, Pcd])
    363                 (FindBlock, FindLibraryClass, FindBuildOption, \
    364                  FindPcdsFeatureFlag, FindPcdsPatchableInModule, \
    365                  FindPcdsFixedAtBuild, FindPcdsDynamic, FindPcdsDynamicEx) = \
    366                  (False, False, False, False, False, False, False, False)
    367                 LibraryClassItem, BuildOption, Pcd = [], [], []
    368                 continue
    369 
    370         if FindBlock:
    371             if FindLibraryClass:
    372                 LibraryClassItem.append(Line)
    373             elif FindBuildOption:
    374                 BuildOption.append(Line)
    375             elif FindPcdsFeatureFlag:
    376                 Pcd.append((DataType.TAB_PCDS_FEATURE_FLAG_NULL, Line))
    377             elif FindPcdsPatchableInModule:
    378                 Pcd.append((DataType.TAB_PCDS_PATCHABLE_IN_MODULE_NULL, Line))
    379             elif FindPcdsFixedAtBuild:
    380                 Pcd.append((DataType.TAB_PCDS_FIXED_AT_BUILD_NULL, Line))
    381             elif FindPcdsDynamic:
    382                 Pcd.append((DataType.TAB_PCDS_DYNAMIC_DEFAULT_NULL, Line))
    383             elif FindPcdsDynamicEx:
    384                 Pcd.append((DataType.TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL, Line))
    385         else:
    386             KeyValues.append([ListItem, [], [], []])
    387 
    388     return True
    389 
    390 ## GetExec

    391 #

    392 # Parse a string with format "InfFilename [EXEC = ExecFilename]"

    393 # Return (InfFilename, ExecFilename)

    394 #

    395 # @param String:  String with EXEC statement

    396 #

    397 def GetExec(String):
    398     InfFilename = ''
    399     ExecFilename = ''
    400     if String.find('EXEC') > -1:
    401         InfFilename = String[ : String.find('EXEC')].strip()
    402         ExecFilename = String[String.find('EXEC') + len('EXEC') : ].strip()
    403     else:
    404         InfFilename = String.strip()
    405 
    406     return (InfFilename, ExecFilename)
    407 
    408 ## GetComponents

    409 #

    410 # Parse block of the components defined in dsc file

    411 # Set KeyValues as [ ['component name', [lib1, lib2, lib3], [bo1, bo2, bo3], 

    412 # [pcd1, pcd2, pcd3]], ...]

    413 #

    414 # @param Lines:             The content to be parsed

    415 # @param Key:               Reserved

    416 # @param KeyValues:         To store data after parsing

    417 # @param CommentCharacter:  Comment char, used to ignore comment content

    418 #

    419 # @retval True Get component successfully

    420 #

    421 def GetComponents(Lines, KeyValues, CommentCharacter):
    422     if Lines.find(DataType.TAB_SECTION_END) > -1:
    423         Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1]
    424     (FindBlock, FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
    425      FindPcdsPatchableInModule, FindPcdsFixedAtBuild, FindPcdsDynamic, \
    426      FindPcdsDynamicEx) = \
    427      (False, False, False, False, False, False, False, False)
    428     ListItem = None
    429     LibraryClassItem = []
    430     BuildOption = []
    431     Pcd = []
    432 
    433     LineList = Lines.split('\n')
    434     for Line in LineList:
    435         Line = CleanString(Line, CommentCharacter)
    436         if Line == None or Line == '':
    437             continue
    438 
    439         if FindBlock == False:
    440             ListItem = Line
    441             #

    442             # find '{' at line tail

    443             #

    444             if Line.endswith('{'):
    445                 FindBlock = True
    446                 ListItem = CleanString(Line.rsplit('{', 1)[0], CommentCharacter)
    447 
    448         #

    449         # Parse a block content

    450         #

    451         if FindBlock:
    452             if Line.find('<LibraryClasses>') != -1:
    453                 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
    454                  FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
    455                  FindPcdsDynamic, FindPcdsDynamicEx) = \
    456                  (True, False, False, False, False, False, False)
    457                 continue
    458             if Line.find('<BuildOptions>') != -1:
    459                 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
    460                  FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
    461                  FindPcdsDynamic, FindPcdsDynamicEx) = \
    462                  (False, True, False, False, False, False, False)
    463                 continue
    464             if Line.find('<PcdsFeatureFlag>') != -1:
    465                 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
    466                  FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
    467                  FindPcdsDynamic, FindPcdsDynamicEx) = \
    468                  (False, False, True, False, False, False, False)
    469                 continue
    470             if Line.find('<PcdsPatchableInModule>') != -1:
    471                 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
    472                  FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
    473                  FindPcdsDynamic, FindPcdsDynamicEx) = \
    474                  (False, False, False, True, False, False, False)
    475                 continue
    476             if Line.find('<PcdsFixedAtBuild>') != -1:
    477                 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
    478                  FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
    479                  FindPcdsDynamic, FindPcdsDynamicEx) = \
    480                  (False, False, False, False, True, False, False)
    481                 continue
    482             if Line.find('<PcdsDynamic>') != -1:
    483                 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
    484                  FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
    485                  FindPcdsDynamic, FindPcdsDynamicEx) = \
    486                  (False, False, False, False, False, True, False)
    487                 continue
    488             if Line.find('<PcdsDynamicEx>') != -1:
    489                 (FindLibraryClass, FindBuildOption, FindPcdsFeatureFlag, \
    490                  FindPcdsPatchableInModule, FindPcdsFixedAtBuild, \
    491                  FindPcdsDynamic, FindPcdsDynamicEx) = \
    492                  (False, False, False, False, False, False, True)
    493                 continue
    494             if Line.endswith('}'):
    495                 #

    496                 # find '}' at line tail

    497                 #

    498                 KeyValues.append([ListItem, LibraryClassItem, BuildOption, \
    499                                   Pcd])
    500                 (FindBlock, FindLibraryClass, FindBuildOption, \
    501                  FindPcdsFeatureFlag, FindPcdsPatchableInModule, \
    502                  FindPcdsFixedAtBuild, FindPcdsDynamic, FindPcdsDynamicEx) = \
    503                  (False, False, False, False, False, False, False, False)
    504                 LibraryClassItem, BuildOption, Pcd = [], [], []
    505                 continue
    506 
    507         if FindBlock:
    508             if FindLibraryClass:
    509                 LibraryClassItem.append(Line)
    510             elif FindBuildOption:
    511                 BuildOption.append(Line)
    512             elif FindPcdsFeatureFlag:
    513                 Pcd.append((DataType.TAB_PCDS_FEATURE_FLAG, Line))
    514             elif FindPcdsPatchableInModule:
    515                 Pcd.append((DataType.TAB_PCDS_PATCHABLE_IN_MODULE, Line))
    516             elif FindPcdsFixedAtBuild:
    517                 Pcd.append((DataType.TAB_PCDS_FIXED_AT_BUILD, Line))
    518             elif FindPcdsDynamic:
    519                 Pcd.append((DataType.TAB_PCDS_DYNAMIC, Line))
    520             elif FindPcdsDynamicEx:
    521                 Pcd.append((DataType.TAB_PCDS_DYNAMIC_EX, Line))
    522         else:
    523             KeyValues.append([ListItem, [], [], []])
    524 
    525     return True
    526 
    527 ## Get Source

    528 #

    529 # Get Source of Inf as <Filename>[|<Family>[|<TagName>[|<ToolCode>

    530 # [|<PcdFeatureFlag>]]]]

    531 #

    532 # @param Item:           String as <Filename>[|<Family>[|<TagName>[|<ToolCode>

    533 #                        [|<PcdFeatureFlag>]]]]

    534 # @param ContainerFile:  The file which describes the library class, used 

    535 #                        for error report

    536 #

    537 def GetSource(Item, ContainerFile, FileRelativePath, LineNo= -1):
    538     ItemNew = Item + DataType.TAB_VALUE_SPLIT * 4
    539     List = GetSplitValueList(ItemNew)
    540     if len(List) < 5 or len(List) > 9:
    541         RaiseParserError(Item, 'Sources', ContainerFile, \
    542                          '<Filename>[|<Family>[|<TagName>[|<ToolCode>\
    543                          [|<PcdFeatureFlag>]]]]', LineNo)
    544     List[0] = NormPath(List[0])
    545     CheckFileExist(FileRelativePath, List[0], ContainerFile, 'Sources', \
    546                    Item, LineNo)
    547     if List[4] != '':
    548         CheckPcdTokenInfo(List[4], 'Sources', ContainerFile, LineNo)
    549 
    550     return (List[0], List[1], List[2], List[3], List[4])
    551 
    552 ## Get Binary

    553 #

    554 # Get Binary of Inf as <Filename>[|<Family>[|<TagName>[|<ToolCode>

    555 # [|<PcdFeatureFlag>]]]]

    556 #

    557 # @param Item:           String as <Filename>[|<Family>[|<TagName>

    558 #                        [|<ToolCode>[|<PcdFeatureFlag>]]]]

    559 # @param ContainerFile:  The file which describes the library class, 

    560 #                        used for error report

    561 #

    562 def GetBinary(Item, ContainerFile, LineNo= -1):
    563     ItemNew = Item + DataType.TAB_VALUE_SPLIT
    564     List = GetSplitValueList(ItemNew)
    565     if len(List) < 3 or len(List) > 5:
    566         RaiseParserError(Item, 'Binaries', ContainerFile, \
    567                          "<FileType>|<Filename>[|<Target>\
    568                          [|<TokenSpaceGuidCName>.<PcdCName>]]", LineNo)
    569 
    570     if len(List) >= 4:
    571         if List[3] != '':
    572             CheckPcdTokenInfo(List[3], 'Binaries', ContainerFile, LineNo)
    573         return (List[0], List[1], List[2], List[3])
    574     elif len(List) == 3:
    575         return (List[0], List[1], List[2], '')
    576 
    577 ## Get Guids/Protocols/Ppis

    578 #

    579 # Get Guids/Protocols/Ppis of Inf as <GuidCName>[|<PcdFeatureFlag>]

    580 #

    581 # @param Item:           String as <GuidCName>[|<PcdFeatureFlag>]

    582 # @param Type:           Type of parsing string

    583 # @param ContainerFile:  The file which describes the library class, 

    584 #                        used for error report

    585 #

    586 def GetGuidsProtocolsPpisOfInf(Item):
    587     ItemNew = Item + DataType.TAB_VALUE_SPLIT
    588     List = GetSplitValueList(ItemNew)
    589     return (List[0], List[1])
    590 
    591 ## Get Guids/Protocols/Ppis

    592 #

    593 # Get Guids/Protocols/Ppis of Dec as <GuidCName>=<GuidValue>

    594 #

    595 # @param Item:           String as <GuidCName>=<GuidValue>

    596 # @param Type:           Type of parsing string

    597 # @param ContainerFile:  The file which describes the library class, 

    598 # used for error report

    599 #

    600 def GetGuidsProtocolsPpisOfDec(Item, Type, ContainerFile, LineNo= -1):
    601     List = GetSplitValueList(Item, DataType.TAB_EQUAL_SPLIT)
    602     if len(List) != 2:
    603         RaiseParserError(Item, Type, ContainerFile, '<CName>=<GuidValue>', \
    604                          LineNo)
    605     #

    606     #convert C-Format Guid to Register Format

    607     #

    608     if List[1][0] == '{' and List[1][-1] == '}':
    609         RegisterFormatGuid = GuidStructureStringToGuidString(List[1])
    610         if RegisterFormatGuid == '':
    611             RaiseParserError(Item, Type, ContainerFile, \
    612                              'CFormat or RegisterFormat', LineNo)
    613     else:
    614         if CheckGuidRegFormat(List[1]):
    615             RegisterFormatGuid = List[1]
    616         else:
    617             RaiseParserError(Item, Type, ContainerFile, \
    618                              'CFormat or RegisterFormat', LineNo)
    619 
    620     return (List[0], RegisterFormatGuid)
    621 
    622 ## GetPackage

    623 #

    624 # Get Package of Inf as <PackagePath>[|<PcdFeatureFlag>]

    625 #

    626 # @param Item:           String as <PackagePath>[|<PcdFeatureFlag>]

    627 # @param Type:           Type of parsing string

    628 # @param ContainerFile:  The file which describes the library class, 

    629 #                        used for error report

    630 #

    631 def GetPackage(Item, ContainerFile, FileRelativePath, LineNo= -1):
    632     ItemNew = Item + DataType.TAB_VALUE_SPLIT
    633     List = GetSplitValueList(ItemNew)
    634     CheckFileType(List[0], '.Dec', ContainerFile, 'package', List[0], LineNo)
    635     CheckFileExist(FileRelativePath, List[0], ContainerFile, 'Packages', \
    636                    List[0], LineNo)
    637     if List[1] != '':
    638         CheckPcdTokenInfo(List[1], 'Packages', ContainerFile, LineNo)
    639 
    640     return (List[0], List[1])
    641 
    642 ## Get Pcd Values of Inf

    643 #

    644 # Get Pcd of Inf as <TokenSpaceGuidCName>.<PcdCName>[|<Value>]

    645 #

    646 # @param Item:  The string describes pcd

    647 # @param Type:  The type of Pcd

    648 # @param File:  The file which describes the pcd, used for error report

    649 #

    650 def GetPcdOfInf(Item, Type, File, LineNo):
    651     Format = '<TokenSpaceGuidCName>.<PcdCName>[|<Value>]'
    652     TokenGuid, TokenName, Value, InfType = '', '', '', ''
    653 
    654     if Type == DataType.TAB_PCDS_FIXED_AT_BUILD:
    655         InfType = DataType.TAB_INF_FIXED_PCD
    656     elif Type == DataType.TAB_PCDS_PATCHABLE_IN_MODULE:
    657         InfType = DataType.TAB_INF_PATCH_PCD
    658     elif Type == DataType.TAB_PCDS_FEATURE_FLAG:
    659         InfType = DataType.TAB_INF_FEATURE_PCD
    660     elif Type == DataType.TAB_PCDS_DYNAMIC_EX:
    661         InfType = DataType.TAB_INF_PCD_EX
    662     elif Type == DataType.TAB_PCDS_DYNAMIC:
    663         InfType = DataType.TAB_INF_PCD
    664     List = GetSplitValueList(Item, DataType.TAB_VALUE_SPLIT, 1)
    665     TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT)
    666     if len(TokenInfo) != 2:
    667         RaiseParserError(Item, InfType, File, Format, LineNo)
    668     else:
    669         TokenGuid = TokenInfo[0]
    670         TokenName = TokenInfo[1]
    671 
    672     if len(List) > 1:
    673         Value = List[1]
    674     else:
    675         Value = None
    676     return (TokenGuid, TokenName, Value, InfType)
    677 
    678 
    679 ## Get Pcd Values of Dec

    680 #

    681 # Get Pcd of Dec as <TokenSpcCName>.<TokenCName>|<Value>|<DatumType>|<Token>

    682 # @param Item:  Pcd item

    683 # @param Type:  Pcd type

    684 # @param File:  Dec file

    685 # @param LineNo:  Line number

    686 #

    687 def GetPcdOfDec(Item, Type, File, LineNo= -1):
    688     Format = '<TokenSpaceGuidCName>.<PcdCName>|<Value>|<DatumType>|<Token>'
    689     TokenGuid, TokenName, Value, DatumType, Token = '', '', '', '', ''
    690     List = GetSplitValueList(Item)
    691     if len(List) != 4:
    692         RaiseParserError(Item, 'Pcds' + Type, File, Format, LineNo)
    693     else:
    694         Value = List[1]
    695         DatumType = List[2]
    696         Token = List[3]
    697     TokenInfo = GetSplitValueList(List[0], DataType.TAB_SPLIT)
    698     if len(TokenInfo) != 2:
    699         RaiseParserError(Item, 'Pcds' + Type, File, Format, LineNo)
    700     else:
    701         TokenGuid = TokenInfo[0]
    702         TokenName = TokenInfo[1]
    703 
    704     return (TokenGuid, TokenName, Value, DatumType, Token, Type)
    705 
    706 ## Parse DEFINE statement

    707 #

    708 # Get DEFINE macros

    709 #

    710 # @param LineValue:  A DEFINE line value

    711 # @param StartLine:  A DEFINE start line

    712 # @param Table:      A table

    713 # @param FileID:     File ID

    714 # @param Filename:   File name

    715 # @param SectionName:  DEFINE section name

    716 # @param SectionModel:  DEFINE section model

    717 # @param Arch:   DEFINE arch

    718 #

    719 def ParseDefine(LineValue, StartLine, Table, FileID, SectionName, \
    720                 SectionModel, Arch):
    721     Logger.Debug(Logger.DEBUG_2, ST.MSG_DEFINE_STATEMENT_FOUND % (LineValue, \
    722                                                                   SectionName))
    723     Define = \
    724     GetSplitValueList(CleanString\
    725                       (LineValue[LineValue.upper().\
    726                                  find(DataType.TAB_DEFINE.upper() + ' ') + \
    727                                  len(DataType.TAB_DEFINE + ' ') : ]), \
    728                                  DataType.TAB_EQUAL_SPLIT, 1)
    729     Table.Insert(DataType.MODEL_META_DATA_DEFINE, Define[0], Define[1], '', \
    730                  '', '', Arch, SectionModel, FileID, StartLine, -1, \
    731                  StartLine, -1, 0)
    732 
    733 ## InsertSectionItems

    734 #

    735 # Insert item data of a section to a dict

    736 #

    737 # @param Model:   A model

    738 # @param CurrentSection:   Current section

    739 # @param SectionItemList:   Section item list

    740 # @param ArchList:   Arch list

    741 # @param ThirdList:   Third list

    742 # @param RecordSet:   Record set

    743 #

    744 def InsertSectionItems(Model, SectionItemList, ArchList, \
    745                        ThirdList, RecordSet):
    746     #

    747     # Insert each item data of a section

    748     #

    749     for Index in range(0, len(ArchList)):
    750         Arch = ArchList[Index]
    751         Third = ThirdList[Index]
    752         if Arch == '':
    753             Arch = DataType.TAB_ARCH_COMMON
    754 
    755         Records = RecordSet[Model]
    756         for SectionItem in SectionItemList:
    757             LineValue, StartLine, Comment = SectionItem[0], \
    758             SectionItem[1], SectionItem[2]
    759 
    760             Logger.Debug(4, ST.MSG_PARSING % LineValue)
    761             #

    762             # And then parse DEFINE statement

    763             #

    764             if LineValue.upper().find(DataType.TAB_DEFINE.upper() + ' ') > -1:
    765                 continue
    766             #

    767             # At last parse other sections

    768             #

    769             IdNum = -1
    770             Records.append([LineValue, Arch, StartLine, IdNum, Third, Comment])
    771 
    772         if RecordSet != {}:
    773             RecordSet[Model] = Records
    774 
    775 ## GenMetaDatSectionItem

    776 #

    777 # @param Key:    A key

    778 # @param Value:  A value

    779 # @param List:   A list

    780 #

    781 def GenMetaDatSectionItem(Key, Value, List):
    782     if Key not in List:
    783         List[Key] = [Value]
    784     else:
    785         List[Key].append(Value)
    786 
    787 ## GetPkgInfoFromDec

    788 #

    789 # get package name, guid, version info from dec files

    790 #

    791 # @param Path:   File path

    792 #

    793 def GetPkgInfoFromDec(Path):
    794     PkgName = None
    795     PkgGuid = None
    796     PkgVersion = None
    797 
    798     Path = Path.replace('\\', '/')
    799 
    800     if not os.path.exists(Path):
    801         Logger.Error("\nUPT", FILE_NOT_FOUND, File=Path)
    802 
    803     if Path in gPKG_INFO_DICT:
    804         return gPKG_INFO_DICT[Path]
    805 
    806     try:
    807         DecParser = None
    808         if Path not in GlobalData.gPackageDict:
    809             DecParser = Dec(Path)
    810             GlobalData.gPackageDict[Path] = DecParser
    811         else:
    812             DecParser = GlobalData.gPackageDict[Path]
    813 
    814         PkgName = DecParser.GetPackageName()
    815         PkgGuid = DecParser.GetPackageGuid()
    816         PkgVersion = DecParser.GetPackageVersion()
    817         gPKG_INFO_DICT[Path] = (PkgName, PkgGuid, PkgVersion)
    818         return PkgName, PkgGuid, PkgVersion
    819     except FatalError:
    820         return None, None, None
    821 
    822 
    823 ## GetWorkspacePackage
    824 #
    825 # Get a list of workspace package information.
    826 #
    827 def GetWorkspacePackage():
    828     DecFileList = []
    829     WorkspaceDir = GlobalData.gWORKSPACE
    830     PackageDir = GlobalData.gPACKAGE_PATH
    831     for PkgRoot in [WorkspaceDir] + PackageDir:
    832         for Root, Dirs, Files in os.walk(PkgRoot):
    833             if 'CVS' in Dirs:
    834                 Dirs.remove('CVS')
    835             if '.svn' in Dirs:
    836                 Dirs.remove('.svn')
    837             for Dir in Dirs:
    838                 if Dir.startswith('.'):
    839                     Dirs.remove(Dir)
    840             for FileSp in Files:
    841                 if FileSp.startswith('.'):
    842                     continue
    843                 Ext = os.path.splitext(FileSp)[1]
    844                 if Ext.lower() in ['.dec']:
    845                     DecFileList.append\
    846                     (os.path.normpath(os.path.join(Root, FileSp)))
    847     #
    848     # abstract package guid, version info from DecFile List
    849     #
    850     PkgList = []
    851     for DecFile in DecFileList:
    852         (PkgName, PkgGuid, PkgVersion) = GetPkgInfoFromDec(DecFile)
    853         if PkgName and PkgGuid and PkgVersion:
    854             PkgList.append((PkgName, PkgGuid, PkgVersion, DecFile))
    855 
    856     return PkgList
    857 
    858 ## GetWorkspaceModule
    859 #
    860 # Get a list of workspace modules.
    861 #
    862 def GetWorkspaceModule():
    863     InfFileList = []
    864     WorkspaceDir = GlobalData.gWORKSPACE
    865     for Root, Dirs, Files in os.walk(WorkspaceDir):
    866         if 'CVS' in Dirs:
    867             Dirs.remove('CVS')
    868         if '.svn' in Dirs:
    869             Dirs.remove('.svn')
    870         if 'Build' in Dirs:
    871             Dirs.remove('Build')
    872         for Dir in Dirs:
    873             if Dir.startswith('.'):
    874                 Dirs.remove(Dir)
    875         for FileSp in Files:
    876             if FileSp.startswith('.'):
    877                 continue
    878             Ext = os.path.splitext(FileSp)[1]
    879             if Ext.lower() in ['.inf']:
    880                 InfFileList.append\
    881                 (os.path.normpath(os.path.join(Root, FileSp)))
    882 
    883     return InfFileList
    884 
    885 ## MacroParser used to parse macro definition
    886 #
    887 # @param Line:            The content contain linestring and line number
    888 # @param FileName:        The meta-file file name
    889 # @param SectionType:     Section for the Line belong to
    890 # @param FileLocalMacros: A list contain Macro defined in [Defines] section.
    891 #
    892 def MacroParser(Line, FileName, SectionType, FileLocalMacros):
    893     MacroDefPattern = re.compile("^(DEFINE)[ \t]+")
    894     LineContent = Line[0]
    895     LineNo = Line[1]
    896     Match = MacroDefPattern.match(LineContent)
    897     if not Match:
    898         #
    899         # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
    900         #
    901         return None, None
    902 
    903     TokenList = GetSplitValueList(LineContent[Match.end(1):], \
    904                                   DataType.TAB_EQUAL_SPLIT, 1)
    905     #
    906     # Syntax check
    907     #
    908     if not TokenList[0]:
    909         Logger.Error('Parser', FORMAT_INVALID, ST.ERR_MACRONAME_NOGIVEN,
    910                         ExtraData=LineContent, File=FileName, Line=LineNo)
    911     if len(TokenList) < 2:
    912         Logger.Error('Parser', FORMAT_INVALID, ST.ERR_MACROVALUE_NOGIVEN,
    913                         ExtraData=LineContent, File=FileName, Line=LineNo)
    914 
    915     Name, Value = TokenList
    916 
    917     #
    918     # DEFINE defined macros
    919     #
    920     if SectionType == DataType.MODEL_META_DATA_HEADER:
    921         FileLocalMacros[Name] = Value
    922 
    923     ReIsValidMacroName = re.compile(r"^[A-Z][A-Z0-9_]*$", re.DOTALL)
    924     if ReIsValidMacroName.match(Name) == None:
    925         Logger.Error('Parser',
    926                      FORMAT_INVALID,
    927                      ST.ERR_MACRONAME_INVALID % (Name),
    928                      ExtraData=LineContent,
    929                      File=FileName,
    930                      Line=LineNo)
    931 
    932     # Validate MACRO Value
    933     #
    934     # <MacroDefinition> ::=  [<Comments>]{0,}
    935     #                       "DEFINE" <MACRO> "=" [{<PATH>} {<VALUE>}] <EOL>
    936     # <Value>           ::=  {<NumVal>} {<Boolean>} {<AsciiString>} {<GUID>}
    937     #                        {<CString>} {<UnicodeString>} {<CArray>}
    938     #
    939     # The definition of <NumVal>, <PATH>, <Boolean>, <GUID>, <CString>, 
    940     # <UnicodeString>, <CArray> are subset of <AsciiString>.
    941     #
    942     ReIsValidMacroValue = re.compile(r"^[\x20-\x7e]*$", re.DOTALL)
    943     if ReIsValidMacroValue.match(Value) == None:
    944         Logger.Error('Parser',
    945                      FORMAT_INVALID,
    946                      ST.ERR_MACROVALUE_INVALID % (Value),
    947                      ExtraData=LineContent,
    948                      File=FileName,
    949                      Line=LineNo)
    950 
    951     return Name, Value
    952 
    953 ## GenSection 
    954 #
    955 # generate section contents
    956 #
    957 # @param  SectionName:  indicate the name of the section, details refer to 
    958 #                       INF, DEC specs
    959 # @param  SectionDict:  section statement dict, key is SectionAttrs(arch, 
    960 #                       moduletype or platform may exist as needed) list 
    961 #                       seperated by space, 
    962 #                       value is statement
    963 #
    964 def GenSection(SectionName, SectionDict, SplitArch=True, NeedBlankLine=False):
    965     Content = ''
    966     for SectionAttrs in SectionDict:
    967         StatementList = SectionDict[SectionAttrs]
    968         if SectionAttrs and SectionName != 'Defines' and SectionAttrs.strip().upper() != DataType.TAB_ARCH_COMMON:
    969             if SplitArch:
    970                 ArchList = GetSplitValueList(SectionAttrs, DataType.TAB_SPACE_SPLIT)
    971             else:
    972                 if SectionName != 'UserExtensions':
    973                     ArchList = GetSplitValueList(SectionAttrs, DataType.TAB_COMMENT_SPLIT)
    974                 else:
    975                     ArchList = [SectionAttrs]
    976             for Index in xrange(0, len(ArchList)):
    977                 ArchList[Index] = ConvertArchForInstall(ArchList[Index])
    978             Section = '[' + SectionName + '.' + (', ' + SectionName + '.').join(ArchList) + ']'
    979         else:
    980             Section = '[' + SectionName + ']'
    981         Content += '\n' + Section + '\n'
    982         if StatementList != None:
    983             for Statement in StatementList:
    984                 LineList = Statement.split('\n')
    985                 NewStatement = ""
    986                 for Line in LineList:
    987                     # ignore blank comment
    988                     if not Line.replace("#", '').strip() and SectionName not in ('Defines', 'Hob', 'Event', 'BootMode'):
    989                         continue
    990                     # add two space before non-comments line except the comments in Defines section
    991                     if Line.strip().startswith('#') and SectionName == 'Defines':

    992                         NewStatement += "%s\n" % Line
    993                         continue
    994                     NewStatement += "  %s\n" % Line
    995                 if NeedBlankLine:
    996                     Content += NewStatement + '\n'
    997                 else:
    998                     Content += NewStatement
    999 
   1000         if NeedBlankLine:
   1001             Content = Content[:-1]
   1002     if not Content.replace('\\n', '').strip():
   1003         return ''
   1004     return Content
   1005 
   1006 ## ConvertArchForInstall

   1007 # if Arch.upper() is in "IA32", "X64", "IPF", and "EBC", it must be upper case.  "common" must be lower case.  

   1008 # Anything else, the case must be preserved

   1009 #

   1010 # @param Arch: the arch string that need to be converted, it should be stripped before pass in 

   1011 # @return: the arch string that get converted

   1012 #

   1013 def ConvertArchForInstall(Arch):
   1014     if Arch.upper() in [DataType.TAB_ARCH_IA32, DataType.TAB_ARCH_X64,
   1015                                    DataType.TAB_ARCH_IPF, DataType.TAB_ARCH_EBC]:
   1016         Arch = Arch.upper()
   1017     elif Arch.upper() == DataType.TAB_ARCH_COMMON:
   1018         Arch = Arch.lower()
   1019 
   1020     return Arch
   1021