1 # Copyright (c) 2007, Intel Corporation
2 # All rights reserved. This program and the accompanying materials
3 # are licensed and made available under the terms and conditions of the BSD License
4 # which accompanies this distribution. The full text of the license may be found at
5 # http://opensource.org/licenses/bsd-license.php
7 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 # This file is used to generate DEPEX file for module's dependency expression
17 from StringIO import StringIO
18 from struct import pack
19 from EdkIIWorkspace import CreateDirectory
20 from BuildToolError import *
29 "DXE_SMM_DRIVER" : "DXE",
30 "DXE_RUNTIME_DRIVER": "DXE",
31 "DXE_SAL_DRIVER" : "DXE",
32 "UEFI_DRIVER" : "DXE",
33 "UEFI_APPLICATION" : "DXE",
36 class DependencyExpression:
72 SupportedOpcode = ["BEFORE", "AFTER", "PUSH", "AND", "OR", "NOT", "TRUE", "FALSE", "END", "SOR"]
74 NonEndingOpcode = ["AND", "OR"]
76 ExclusiveOpcode = ["BEFORE", "AFTER"]
78 AboveAllOpcode = ["SOR"]
81 # open and close brace must be taken as individual tokens
83 TokenPattern = re.compile("(\(|\)|\{[^{}]+\{[^{}]+\}[ ]*\}|\w+)")
85 def __init__(self, expression, mtype):
86 self.Phase = gType2Phase[mtype]
87 if type(expression) == type([]):
88 self.ExpressionString = " ".join(expression)
89 self.TokenList = expression
91 self.ExpressionString = expression
92 self.GetExpressionTokenList()
94 self.PostfixNotation = []
97 self.GetPostfixNotation()
100 def GetExpressionTokenList(self):
101 self.TokenList = self.TokenPattern.findall(self.ExpressionString)
103 def GetPostfixNotation(self):
105 for token in self.TokenList:
109 while len(stack) > 0:
113 self.PostfixNotation.append(stack.pop())
114 elif token in self.OpcodePriority:
115 while len(stack) > 0:
116 if stack[-1] == "(" or self.OpcodePriority[token] > self.OpcodePriority[stack[-1]]:
118 self.PostfixNotation.append(stack.pop())
120 self.OpcodeList.append(token)
122 if token not in self.Opcode[self.Phase]:
123 self.PostfixNotation.append("PUSH")
125 self.OpcodeList.append(token)
126 self.PostfixNotation.append(token)
127 while len(stack) > 0:
128 self.PostfixNotation.append(stack.pop())
129 self.PostfixNotation.append("END")
130 #print " ","\n ".join(self.PostfixNotation)
132 def ValidateOpcode(self):
133 for op in self.AboveAllOpcode:
134 if op in self.OpcodeList and op != self.OpcodeList[0]:
135 raise AutoGenError("Opcode=%s should be the first one in expression", op)
136 for op in self.ExclusiveOpcode:
137 if op in self.OpcodeList and len(self.OpcodeList) > 1:
138 raise AutoGenError("Opcode=%s should be only opcode in expression", op)
139 # print "######", self.ExpressionString
140 if self.TokenList[-1] in self.NonEndingOpcode:
141 raise AutoGenError("Extra %s at the end of dependency expression" % self.TokenList[-1])
143 def GetGuidValue(self, guid):
144 guidValueString = guid.replace("{", "").replace("}", "").replace(" ", "")
145 guidValueList = guidValueString.split(",")
146 if len(guidValueList) != 11:
147 raise AutoGenError("Invalid GUID value string or opcode: %s" % guid)
148 return pack("1I2H8B", *(int(value, 16) for value in guidValueList))
150 def SaveFile(self, file, content):
151 CreateDirectory(os.path.dirname(file))
153 if os.path.exists(file):
155 if content == f.read():
163 def Generate(self, file=None):
165 for item in self.PostfixNotation:
166 if item in self.Opcode[self.Phase]:
167 buffer.write(pack("B", self.Opcode[self.Phase][item]))
169 buffer.write(self.GetGuidValue(item))
173 sys.stdout.write(buffer.getvalue())
176 self.SaveFile(file, buffer.getvalue())
182 versionNumber = "0.01"
183 __version__ = "%prog Version " + versionNumber
184 __copyright__ = "Copyright (c) 2007, Intel Corporation All rights reserved."
185 __usage__ = "%prog [options] [dependency_expression_file]"
188 from optparse import OptionParser
190 parser = OptionParser(description=__copyright__, version=__version__, usage=__usage__)
192 parser.add_option("-o", "--output", dest="OutputFile", default=None, metavar="FILE",
193 help="Specify the name of depex file to be generated")
194 parser.add_option("-t", "--module-type", dest="ModuleType", default=None,
195 help="The type of module for which the dependency expression serves")
196 parser.add_option("-e", "--dependency-expression", dest="Expression", default="",
197 help="The string of dependency expression. If this option presents, the input file will be ignored.")
198 parser.add_option("-v", "--verbose", dest="verbose", default=False, action="store_true",
199 help="build with verbose information")
200 parser.add_option("-d", "--debug", dest="debug", default=False, action="store_true",
201 help="build with debug information")
202 parser.add_option("-q", "--quiet", dest="quiet", default=False, action="store_true",
203 help="build with little information")
205 return parser.parse_args()
209 option, input = GetOptions()
210 if option.ModuleType == None or option.ModuleType not in gType2Phase:
211 print "Module type is not specified or supported"
215 if len(input) > 0 and option.Expression == "":
217 dxsString = open(dxsFile, 'r').read().replace("\n", " ").replace("\r", " ")
218 dxsString = re.compile("DEPENDENCY_START(.+)DEPENDENCY_END").findall(dxsString)[0]
219 elif option.Expression != "":
220 dxsString = option.Expression
222 print "No expression string or file given"
225 dpx = DependencyExpression(dxsString, option.ModuleType)
227 if option.OutputFile != None:
228 dpx.Generate(option.OutputFile)
236 if __name__ == '__main__':