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
.Misc
import ProcessEdkComment
30 from Library
.Parsing
import NormPath
31 from Library
.ParserValidate
import IsValidInfMoudleTypeList
32 from Library
.ParserValidate
import IsValidArch
33 from Library
import DataType
as DT
34 from Library
import GlobalData
36 import Logger
.Log
as Logger
37 from Logger
import StringTable
as ST
38 from Logger
.ToolError
import FORMAT_INVALID
39 from Logger
.ToolError
import FILE_READ_FAILURE
40 from Logger
.ToolError
import PARSER_ERROR
42 from Object
.Parser
.InfCommonObject
import InfSectionCommonDef
43 from Parser
.InfSectionParser
import InfSectionParser
44 from Parser
.InfParserMisc
import gINF_SECTION_DEF
45 from Parser
.InfParserMisc
import IsBinaryInf
50 def OpenInfFile(Filename
):
54 FInputfile
= open(Filename
, "rb", 0)
56 FileLinesList
= FInputfile
.readlines()
58 Logger
.Error("InfParser",
60 ST
.ERR_FILE_OPEN_FAILURE
,
65 Logger
.Error("InfParser",
67 ST
.ERR_FILE_OPEN_FAILURE
,
74 # This class defined the structure used in InfParser object
76 # @param InfObject: Inherited from InfSectionParser class
77 # @param Filename: Input value for Filename of INF file, default is
79 # @param WorkspaceDir: Input value for current workspace directory,
82 class InfParser(InfSectionParser
):
84 def __init__(self
, Filename
= None, WorkspaceDir
= None):
87 # Call parent class construct function
89 super(InfParser
, self
).__init
__()
91 self
.WorkspaceDir
= WorkspaceDir
92 self
.SupArchList
= DT
.ARCH_LIST
95 self
.BootModeList
= []
98 # Load Inf file if filename is not None
101 self
.ParseInfFile(Filename
)
105 # Parse the file if it exists
107 # @param Filename: Input value for filename of INF file
109 def ParseInfFile(self
, Filename
):
111 Filename
= NormPath(Filename
)
112 (Path
, Name
) = os
.path
.split(Filename
)
113 self
.FullPath
= Filename
116 GlobalData
.gINF_MODULE_DIR
= Path
117 GlobalData
.gINF_MODULE_NAME
= self
.FullPath
118 GlobalData
.gIS_BINARY_INF
= False
120 # Initialize common data
123 CurrentSection
= DT
.MODEL_UNKNOWN
129 HeaderCommentStart
= False
130 HeaderCommentEnd
= False
133 # While Section ends. parse whole section contents.
135 NewSectionStartFlag
= False
136 FirstSectionStartFlag
= False
144 # Variables for Event/Hob/BootMode
148 self
.BootModeList
= []
151 FileLinesList
= OpenInfFile (Filename
)
154 # One INF file can only has one [Defines] section.
156 DefineSectionParsedFlag
= False
159 # Convert special characters in lines to space character.
161 FileLinesList
= ConvertSpecialChar(FileLinesList
)
164 # Process Line Extender
166 FileLinesList
= ProcessLineExtender(FileLinesList
)
169 # Process EdkI INF style comment if found
171 OrigLines
= [Line
for Line
in FileLinesList
]
172 FileLinesList
, EdkCommentStartPos
= ProcessEdkComment(FileLinesList
)
175 # Judge whether the INF file is Binary INF or not
177 if IsBinaryInf(FileLinesList
):
178 GlobalData
.gIS_BINARY_INF
= True
180 InfSectionCommonDefObj
= None
182 for Line
in FileLinesList
:
185 if (LineNo
< len(FileLinesList
) - 1):
186 NextLine
= FileLinesList
[LineNo
].strip()
191 if (Line
== '' or not Line
) and LineNo
== len(FileLinesList
):
192 LastSectionFalg
= True
195 # check whether file header comment section started
197 if Line
.startswith(DT
.TAB_SPECIAL_COMMENT
) and \
198 (Line
.find(DT
.TAB_HEADER_COMMENT
) > -1) and \
199 not HeaderCommentStart
:
200 if CurrentSection
!= DT
.MODEL_UNKNOWN
:
201 Logger
.Error("Parser",
203 ST
.ERR_INF_PARSER_HEADER_FILE
,
206 RaiseError
= Logger
.IS_RAISE_ERROR
)
208 CurrentSection
= DT
.MODEL_META_DATA_FILE_HEADER
210 # Append the first line to section lines.
212 SectionLines
.append((Line
, LineNo
))
213 HeaderCommentStart
= True
217 # Collect Header content.
219 if (Line
.startswith(DT
.TAB_COMMENT_SPLIT
) and CurrentSection
== DT
.MODEL_META_DATA_FILE_HEADER
) and\
220 HeaderCommentStart
and not Line
.startswith(DT
.TAB_SPECIAL_COMMENT
) and not\
221 HeaderCommentEnd
and NextLine
!= '':
222 SectionLines
.append((Line
, LineNo
))
227 if (Line
.startswith(DT
.TAB_SPECIAL_COMMENT
) or not Line
.strip().startswith("#")) and HeaderCommentStart \
228 and not HeaderCommentEnd
:
229 SectionLines
.append((Line
, LineNo
))
230 HeaderCommentStart
= False
232 # Call Header comment parser.
234 self
.InfHeaderParser(SectionLines
, self
.InfHeader
, self
.FileName
)
236 HeaderCommentEnd
= True
240 # Find a new section tab
241 # Or at the last line of INF file,
242 # need to process the last section.
244 LastSectionFalg
= False
245 if LineNo
== len(FileLinesList
):
246 LastSectionFalg
= True
248 if Line
.startswith(DT
.TAB_COMMENT_SPLIT
) and not Line
.startswith(DT
.TAB_SPECIAL_COMMENT
):
249 SectionLines
.append((Line
, LineNo
))
250 if not LastSectionFalg
:
254 # Encountered a section. start with '[' and end with ']'
256 if (Line
.startswith(DT
.TAB_SECTION_START
) and \
257 Line
.find(DT
.TAB_SECTION_END
) > -1) or LastSectionFalg
:
258 if not LastSectionFalg
:
260 # check to prevent '#' inside section header
262 HeaderContent
= Line
[1:Line
.find(DT
.TAB_SECTION_END
)]
263 if HeaderContent
.find(DT
.TAB_COMMENT_SPLIT
) != -1:
264 Logger
.Error("InfParser",
266 ST
.ERR_INF_PARSER_DEFINE_SECTION_HEADER_INVALID
,
272 # Keep last time section header content for section parser
275 self
.LastSectionHeaderContent
= deepcopy(self
.SectionHeaderContent
)
278 # TailComments in section define.
281 CommentIndex
= Line
.find(DT
.TAB_COMMENT_SPLIT
)
282 if CommentIndex
> -1:
283 TailComments
= Line
[CommentIndex
:]
284 Line
= Line
[:CommentIndex
]
286 InfSectionCommonDefObj
= InfSectionCommonDef()
287 if TailComments
!= '':
288 InfSectionCommonDefObj
.SetTailComments(TailComments
)
289 if CommentBlock
!= '':
290 InfSectionCommonDefObj
.SetHeaderComments(CommentBlock
)
293 # Call section parser before section header parer to avoid encounter EDKI INF file
295 if CurrentSection
== DT
.MODEL_META_DATA_DEFINE
:
296 DefineSectionParsedFlag
= self
._CallSectionParsers
(CurrentSection
,
297 DefineSectionParsedFlag
, SectionLines
,
298 InfSectionCommonDefObj
, LineNo
)
300 # Compare the new section name with current
302 self
.SectionHeaderParser(Line
, self
.FileName
, LineNo
)
304 self
._CheckSectionHeaders
(Line
, LineNo
)
306 SectionType
= _ConvertSecNameToType(self
.SectionHeaderContent
[0][0])
308 if not FirstSectionStartFlag
:
309 CurrentSection
= SectionType
310 FirstSectionStartFlag
= True
312 NewSectionStartFlag
= True
314 SectionLines
.append((Line
, LineNo
))
318 SectionLines
, CurrentSection
= self
._ProcessLastSection
(SectionLines
, Line
, LineNo
, CurrentSection
)
321 # End of section content collect.
322 # Parser the section content collected previously.
324 if NewSectionStartFlag
or LastSectionFalg
:
325 if CurrentSection
!= DT
.MODEL_META_DATA_DEFINE
or \
326 (LastSectionFalg
and CurrentSection
== DT
.MODEL_META_DATA_DEFINE
):
327 DefineSectionParsedFlag
= self
._CallSectionParsers
(CurrentSection
,
328 DefineSectionParsedFlag
, SectionLines
,
329 InfSectionCommonDefObj
, LineNo
)
331 CurrentSection
= SectionType
333 # Clear section lines
340 # Found the first section, No file header.
342 if not DefineSectionParsedFlag
:
343 Logger
.Error("InfParser",
345 ST
.ERR_INF_PARSER_HEADER_MISSGING
,
349 # EDKII INF should not have EDKI style comment
351 if EdkCommentStartPos
!= -1:
352 Logger
.Error("InfParser",
354 ST
.ERR_INF_PARSER_EDKI_COMMENT_IN_EDKII
,
356 Line
=EdkCommentStartPos
+ 1,
357 ExtraData
=OrigLines
[EdkCommentStartPos
])
360 # extract [Event] [Hob] [BootMode] sections
362 self
._ExtractEventHobBootMod
(FileLinesList
)
364 ## _CheckSectionHeaders
367 def _CheckSectionHeaders(self
, Line
, LineNo
):
368 if len(self
.SectionHeaderContent
) == 0:
369 Logger
.Error("InfParser",
371 ST
.ERR_INF_PARSER_DEFINE_SECTION_HEADER_INVALID
,
373 Line
=LineNo
, ExtraData
=Line
)
375 for SectionItem
in self
.SectionHeaderContent
:
378 # Not cover Depex/UserExtension section header
381 if SectionItem
[0].strip().upper() == DT
.TAB_INF_FIXED_PCD
.upper() or \
382 SectionItem
[0].strip().upper() == DT
.TAB_INF_PATCH_PCD
.upper() or \
383 SectionItem
[0].strip().upper() == DT
.TAB_INF_PCD_EX
.upper() or \
384 SectionItem
[0].strip().upper() == DT
.TAB_INF_PCD
.upper() or \
385 SectionItem
[0].strip().upper() == DT
.TAB_INF_FEATURE_PCD
.upper():
386 ArchList
= GetSplitValueList(SectionItem
[1].strip(), ' ')
388 ArchList
= [SectionItem
[1].strip()]
390 for Arch
in ArchList
:
391 if (not IsValidArch(Arch
)) and \
392 (SectionItem
[0].strip().upper() != DT
.TAB_DEPEX
.upper()) and \
393 (SectionItem
[0].strip().upper() != DT
.TAB_USER_EXTENSIONS
.upper()) and \
394 (SectionItem
[0].strip().upper() != DT
.TAB_COMMON_DEFINES
.upper()):
395 Logger
.Error("InfParser",
397 ST
.ERR_INF_PARSER_DEFINE_FROMAT_INVALID
%(SectionItem
[1]),
399 Line
=LineNo
, ExtraData
=Line
)
401 # Check if the ModuleType is valid
403 ChkModSectionList
= ['LIBRARYCLASSES']
404 if (self
.SectionHeaderContent
[0][0].upper() in ChkModSectionList
):
405 if SectionItem
[2].strip().upper():
406 MoudleTypeList
= GetSplitValueList(
407 SectionItem
[2].strip().upper())
408 if (not IsValidInfMoudleTypeList(MoudleTypeList
)):
409 Logger
.Error("InfParser",
411 ST
.ERR_INF_PARSER_DEFINE_FROMAT_INVALID
%(SectionItem
[2]),
412 File
=self
.FullPath
, Line
=LineNo
,
415 ## _CallSectionParsers
418 def _CallSectionParsers(self
, CurrentSection
, DefineSectionParsedFlag
,
419 SectionLines
, InfSectionCommonDefObj
, LineNo
):
420 if CurrentSection
== DT
.MODEL_META_DATA_DEFINE
:
421 if not DefineSectionParsedFlag
:
422 self
.InfDefineParser(SectionLines
,
425 InfSectionCommonDefObj
)
426 DefineSectionParsedFlag
= True
428 Logger
.Error("Parser",
430 ST
.ERR_INF_PARSER_MULTI_DEFINE_SECTION
,
432 RaiseError
= Logger
.IS_RAISE_ERROR
)
434 elif CurrentSection
== DT
.MODEL_META_DATA_BUILD_OPTION
:
435 self
.InfBuildOptionParser(SectionLines
,
436 self
.InfBuildOptionSection
,
439 elif CurrentSection
== DT
.MODEL_EFI_LIBRARY_CLASS
:
440 self
.InfLibraryParser(SectionLines
,
441 self
.InfLibraryClassSection
,
444 elif CurrentSection
== DT
.MODEL_META_DATA_PACKAGE
:
445 self
.InfPackageParser(SectionLines
,
446 self
.InfPackageSection
,
449 # [Pcd] Sections, put it together
451 elif CurrentSection
== DT
.MODEL_PCD_FIXED_AT_BUILD
or \
452 CurrentSection
== DT
.MODEL_PCD_PATCHABLE_IN_MODULE
or \
453 CurrentSection
== DT
.MODEL_PCD_FEATURE_FLAG
or \
454 CurrentSection
== DT
.MODEL_PCD_DYNAMIC_EX
or \
455 CurrentSection
== DT
.MODEL_PCD_DYNAMIC
:
456 self
.InfPcdParser(SectionLines
,
460 elif CurrentSection
== DT
.MODEL_EFI_SOURCE_FILE
:
461 self
.InfSourceParser(SectionLines
,
462 self
.InfSourcesSection
,
465 elif CurrentSection
== DT
.MODEL_META_DATA_USER_EXTENSION
:
466 self
.InfUserExtensionParser(SectionLines
,
467 self
.InfUserExtensionSection
,
470 elif CurrentSection
== DT
.MODEL_EFI_PROTOCOL
:
471 self
.InfProtocolParser(SectionLines
,
472 self
.InfProtocolSection
,
475 elif CurrentSection
== DT
.MODEL_EFI_PPI
:
476 self
.InfPpiParser(SectionLines
,
480 elif CurrentSection
== DT
.MODEL_EFI_GUID
:
481 self
.InfGuidParser(SectionLines
,
485 elif CurrentSection
== DT
.MODEL_EFI_DEPEX
:
486 self
.InfDepexParser(SectionLines
,
487 self
.InfDepexSection
,
490 elif CurrentSection
== DT
.MODEL_EFI_BINARY_FILE
:
491 self
.InfBinaryParser(SectionLines
,
492 self
.InfBinariesSection
,
495 # Unknown section type found, raise error.
498 if len(self
.SectionHeaderContent
) >= 1:
499 Logger
.Error("Parser",
501 ST
.ERR_INF_PARSER_UNKNOWN_SECTION
,
502 File
=self
.FullPath
, Line
=LineNo
,
503 RaiseError
= Logger
.IS_RAISE_ERROR
)
505 Logger
.Error("Parser",
507 ST
.ERR_INF_PARSER_NO_SECTION_ERROR
,
508 File
=self
.FullPath
, Line
=LineNo
,
509 RaiseError
= Logger
.IS_RAISE_ERROR
)
511 return DefineSectionParsedFlag
513 def _ExtractEventHobBootMod(self
, FileLinesList
):
514 SpecialSectionStart
= False
515 CheckLocation
= False
516 GFindSpecialCommentRe
= \
517 re
.compile(r
"""#(?:\s*)\[(.*?)\](?:.*)""", re
.DOTALL
)
518 GFindNewSectionRe2
= \
519 re
.compile(r
"""#?(\s*)\[(.*?)\](.*)""", re
.DOTALL
)
522 for Line
in FileLinesList
:
525 MatchObject
= GFindSpecialCommentRe
.search(Line
)
527 SpecialSectionStart
= True
529 if MatchObject
.group(1).upper().startswith("EVENT"):
530 List
= self
.EventList
531 elif MatchObject
.group(1).upper().startswith("HOB"):
533 elif MatchObject
.group(1).upper().startswith("BOOTMODE"):
534 List
= self
.BootModeList
536 SpecialSectionStart
= False
537 CheckLocation
= False
538 if SpecialSectionStart
:
539 Element
.append([Line
, LineNum
])
543 # if currently in special section, try to detect end of current section
545 MatchObject
= GFindNewSectionRe2
.search(Line
)
546 if SpecialSectionStart
:
548 SpecialSectionStart
= False
549 CheckLocation
= False
552 SpecialSectionStart
= False
556 if not Line
.startswith(DT
.TAB_COMMENT_SPLIT
):
557 Logger
.Warn("Parser",
558 ST
.WARN_SPECIAL_SECTION_LOCATION_WRONG
,
559 File
=self
.FullPath
, Line
=LineNum
)
560 SpecialSectionStart
= False
561 CheckLocation
= False
564 Element
.append([Line
, LineNum
])
568 CheckLocation
= False
570 Logger
.Warn("Parser",
571 ST
.WARN_SPECIAL_SECTION_LOCATION_WRONG
,
572 File
=self
.FullPath
, Line
=LineNum
)
573 CheckLocation
= False
575 if len(self
.BootModeList
) >= 1:
576 self
.InfSpecialCommentParser(self
.BootModeList
,
577 self
.InfSpecialCommentSection
,
579 DT
.TYPE_BOOTMODE_SECTION
)
581 if len(self
.EventList
) >= 1:
582 self
.InfSpecialCommentParser(self
.EventList
,
583 self
.InfSpecialCommentSection
,
585 DT
.TYPE_EVENT_SECTION
)
587 if len(self
.HobList
) >= 1:
588 self
.InfSpecialCommentParser(self
.HobList
,
589 self
.InfSpecialCommentSection
,
592 ## _ProcessLastSection
595 def _ProcessLastSection(self
, SectionLines
, Line
, LineNo
, CurrentSection
):
597 # The last line is a section header. will discard it.
599 if not (Line
.startswith(DT
.TAB_SECTION_START
) and Line
.find(DT
.TAB_SECTION_END
) > -1):
600 SectionLines
.append((Line
, LineNo
))
602 if len(self
.SectionHeaderContent
) >= 1:
603 TemSectionName
= self
.SectionHeaderContent
[0][0].upper()
604 if TemSectionName
.upper() not in gINF_SECTION_DEF
.keys():
605 Logger
.Error("InfParser",
607 ST
.ERR_INF_PARSER_UNKNOWN_SECTION
,
611 RaiseError
= Logger
.IS_RAISE_ERROR
614 CurrentSection
= gINF_SECTION_DEF
[TemSectionName
]
615 self
.LastSectionHeaderContent
= self
.SectionHeaderContent
617 return SectionLines
, CurrentSection
619 ## _ConvertSecNameToType
622 def _ConvertSecNameToType(SectionName
):
624 if SectionName
.upper() not in gINF_SECTION_DEF
.keys():
625 SectionType
= DT
.MODEL_UNKNOWN
627 SectionType
= gINF_SECTION_DEF
[SectionName
.upper()]