]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/AutoGen/BuildEngine.py
BaseTools: Remove equality operator with None
[mirror_edk2.git] / BaseTools / Source / Python / AutoGen / BuildEngine.py
1 ## @file
2 # The engine for building files
3 #
4 # Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
9 #
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 #
13
14 ##
15 # Import Modules
16 #
17 import Common.LongFilePathOs as os
18 import re
19 import copy
20 import string
21 from Common.LongFilePathSupport import OpenLongFilePath as open
22
23 from Common.GlobalData import *
24 from Common.BuildToolError import *
25 from Common.Misc import tdict, PathClass
26 from Common.String import NormPath
27 from Common.DataType import *
28
29 import Common.EdkLogger as EdkLogger
30
31 ## Convert file type to file list macro name
32 #
33 # @param FileType The name of file type
34 #
35 # @retval string The name of macro
36 #
37 def FileListMacro(FileType):
38 return "%sS" % FileType.replace("-", "_").upper()
39
40 ## Convert file type to list file macro name
41 #
42 # @param FileType The name of file type
43 #
44 # @retval string The name of macro
45 #
46 def ListFileMacro(FileType):
47 return "%s_LIST" % FileListMacro(FileType)
48
49 class TargetDescBlock(object):
50 _Cache_ = {} # {TargetFile : TargetDescBlock object}
51
52 # Factory method
53 def __new__(Class, Inputs, Outputs, Commands, Dependencies):
54 if Outputs[0] in Class._Cache_:
55 Tdb = Class._Cache_[Outputs[0]]
56 for File in Inputs:
57 Tdb.AddInput(File)
58 else:
59 Tdb = super(TargetDescBlock, Class).__new__(Class)
60 Tdb._Init(Inputs, Outputs, Commands, Dependencies)
61 #Class._Cache_[Outputs[0]] = Tdb
62 return Tdb
63
64 def _Init(self, Inputs, Outputs, Commands, Dependencies):
65 self.Inputs = Inputs
66 self.Outputs = Outputs
67 self.Commands = Commands
68 self.Dependencies = Dependencies
69 if self.Outputs:
70 self.Target = self.Outputs[0]
71 else:
72 self.Target = None
73
74 def __str__(self):
75 return self.Target.Path
76
77 def __hash__(self):
78 return hash(self.Target.Path)
79
80 def __eq__(self, Other):
81 if type(Other) == type(self):
82 return Other.Target.Path == self.Target.Path
83 else:
84 return str(Other) == self.Target.Path
85
86 def AddInput(self, Input):
87 if Input not in self.Inputs:
88 self.Inputs.append(Input)
89
90 def IsMultipleInput(self):
91 return len(self.Inputs) > 1
92
93 @staticmethod
94 def Renew():
95 TargetDescBlock._Cache_ = {}
96
97 ## Class for one build rule
98 #
99 # This represents a build rule which can give out corresponding command list for
100 # building the given source file(s). The result can be used for generating the
101 # target for makefile.
102 #
103 class FileBuildRule:
104 INC_LIST_MACRO = "INC_LIST"
105 INC_MACRO = "INC"
106
107 ## constructor
108 #
109 # @param Input The dictionary represeting input file(s) for a rule
110 # @param Output The list represeting output file(s) for a rule
111 # @param Command The list containing commands to generate the output from input
112 #
113 def __init__(self, Type, Input, Output, Command, ExtraDependency=None):
114 # The Input should not be empty
115 if not Input:
116 Input = []
117 if not Output:
118 Output = []
119 if not Command:
120 Command = []
121
122 self.FileListMacro = FileListMacro(Type)
123 self.ListFileMacro = ListFileMacro(Type)
124 self.IncListFileMacro = self.INC_LIST_MACRO
125
126 self.SourceFileType = Type
127 # source files listed not in "*" or "?" pattern format
128 if not ExtraDependency:
129 self.ExtraSourceFileList = []
130 else:
131 self.ExtraSourceFileList = ExtraDependency
132
133 #
134 # Search macros used in command lines for <FILE_TYPE>_LIST and INC_LIST.
135 # If found, generate a file to keep the input files used to get over the
136 # limitation of command line length
137 #
138 self.MacroList = []
139 self.CommandList = []
140 for CmdLine in Command:
141 self.MacroList.extend(gMacroRefPattern.findall(CmdLine))
142 # replace path separator with native one
143 self.CommandList.append(CmdLine)
144
145 # Indicate what should be generated
146 if self.FileListMacro in self.MacroList:
147 self.GenFileListMacro = True
148 else:
149 self.GenFileListMacro = False
150
151 if self.ListFileMacro in self.MacroList:
152 self.GenListFile = True
153 self.GenFileListMacro = True
154 else:
155 self.GenListFile = False
156
157 if self.INC_LIST_MACRO in self.MacroList:
158 self.GenIncListFile = True
159 else:
160 self.GenIncListFile = False
161
162 # Check input files
163 self.IsMultipleInput = False
164 self.SourceFileExtList = []
165 for File in Input:
166 Base, Ext = os.path.splitext(File)
167 if Base.find("*") >= 0:
168 # There's "*" in the file name
169 self.IsMultipleInput = True
170 self.GenFileListMacro = True
171 elif Base.find("?") < 0:
172 # There's no "*" and "?" in file name
173 self.ExtraSourceFileList.append(File)
174 continue
175 if Ext not in self.SourceFileExtList:
176 self.SourceFileExtList.append(Ext)
177
178 # Check output files
179 self.DestFileList = []
180 for File in Output:
181 self.DestFileList.append(File)
182
183 # All build targets generated by this rule for a module
184 self.BuildTargets = {}
185
186 ## str() function support
187 #
188 # @retval string
189 #
190 def __str__(self):
191 SourceString = ""
192 SourceString += " %s %s %s" % (self.SourceFileType, " ".join(self.SourceFileExtList), self.ExtraSourceFileList)
193 DestString = ", ".join(self.DestFileList)
194 CommandString = "\n\t".join(self.CommandList)
195 return "%s : %s\n\t%s" % (DestString, SourceString, CommandString)
196
197 ## Check if given file extension is supported by this rule
198 #
199 # @param FileExt The extension of a file
200 #
201 # @retval True If the extension is supported
202 # @retval False If the extension is not supported
203 #
204 def IsSupported(self, FileExt):
205 return FileExt in self.SourceFileExtList
206
207 def Instantiate(self, Macros={}):
208 NewRuleObject = copy.copy(self)
209 NewRuleObject.BuildTargets = {}
210 NewRuleObject.DestFileList = []
211 for File in self.DestFileList:
212 NewRuleObject.DestFileList.append(PathClass(NormPath(File, Macros)))
213 return NewRuleObject
214
215 ## Apply the rule to given source file(s)
216 #
217 # @param SourceFile One file or a list of files to be built
218 # @param RelativeToDir The relative path of the source file
219 # @param PathSeparator Path separator
220 #
221 # @retval tuple (Source file in full path, List of individual sourcefiles, Destionation file, List of build commands)
222 #
223 def Apply(self, SourceFile, BuildRuleOrder=None):
224 if not self.CommandList or not self.DestFileList:
225 return None
226
227 # source file
228 if self.IsMultipleInput:
229 SrcFileName = ""
230 SrcFileBase = ""
231 SrcFileExt = ""
232 SrcFileDir = ""
233 SrcPath = ""
234 # SourceFile must be a list
235 SrcFile = "$(%s)" % self.FileListMacro
236 else:
237 SrcFileName, SrcFileBase, SrcFileExt = SourceFile.Name, SourceFile.BaseName, SourceFile.Ext
238 if SourceFile.Root:
239 SrcFileDir = SourceFile.SubDir
240 if SrcFileDir == "":
241 SrcFileDir = "."
242 else:
243 SrcFileDir = "."
244 SrcFile = SourceFile.Path
245 SrcPath = SourceFile.Dir
246
247 # destination file (the first one)
248 if self.DestFileList:
249 DestFile = self.DestFileList[0].Path
250 DestPath = self.DestFileList[0].Dir
251 DestFileName = self.DestFileList[0].Name
252 DestFileBase, DestFileExt = self.DestFileList[0].BaseName, self.DestFileList[0].Ext
253 else:
254 DestFile = ""
255 DestPath = ""
256 DestFileName = ""
257 DestFileBase = ""
258 DestFileExt = ""
259
260 BuildRulePlaceholderDict = {
261 # source file
262 "src" : SrcFile,
263 "s_path" : SrcPath,
264 "s_dir" : SrcFileDir,
265 "s_name" : SrcFileName,
266 "s_base" : SrcFileBase,
267 "s_ext" : SrcFileExt,
268 # destination file
269 "dst" : DestFile,
270 "d_path" : DestPath,
271 "d_name" : DestFileName,
272 "d_base" : DestFileBase,
273 "d_ext" : DestFileExt,
274 }
275
276 DstFile = []
277 for File in self.DestFileList:
278 File = string.Template(str(File)).safe_substitute(BuildRulePlaceholderDict)
279 File = string.Template(str(File)).safe_substitute(BuildRulePlaceholderDict)
280 DstFile.append(PathClass(File, IsBinary=True))
281
282 if DstFile[0] in self.BuildTargets:
283 TargetDesc = self.BuildTargets[DstFile[0]]
284 if BuildRuleOrder and SourceFile.Ext in BuildRuleOrder:
285 Index = BuildRuleOrder.index(SourceFile.Ext)
286 for Input in TargetDesc.Inputs:
287 if Input.Ext not in BuildRuleOrder or BuildRuleOrder.index(Input.Ext) > Index:
288 #
289 # Command line should be regenerated since some macros are different
290 #
291 CommandList = self._BuildCommand(BuildRulePlaceholderDict)
292 TargetDesc._Init([SourceFile], DstFile, CommandList, self.ExtraSourceFileList)
293 break
294 else:
295 TargetDesc.AddInput(SourceFile)
296 else:
297 CommandList = self._BuildCommand(BuildRulePlaceholderDict)
298 TargetDesc = TargetDescBlock([SourceFile], DstFile, CommandList, self.ExtraSourceFileList)
299 TargetDesc.ListFileMacro = self.ListFileMacro
300 TargetDesc.FileListMacro = self.FileListMacro
301 TargetDesc.IncListFileMacro = self.IncListFileMacro
302 TargetDesc.GenFileListMacro = self.GenFileListMacro
303 TargetDesc.GenListFile = self.GenListFile
304 TargetDesc.GenIncListFile = self.GenIncListFile
305 self.BuildTargets[DstFile[0]] = TargetDesc
306 return TargetDesc
307
308 def _BuildCommand(self, Macros):
309 CommandList = []
310 for CommandString in self.CommandList:
311 CommandString = string.Template(CommandString).safe_substitute(Macros)
312 CommandString = string.Template(CommandString).safe_substitute(Macros)
313 CommandList.append(CommandString)
314 return CommandList
315
316 ## Class for build rules
317 #
318 # BuildRule class parses rules defined in a file or passed by caller, and converts
319 # the rule into FileBuildRule object.
320 #
321 class BuildRule:
322 _SectionHeader = "SECTIONHEADER"
323 _Section = "SECTION"
324 _SubSectionHeader = "SUBSECTIONHEADER"
325 _SubSection = "SUBSECTION"
326 _InputFile = "INPUTFILE"
327 _OutputFile = "OUTPUTFILE"
328 _ExtraDependency = "EXTRADEPENDENCY"
329 _Command = "COMMAND"
330 _UnknownSection = "UNKNOWNSECTION"
331
332 _SubSectionList = [_InputFile, _OutputFile, _Command]
333
334 _PATH_SEP = "(+)"
335 _FileTypePattern = re.compile("^[_a-zA-Z][_\-0-9a-zA-Z]*$")
336 _BinaryFileRule = FileBuildRule(TAB_DEFAULT_BINARY_FILE, [], [os.path.join("$(OUTPUT_DIR)", "${s_name}")],
337 ["$(CP) ${src} ${dst}"], [])
338
339 ## Constructor
340 #
341 # @param File The file containing build rules in a well defined format
342 # @param Content The string list of build rules in a well defined format
343 # @param LineIndex The line number from which the parsing will begin
344 # @param SupportedFamily The list of supported tool chain families
345 #
346 def __init__(self, File=None, Content=None, LineIndex=0, SupportedFamily=["MSFT", "INTEL", "GCC", "RVCT"]):
347 self.RuleFile = File
348 # Read build rules from file if it's not none
349 if File is not None:
350 try:
351 self.RuleContent = open(File, 'r').readlines()
352 except:
353 EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=File)
354 elif Content is not None:
355 self.RuleContent = Content
356 else:
357 EdkLogger.error("build", PARAMETER_MISSING, ExtraData="No rule file or string given")
358
359 self.SupportedToolChainFamilyList = SupportedFamily
360 self.RuleDatabase = tdict(True, 4) # {FileExt, ModuleType, Arch, Family : FileBuildRule object}
361 self.Ext2FileType = {} # {ext : file-type}
362 self.FileTypeList = set()
363
364 self._LineIndex = LineIndex
365 self._State = ""
366 self._RuleInfo = tdict(True, 2) # {toolchain family : {"InputFile": {}, "OutputFile" : [], "Command" : []}}
367 self._FileType = ''
368 self._BuildTypeList = []
369 self._ArchList = []
370 self._FamilyList = []
371 self._TotalToolChainFamilySet = set()
372 self._RuleObjectList = [] # FileBuildRule object list
373 self._FileVersion = ""
374
375 self.Parse()
376
377 # some intrinsic rules
378 self.RuleDatabase[TAB_DEFAULT_BINARY_FILE, "COMMON", "COMMON", "COMMON"] = self._BinaryFileRule
379 self.FileTypeList.add(TAB_DEFAULT_BINARY_FILE)
380
381 ## Parse the build rule strings
382 def Parse(self):
383 self._State = self._Section
384 for Index in range(self._LineIndex, len(self.RuleContent)):
385 # Clean up the line and replace path separator with native one
386 Line = self.RuleContent[Index].strip().replace(self._PATH_SEP, os.path.sep)
387 self.RuleContent[Index] = Line
388
389 # find the build_rule_version
390 if Line and Line[0] == "#" and Line.find(TAB_BUILD_RULE_VERSION) <> -1:
391 if Line.find("=") <> -1 and Line.find("=") < (len(Line) - 1) and (Line[(Line.find("=") + 1):]).split():
392 self._FileVersion = (Line[(Line.find("=") + 1):]).split()[0]
393 # skip empty or comment line
394 if Line == "" or Line[0] == "#":
395 continue
396
397 # find out section header, enclosed by []
398 if Line[0] == '[' and Line[-1] == ']':
399 # merge last section information into rule database
400 self.EndOfSection()
401 self._State = self._SectionHeader
402 # find out sub-section header, enclosed by <>
403 elif Line[0] == '<' and Line[-1] == '>':
404 if self._State != self._UnknownSection:
405 self._State = self._SubSectionHeader
406
407 # call section handler to parse each (sub)section
408 self._StateHandler[self._State](self, Index)
409 # merge last section information into rule database
410 self.EndOfSection()
411
412 ## Parse definitions under a section
413 #
414 # @param LineIndex The line index of build rule text
415 #
416 def ParseSection(self, LineIndex):
417 pass
418
419 ## Parse definitions under a subsection
420 #
421 # @param LineIndex The line index of build rule text
422 #
423 def ParseSubSection(self, LineIndex):
424 # currenly nothing here
425 pass
426
427 ## Placeholder for not supported sections
428 #
429 # @param LineIndex The line index of build rule text
430 #
431 def SkipSection(self, LineIndex):
432 pass
433
434 ## Merge section information just got into rule database
435 def EndOfSection(self):
436 Database = self.RuleDatabase
437 # if there's specific toochain family, 'COMMON' doesn't make sense any more
438 if len(self._TotalToolChainFamilySet) > 1 and 'COMMON' in self._TotalToolChainFamilySet:
439 self._TotalToolChainFamilySet.remove('COMMON')
440 for Family in self._TotalToolChainFamilySet:
441 Input = self._RuleInfo[Family, self._InputFile]
442 Output = self._RuleInfo[Family, self._OutputFile]
443 Command = self._RuleInfo[Family, self._Command]
444 ExtraDependency = self._RuleInfo[Family, self._ExtraDependency]
445
446 BuildRule = FileBuildRule(self._FileType, Input, Output, Command, ExtraDependency)
447 for BuildType in self._BuildTypeList:
448 for Arch in self._ArchList:
449 Database[self._FileType, BuildType, Arch, Family] = BuildRule
450 for FileExt in BuildRule.SourceFileExtList:
451 self.Ext2FileType[FileExt] = self._FileType
452
453 ## Parse section header
454 #
455 # @param LineIndex The line index of build rule text
456 #
457 def ParseSectionHeader(self, LineIndex):
458 self._RuleInfo = tdict(True, 2)
459 self._BuildTypeList = []
460 self._ArchList = []
461 self._FamilyList = []
462 self._TotalToolChainFamilySet = set()
463 FileType = ''
464 RuleNameList = self.RuleContent[LineIndex][1:-1].split(',')
465 for RuleName in RuleNameList:
466 Arch = 'COMMON'
467 BuildType = 'COMMON'
468 TokenList = [Token.strip().upper() for Token in RuleName.split('.')]
469 # old format: Build.File-Type
470 if TokenList[0] == "BUILD":
471 if len(TokenList) == 1:
472 EdkLogger.error("build", FORMAT_INVALID, "Invalid rule section",
473 File=self.RuleFile, Line=LineIndex + 1,
474 ExtraData=self.RuleContent[LineIndex])
475
476 FileType = TokenList[1]
477 if FileType == '':
478 EdkLogger.error("build", FORMAT_INVALID, "No file type given",
479 File=self.RuleFile, Line=LineIndex + 1,
480 ExtraData=self.RuleContent[LineIndex])
481 if self._FileTypePattern.match(FileType) is None:
482 EdkLogger.error("build", FORMAT_INVALID, File=self.RuleFile, Line=LineIndex + 1,
483 ExtraData="Only character, number (non-first character), '_' and '-' are allowed in file type")
484 # new format: File-Type.Build-Type.Arch
485 else:
486 if FileType == '':
487 FileType = TokenList[0]
488 elif FileType != TokenList[0]:
489 EdkLogger.error("build", FORMAT_INVALID,
490 "Different file types are not allowed in the same rule section",
491 File=self.RuleFile, Line=LineIndex + 1,
492 ExtraData=self.RuleContent[LineIndex])
493 if len(TokenList) > 1:
494 BuildType = TokenList[1]
495 if len(TokenList) > 2:
496 Arch = TokenList[2]
497 if BuildType not in self._BuildTypeList:
498 self._BuildTypeList.append(BuildType)
499 if Arch not in self._ArchList:
500 self._ArchList.append(Arch)
501
502 if 'COMMON' in self._BuildTypeList and len(self._BuildTypeList) > 1:
503 EdkLogger.error("build", FORMAT_INVALID,
504 "Specific build types must not be mixed with common one",
505 File=self.RuleFile, Line=LineIndex + 1,
506 ExtraData=self.RuleContent[LineIndex])
507 if 'COMMON' in self._ArchList and len(self._ArchList) > 1:
508 EdkLogger.error("build", FORMAT_INVALID,
509 "Specific ARCH must not be mixed with common one",
510 File=self.RuleFile, Line=LineIndex + 1,
511 ExtraData=self.RuleContent[LineIndex])
512
513 self._FileType = FileType
514 self._State = self._Section
515 self.FileTypeList.add(FileType)
516
517 ## Parse sub-section header
518 #
519 # @param LineIndex The line index of build rule text
520 #
521 def ParseSubSectionHeader(self, LineIndex):
522 SectionType = ""
523 List = self.RuleContent[LineIndex][1:-1].split(',')
524 FamilyList = []
525 for Section in List:
526 TokenList = Section.split('.')
527 Type = TokenList[0].strip().upper()
528
529 if SectionType == "":
530 SectionType = Type
531 elif SectionType != Type:
532 EdkLogger.error("build", FORMAT_INVALID,
533 "Two different section types are not allowed in the same sub-section",
534 File=self.RuleFile, Line=LineIndex + 1,
535 ExtraData=self.RuleContent[LineIndex])
536
537 if len(TokenList) > 1:
538 Family = TokenList[1].strip().upper()
539 else:
540 Family = "COMMON"
541
542 if Family not in FamilyList:
543 FamilyList.append(Family)
544
545 self._FamilyList = FamilyList
546 self._TotalToolChainFamilySet.update(FamilyList)
547 self._State = SectionType.upper()
548 if 'COMMON' in FamilyList and len(FamilyList) > 1:
549 EdkLogger.error("build", FORMAT_INVALID,
550 "Specific tool chain family should not be mixed with general one",
551 File=self.RuleFile, Line=LineIndex + 1,
552 ExtraData=self.RuleContent[LineIndex])
553 if self._State not in self._StateHandler:
554 EdkLogger.error("build", FORMAT_INVALID, File=self.RuleFile, Line=LineIndex + 1,
555 ExtraData="Unknown subsection: %s" % self.RuleContent[LineIndex])
556 ## Parse <InputFile> sub-section
557 #
558 # @param LineIndex The line index of build rule text
559 #
560 def ParseInputFile(self, LineIndex):
561 FileList = [File.strip() for File in self.RuleContent[LineIndex].split(",")]
562 for ToolChainFamily in self._FamilyList:
563 InputFiles = self._RuleInfo[ToolChainFamily, self._State]
564 if InputFiles is None:
565 InputFiles = []
566 self._RuleInfo[ToolChainFamily, self._State] = InputFiles
567 InputFiles.extend(FileList)
568
569 ## Parse <ExtraDependency> sub-section
570 #
571 # @param LineIndex The line index of build rule text
572 #
573 def ParseCommon(self, LineIndex):
574 for ToolChainFamily in self._FamilyList:
575 Items = self._RuleInfo[ToolChainFamily, self._State]
576 if Items is None:
577 Items = []
578 self._RuleInfo[ToolChainFamily, self._State] = Items
579 Items.append(self.RuleContent[LineIndex])
580
581 ## Get a build rule via [] operator
582 #
583 # @param FileExt The extension of a file
584 # @param ToolChainFamily The tool chain family name
585 # @param BuildVersion The build version number. "*" means any rule
586 # is applicalbe.
587 #
588 # @retval FileType The file type string
589 # @retval FileBuildRule The object of FileBuildRule
590 #
591 # Key = (FileExt, ModuleType, Arch, ToolChainFamily)
592 def __getitem__(self, Key):
593 if not Key:
594 return None
595
596 if Key[0] in self.Ext2FileType:
597 Type = self.Ext2FileType[Key[0]]
598 elif Key[0].upper() in self.FileTypeList:
599 Type = Key[0].upper()
600 else:
601 return None
602
603 if len(Key) > 1:
604 Key = (Type,) + Key[1:]
605 else:
606 Key = (Type,)
607 return self.RuleDatabase[Key]
608
609 _StateHandler = {
610 _SectionHeader : ParseSectionHeader,
611 _Section : ParseSection,
612 _SubSectionHeader : ParseSubSectionHeader,
613 _SubSection : ParseSubSection,
614 _InputFile : ParseInputFile,
615 _OutputFile : ParseCommon,
616 _ExtraDependency : ParseCommon,
617 _Command : ParseCommon,
618 _UnknownSection : SkipSection,
619 }
620
621 # This acts like the main() function for the script, unless it is 'import'ed into another
622 # script.
623 if __name__ == '__main__':
624 import sys
625 EdkLogger.Initialize()
626 if len(sys.argv) > 1:
627 Br = BuildRule(sys.argv[1])
628 print str(Br[".c", "DXE_DRIVER", "IA32", "MSFT"][1])
629 print
630 print str(Br[".c", "DXE_DRIVER", "IA32", "INTEL"][1])
631 print
632 print str(Br[".c", "DXE_DRIVER", "IA32", "GCC"][1])
633 print
634 print str(Br[".ac", "ACPI_TABLE", "IA32", "MSFT"][1])
635 print
636 print str(Br[".h", "ACPI_TABLE", "IA32", "INTEL"][1])
637 print
638 print str(Br[".ac", "ACPI_TABLE", "IA32", "MSFT"][1])
639 print
640 print str(Br[".s", "SEC", "IPF", "COMMON"][1])
641 print
642 print str(Br[".s", "SEC"][1])
643