2 # This file contained the parser for INF file
4 # Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
6 # This program and the accompanying materials are licensed and made available
7 # under the terms and conditions of the BSD License which accompanies this
8 # distribution. The full text of the license may be found at
9 # http://opensource.org/licenses/bsd-license.php
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.
24 from copy
import deepcopy
26 from Library
.String
import GetSplitValueList
27 from Library
.String
import ConvertSpecialChar
28 from Library
.Misc
import ProcessLineExtender
29 from Library
.Parsing
import NormPath
30 from Library
.ParserValidate
import IsValidInfMoudleTypeList
31 from Library
.ParserValidate
import IsValidArch
32 from Library
import DataType
as DT
33 from Library
import GlobalData
35 import Logger
.Log
as Logger
36 from Logger
import StringTable
as ST
37 from Logger
.ToolError
import FORMAT_INVALID
38 from Logger
.ToolError
import FILE_READ_FAILURE
39 from Logger
.ToolError
import PARSER_ERROR
41 from Object
.Parser
.InfCommonObject
import InfSectionCommonDef
42 from Parser
.InfSectionParser
import InfSectionParser
43 from Parser
.InfParserMisc
import gINF_SECTION_DEF
44 from Parser
.InfParserMisc
import IsBinaryInf
49 def OpenInfFile(Filename
):
53 FInputfile
= open(Filename
, "rb", 0)
55 FileLinesList
= FInputfile
.readlines()
57 Logger
.Error("InfParser",
59 ST
.ERR_FILE_OPEN_FAILURE
,
64 Logger
.Error("InfParser",
66 ST
.ERR_FILE_OPEN_FAILURE
,
73 # This class defined the structure used in InfParser object
75 # @param InfObject: Inherited from InfSectionParser class
76 # @param Filename: Input value for Filename of INF file, default is
78 # @param WorkspaceDir: Input value for current workspace directory,
81 class InfParser(InfSectionParser
):
83 def __init__(self
, Filename
= None, WorkspaceDir
= None):
86 # Call parent class construct function
88 super(InfParser
, self
).__init
__()
90 self
.WorkspaceDir
= WorkspaceDir
91 self
.SupArchList
= DT
.ARCH_LIST
94 self
.BootModeList
= []
97 # Load Inf file if filename is not None
100 self
.ParseInfFile(Filename
)
104 # Parse the file if it exists
106 # @param Filename: Input value for filename of INF file
108 def ParseInfFile(self
, Filename
):
110 Filename
= NormPath(Filename
)
111 (Path
, Name
) = os
.path
.split(Filename
)
112 self
.FullPath
= Filename
115 GlobalData
.gINF_MODULE_DIR
= Path
116 GlobalData
.gINF_MODULE_NAME
= self
.FullPath
117 GlobalData
.gIS_BINARY_INF
= False
119 # Initialize common data
122 CurrentSection
= DT
.MODEL_UNKNOWN
128 HeaderCommentStart
= False
129 HeaderCommentEnd
= False
132 # While Section ends. parse whole section contents.
134 NewSectionStartFlag
= False
135 FirstSectionStartFlag
= False
143 # Variables for Event/Hob/BootMode
147 self
.BootModeList
= []
150 FileLinesList
= OpenInfFile (Filename
)
153 # One INF file can only has one [Defines] section.
155 DefineSectionParsedFlag
= False
158 # Convert special characters in lines to space character.
160 FileLinesList
= ConvertSpecialChar(FileLinesList
)
163 # Process Line Extender
165 FileLinesList
= ProcessLineExtender(FileLinesList
)
168 # Judge whether the INF file is Binary INF or not
170 if IsBinaryInf(FileLinesList
):
171 GlobalData
.gIS_BINARY_INF
= True
173 InfSectionCommonDefObj
= None
175 for Line
in FileLinesList
:
178 if (LineNo
< len(FileLinesList
) - 1):
179 NextLine
= FileLinesList
[LineNo
].strip()
184 if (Line
== '' or not Line
) and LineNo
== len(FileLinesList
):
185 LastSectionFalg
= True
188 # check whether file header comment section started
190 if Line
.startswith(DT
.TAB_SPECIAL_COMMENT
) and \
191 (Line
.find(DT
.TAB_HEADER_COMMENT
) > -1) and \
192 not HeaderCommentStart
:
193 if CurrentSection
!= DT
.MODEL_UNKNOWN
:
194 Logger
.Error("Parser",
196 ST
.ERR_INF_PARSER_HEADER_FILE
,
199 RaiseError
= Logger
.IS_RAISE_ERROR
)
201 CurrentSection
= DT
.MODEL_META_DATA_FILE_HEADER
203 # Append the first line to section lines.
205 SectionLines
.append((Line
, LineNo
))
206 HeaderCommentStart
= True
210 # Collect Header content.
212 if (Line
.startswith(DT
.TAB_COMMENT_SPLIT
) and CurrentSection
== DT
.MODEL_META_DATA_FILE_HEADER
) and\
213 HeaderCommentStart
and not Line
.startswith(DT
.TAB_SPECIAL_COMMENT
) and not\
214 HeaderCommentEnd
and NextLine
!= '':
215 SectionLines
.append((Line
, LineNo
))
220 if (Line
.startswith(DT
.TAB_SPECIAL_COMMENT
) or not Line
.strip().startswith("#")) and HeaderCommentStart \
221 and not HeaderCommentEnd
:
222 SectionLines
.append((Line
, LineNo
))
223 HeaderCommentStart
= False
225 # Call Header comment parser.
227 self
.InfHeaderParser(SectionLines
, self
.InfHeader
, self
.FileName
)
229 HeaderCommentEnd
= True
233 # Find a new section tab
234 # Or at the last line of INF file,
235 # need to process the last section.
237 LastSectionFalg
= False
238 if LineNo
== len(FileLinesList
):
239 LastSectionFalg
= True
241 if Line
.startswith(DT
.TAB_COMMENT_SPLIT
) and not Line
.startswith(DT
.TAB_SPECIAL_COMMENT
):
242 SectionLines
.append((Line
, LineNo
))
243 if not LastSectionFalg
:
247 # Encountered a section. start with '[' and end with ']'
249 if (Line
.startswith(DT
.TAB_SECTION_START
) and \
250 Line
.find(DT
.TAB_SECTION_END
) > -1) or LastSectionFalg
:
251 if not LastSectionFalg
:
253 # check to prevent '#' inside section header
255 HeaderContent
= Line
[1:Line
.find(DT
.TAB_SECTION_END
)]
256 if HeaderContent
.find(DT
.TAB_COMMENT_SPLIT
) != -1:
257 Logger
.Error("InfParser",
259 ST
.ERR_INF_PARSER_DEFINE_SECTION_HEADER_INVALID
,
265 # Keep last time section header content for section parser
268 self
.LastSectionHeaderContent
= deepcopy(self
.SectionHeaderContent
)
271 # TailComments in section define.
274 CommentIndex
= Line
.find(DT
.TAB_COMMENT_SPLIT
)
275 if CommentIndex
> -1:
276 TailComments
= Line
[CommentIndex
:]
277 Line
= Line
[:CommentIndex
]
279 InfSectionCommonDefObj
= InfSectionCommonDef()
280 if TailComments
!= '':
281 InfSectionCommonDefObj
.SetTailComments(TailComments
)
282 if CommentBlock
!= '':
283 InfSectionCommonDefObj
.SetHeaderComments(CommentBlock
)
286 # Call section parser before section header parer to avoid encounter EDKI INF file
288 if CurrentSection
== DT
.MODEL_META_DATA_DEFINE
:
289 DefineSectionParsedFlag
= self
._CallSectionParsers
(CurrentSection
,
290 DefineSectionParsedFlag
, SectionLines
,
291 InfSectionCommonDefObj
, LineNo
)
293 # Compare the new section name with current
295 self
.SectionHeaderParser(Line
, self
.FileName
, LineNo
)
297 self
._CheckSectionHeaders
(Line
, LineNo
)
299 SectionType
= _ConvertSecNameToType(self
.SectionHeaderContent
[0][0])
301 if not FirstSectionStartFlag
:
302 CurrentSection
= SectionType
303 FirstSectionStartFlag
= True
305 NewSectionStartFlag
= True
307 SectionLines
.append((Line
, LineNo
))
311 SectionLines
, CurrentSection
= self
._ProcessLastSection
(SectionLines
, Line
, LineNo
, CurrentSection
)
314 # End of section content collect.
315 # Parser the section content collected previously.
317 if NewSectionStartFlag
or LastSectionFalg
:
318 if CurrentSection
!= DT
.MODEL_META_DATA_DEFINE
or \
319 (LastSectionFalg
and CurrentSection
== DT
.MODEL_META_DATA_DEFINE
):
320 DefineSectionParsedFlag
= self
._CallSectionParsers
(CurrentSection
,
321 DefineSectionParsedFlag
, SectionLines
,
322 InfSectionCommonDefObj
, LineNo
)
324 CurrentSection
= SectionType
326 # Clear section lines
333 # Found the first section, No file header.
335 if not DefineSectionParsedFlag
:
336 Logger
.Error("InfParser",
338 ST
.ERR_INF_PARSER_HEADER_MISSGING
,
342 # extract [Event] [Hob] [BootMode] sections
344 self
._ExtractEventHobBootMod
(FileLinesList
)
346 ## _CheckSectionHeaders
349 def _CheckSectionHeaders(self
, Line
, LineNo
):
350 if len(self
.SectionHeaderContent
) == 0:
351 Logger
.Error("InfParser",
353 ST
.ERR_INF_PARSER_DEFINE_SECTION_HEADER_INVALID
,
355 Line
=LineNo
, ExtraData
=Line
)
357 for SectionItem
in self
.SectionHeaderContent
:
360 # Not cover Depex/UserExtension section header
363 if SectionItem
[0].strip().upper() == DT
.TAB_INF_FIXED_PCD
.upper() or \
364 SectionItem
[0].strip().upper() == DT
.TAB_INF_PATCH_PCD
.upper() or \
365 SectionItem
[0].strip().upper() == DT
.TAB_INF_PCD_EX
.upper() or \
366 SectionItem
[0].strip().upper() == DT
.TAB_INF_PCD
.upper() or \
367 SectionItem
[0].strip().upper() == DT
.TAB_INF_FEATURE_PCD
.upper():
368 ArchList
= GetSplitValueList(SectionItem
[1].strip(), ' ')
370 ArchList
= [SectionItem
[1].strip()]
372 for Arch
in ArchList
:
373 if (not IsValidArch(Arch
)) and \
374 (SectionItem
[0].strip().upper() != DT
.TAB_DEPEX
.upper()) and \
375 (SectionItem
[0].strip().upper() != DT
.TAB_USER_EXTENSIONS
.upper()) and \
376 (SectionItem
[0].strip().upper() != DT
.TAB_COMMON_DEFINES
.upper()):
377 Logger
.Error("InfParser",
379 ST
.ERR_INF_PARSER_DEFINE_FROMAT_INVALID
%(SectionItem
[1]),
381 Line
=LineNo
, ExtraData
=Line
)
383 # Check if the ModuleType is valid
385 ChkModSectionList
= ['LIBRARYCLASSES']
386 if (self
.SectionHeaderContent
[0][0].upper() in ChkModSectionList
):
387 if SectionItem
[2].strip().upper():
388 MoudleTypeList
= GetSplitValueList(
389 SectionItem
[2].strip().upper())
390 if (not IsValidInfMoudleTypeList(MoudleTypeList
)):
391 Logger
.Error("InfParser",
393 ST
.ERR_INF_PARSER_DEFINE_FROMAT_INVALID
%(SectionItem
[2]),
394 File
=self
.FullPath
, Line
=LineNo
,
397 ## _CallSectionParsers
400 def _CallSectionParsers(self
, CurrentSection
, DefineSectionParsedFlag
,
401 SectionLines
, InfSectionCommonDefObj
, LineNo
):
402 if CurrentSection
== DT
.MODEL_META_DATA_DEFINE
:
403 if not DefineSectionParsedFlag
:
404 self
.InfDefineParser(SectionLines
,
407 InfSectionCommonDefObj
)
408 DefineSectionParsedFlag
= True
410 Logger
.Error("Parser",
412 ST
.ERR_INF_PARSER_MULTI_DEFINE_SECTION
,
414 RaiseError
= Logger
.IS_RAISE_ERROR
)
416 elif CurrentSection
== DT
.MODEL_META_DATA_BUILD_OPTION
:
417 self
.InfBuildOptionParser(SectionLines
,
418 self
.InfBuildOptionSection
,
421 elif CurrentSection
== DT
.MODEL_EFI_LIBRARY_CLASS
:
422 self
.InfLibraryParser(SectionLines
,
423 self
.InfLibraryClassSection
,
426 elif CurrentSection
== DT
.MODEL_META_DATA_PACKAGE
:
427 self
.InfPackageParser(SectionLines
,
428 self
.InfPackageSection
,
431 # [Pcd] Sections, put it together
433 elif CurrentSection
== DT
.MODEL_PCD_FIXED_AT_BUILD
or \
434 CurrentSection
== DT
.MODEL_PCD_PATCHABLE_IN_MODULE
or \
435 CurrentSection
== DT
.MODEL_PCD_FEATURE_FLAG
or \
436 CurrentSection
== DT
.MODEL_PCD_DYNAMIC_EX
or \
437 CurrentSection
== DT
.MODEL_PCD_DYNAMIC
:
438 self
.InfPcdParser(SectionLines
,
442 elif CurrentSection
== DT
.MODEL_EFI_SOURCE_FILE
:
443 self
.InfSourceParser(SectionLines
,
444 self
.InfSourcesSection
,
447 elif CurrentSection
== DT
.MODEL_META_DATA_USER_EXTENSION
:
448 self
.InfUserExtensionParser(SectionLines
,
449 self
.InfUserExtensionSection
,
452 elif CurrentSection
== DT
.MODEL_EFI_PROTOCOL
:
453 self
.InfProtocolParser(SectionLines
,
454 self
.InfProtocolSection
,
457 elif CurrentSection
== DT
.MODEL_EFI_PPI
:
458 self
.InfPpiParser(SectionLines
,
462 elif CurrentSection
== DT
.MODEL_EFI_GUID
:
463 self
.InfGuidParser(SectionLines
,
467 elif CurrentSection
== DT
.MODEL_EFI_DEPEX
:
468 self
.InfDepexParser(SectionLines
,
469 self
.InfDepexSection
,
472 elif CurrentSection
== DT
.MODEL_EFI_BINARY_FILE
:
473 self
.InfBinaryParser(SectionLines
,
474 self
.InfBinariesSection
,
477 # Unknown section type found, raise error.
480 if len(self
.SectionHeaderContent
) >= 1:
481 Logger
.Error("Parser",
483 ST
.ERR_INF_PARSER_UNKNOWN_SECTION
,
484 File
=self
.FullPath
, Line
=LineNo
,
485 RaiseError
= Logger
.IS_RAISE_ERROR
)
487 Logger
.Error("Parser",
489 ST
.ERR_INF_PARSER_NO_SECTION_ERROR
,
490 File
=self
.FullPath
, Line
=LineNo
,
491 RaiseError
= Logger
.IS_RAISE_ERROR
)
493 return DefineSectionParsedFlag
495 def _ExtractEventHobBootMod(self
, FileLinesList
):
496 SpecialSectionStart
= False
497 CheckLocation
= False
498 GFindSpecialCommentRe
= \
499 re
.compile(r
"""#(?:\s*)\[(.*?)\](?:.*)""", re
.DOTALL
)
500 GFindNewSectionRe2
= \
501 re
.compile(r
"""#?(\s*)\[(.*?)\](.*)""", re
.DOTALL
)
504 for Line
in FileLinesList
:
507 MatchObject
= GFindSpecialCommentRe
.search(Line
)
509 SpecialSectionStart
= True
511 if MatchObject
.group(1).upper().startswith("EVENT"):
512 List
= self
.EventList
513 elif MatchObject
.group(1).upper().startswith("HOB"):
515 elif MatchObject
.group(1).upper().startswith("BOOTMODE"):
516 List
= self
.BootModeList
518 SpecialSectionStart
= False
519 CheckLocation
= False
520 if SpecialSectionStart
:
521 Element
.append([Line
, LineNum
])
525 # if currently in special section, try to detect end of current section
527 MatchObject
= GFindNewSectionRe2
.search(Line
)
528 if SpecialSectionStart
:
530 SpecialSectionStart
= False
531 CheckLocation
= False
534 SpecialSectionStart
= False
538 if not Line
.startswith(DT
.TAB_COMMENT_SPLIT
):
539 Logger
.Warn("Parser",
540 ST
.WARN_SPECIAL_SECTION_LOCATION_WRONG
,
541 File
=self
.FullPath
, Line
=LineNum
)
542 SpecialSectionStart
= False
543 CheckLocation
= False
546 Element
.append([Line
, LineNum
])
550 CheckLocation
= False
552 Logger
.Warn("Parser",
553 ST
.WARN_SPECIAL_SECTION_LOCATION_WRONG
,
554 File
=self
.FullPath
, Line
=LineNum
)
555 CheckLocation
= False
557 if len(self
.BootModeList
) >= 1:
558 self
.InfSpecialCommentParser(self
.BootModeList
,
559 self
.InfSpecialCommentSection
,
561 DT
.TYPE_BOOTMODE_SECTION
)
563 if len(self
.EventList
) >= 1:
564 self
.InfSpecialCommentParser(self
.EventList
,
565 self
.InfSpecialCommentSection
,
567 DT
.TYPE_EVENT_SECTION
)
569 if len(self
.HobList
) >= 1:
570 self
.InfSpecialCommentParser(self
.HobList
,
571 self
.InfSpecialCommentSection
,
574 ## _ProcessLastSection
577 def _ProcessLastSection(self
, SectionLines
, Line
, LineNo
, CurrentSection
):
579 # The last line is a section header. will discard it.
581 if not (Line
.startswith(DT
.TAB_SECTION_START
) and Line
.find(DT
.TAB_SECTION_END
) > -1):
582 SectionLines
.append((Line
, LineNo
))
584 if len(self
.SectionHeaderContent
) >= 1:
585 TemSectionName
= self
.SectionHeaderContent
[0][0].upper()
586 if TemSectionName
.upper() not in gINF_SECTION_DEF
.keys():
587 Logger
.Error("InfParser",
589 ST
.ERR_INF_PARSER_UNKNOWN_SECTION
,
593 RaiseError
= Logger
.IS_RAISE_ERROR
596 CurrentSection
= gINF_SECTION_DEF
[TemSectionName
]
597 self
.LastSectionHeaderContent
= self
.SectionHeaderContent
599 return SectionLines
, CurrentSection
601 ## _ConvertSecNameToType
604 def _ConvertSecNameToType(SectionName
):
606 if SectionName
.upper() not in gINF_SECTION_DEF
.keys():
607 SectionType
= DT
.MODEL_UNKNOWN
609 SectionType
= gINF_SECTION_DEF
[SectionName
.upper()]