Revision: 17005
          http://sourceforge.net/p/edk2/code/17005
Author:   hwu1225
Date:     2015-03-04 02:20:35 +0000 (Wed, 04 Mar 2015)
Log Message:
-----------
Add UINT16/32/64 array and DSC include support.

(Sync patch r17003 from main trunk.)

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: "Ma, Maurice" <[email protected]>
Reviewed-by: "Yao, Jiewen" <[email protected]>

Revision Links:
--------------
    http://sourceforge.net/p/edk2/code/17003

Modified Paths:
--------------
    branches/UDK2014.SP1/IntelFspPkg/Tools/GenCfgOpt.py

Modified: branches/UDK2014.SP1/IntelFspPkg/Tools/GenCfgOpt.py
===================================================================
--- branches/UDK2014.SP1/IntelFspPkg/Tools/GenCfgOpt.py 2015-03-04 01:15:08 UTC 
(rev 17004)
+++ branches/UDK2014.SP1/IntelFspPkg/Tools/GenCfgOpt.py 2015-03-04 02:20:35 UTC 
(rev 17005)
@@ -88,8 +88,206 @@
 **/
 """
 
+class CLogicalExpression:
+    def __init__(self):
+        self.index    = 0
+        self.string   = ''
+
+    def errExit(self, err = ''):
+        print "ERROR: Express parsing for:"
+        print "       %s" % self.string
+        print "       %s^" % (' ' * self.index)
+        if err:
+            print "INFO : %s" % err
+        raise SystemExit
+
+    def getNonNumber (self, n1, n2):
+        if not n1.isdigit():
+            return n1
+        if not n2.isdigit():
+            return n2
+        return None
+
+    def getCurr(self, lens = 1):
+        try:
+            if lens == -1:
+                return self.string[self.index :]
+            else:
+                if self.index + lens > len(self.string):
+                    lens = len(self.string) - self.index
+                return self.string[self.index : self.index + lens]
+        except Exception:
+            return ''
+
+    def isLast(self):
+        return self.index == len(self.string)
+
+    def moveNext(self, len = 1):
+        self.index += len
+
+    def skipSpace(self):
+        while not self.isLast():
+            if self.getCurr() in ' \t':
+                self.moveNext()
+            else:
+                return
+
+    def normNumber (self, val):
+        return True if val else False
+
+    def getNumber(self, var):
+        var = var.strip()
+        if   re.match('^0x[a-fA-F0-9]+$', var):
+            value = int(var, 16)
+        elif re.match('^[+-]?\d+$', var):
+            value = int(var, 10)
+        else:
+            value = None
+        return value
+
+    def parseValue(self):
+        self.skipSpace()
+        var = ''
+        while not self.isLast():
+            char = self.getCurr()
+            if re.match('^[\w.]', char):
+                var += char
+                self.moveNext()
+            else:
+                break
+        val = self.getNumber(var)
+        if val is None:
+            value = var
+        else:
+            value = "%d" % val
+        return value
+
+    def parseSingleOp(self):
+        self.skipSpace()
+        if re.match('^NOT\W', self.getCurr(-1)):
+            self.moveNext(3)
+            op  = self.parseBrace()
+            val = self.getNumber (op)
+            if val is None:
+                self.errExit ("'%s' is not a number" % op)
+            return "%d" % (not self.normNumber(int(op)))
+        else:
+            return self.parseValue()
+
+    def parseBrace(self):
+        self.skipSpace()
+        char = self.getCurr()
+        if char == '(':
+            self.moveNext()
+            value = self.parseExpr()
+            self.skipSpace()
+            if self.getCurr() != ')':
+                self.errExit ("Expecting closing brace or operator")
+            self.moveNext()
+            return value
+        else:
+            value = self.parseSingleOp()
+            return value
+
+    def parseCompare(self):
+        value = self.parseBrace()
+        while True:
+            self.skipSpace()
+            char = self.getCurr()
+            if char in ['<', '>']:
+                self.moveNext()
+                next = self.getCurr()
+                if next == '=':
+                    op = char + next
+                    self.moveNext()
+                else:
+                    op = char
+                result = self.parseBrace()
+                test = self.getNonNumber(result, value)
+                if test is None:
+                    value = "%d" % self.normNumber(eval (value + op + result))
+                else:
+                    self.errExit ("'%s' is not a valid number for comparision" 
% test)
+            elif char in ['=', '!']:
+                op = self.getCurr(2)
+                if op in ['==', '!=']:
+                    self.moveNext(2)
+                    result = self.parseBrace()
+                    test = self.getNonNumber(result, value)
+                    if test is None:
+                        value = "%d" % self.normNumber((eval (value + op + 
result)))
+                    else:
+                        value = "%d" % self.normNumber(eval ("'" + value + "'" 
+ op + "'" + result + "'"))
+                else:
+                    break
+            else:
+                break
+        return value
+
+    def parseAnd(self):
+        value = self.parseCompare()
+        while True:
+            self.skipSpace()
+            if re.match('^AND\W', self.getCurr(-1)):
+                self.moveNext(3)
+                result = self.parseCompare()
+                test = self.getNonNumber(result, value)
+                if test is None:
+                    value = "%d" % self.normNumber(int(value) & int(result))
+                else:
+                    self.errExit ("'%s' is not a valid op number for AND" % 
test)
+            else:
+                break
+        return value
+
+    def parseOrXor(self):
+        value  = self.parseAnd()
+        op     = None
+        while True:
+            self.skipSpace()
+            op = None
+            if re.match('^XOR\W', self.getCurr(-1)):
+                self.moveNext(3)
+                op = '^'
+            elif re.match('^OR\W', self.getCurr(-1)):
+                self.moveNext(2)
+                op = '|'
+            else:
+                break
+            if op:
+                result = self.parseAnd()
+                test = self.getNonNumber(result, value)
+                if test is None:
+                    value = "%d" % self.normNumber(eval (value + op + result))
+                else:
+                    self.errExit ("'%s' is not a valid op number for XOR/OR" % 
test)
+        return value
+
+    def parseExpr(self):
+        return self.parseOrXor()
+
+    def getResult(self):
+        value = self.parseExpr()
+        self.skipSpace()
+        if not self.isLast():
+            self.errExit ("Unexpected character found '%s'" % self.getCurr())
+        test = self.getNumber(value)
+        if test is None:
+            self.errExit ("Result '%s' is not a number" % value)
+        return int(value)
+
+    def evaluateExpress (self, Expr):
+        self.index     = 0
+        self.string    = Expr
+        if self.getResult():
+            Result = True
+        else:
+            Result = False
+        return Result
+
 class CGenCfgOpt:
     def __init__(self):
+        self.Debug          = False
         self.Error          = ''
 
         self._GlobalDataDef = """
@@ -139,13 +337,72 @@
                     if Match:
                         self._MacroDict[Match.group(1)] = ''
         if len(self._MacroDict) == 0:
-            self.Error = "Invalid MACRO arguments"
             Error = 1
         else:
             Error = 0
+            if self.Debug:
+                print "INFO : Macro dictionary:"
+                for Each in self._MacroDict:
+                    print "       $(%s) = [ %s ]" % (Each , 
self._MacroDict[Each])
         return Error
 
+    def EvaulateIfdef   (self, Macro):
+        Result = Macro in self._MacroDict
+        if self.Debug:
+            print "INFO : Eval Ifdef [%s] : %s" % (Macro, Result)
+        return  Result
 
+    def ExpandMacros (self, Input):
+        Line = Input
+        Match = re.findall("\$\(\w+\)", Input)
+        if Match:
+            for Each in Match:
+              Variable = Each[2:-1]
+              if Variable in self._MacroDict:
+                  Line = Line.replace(Each, self._MacroDict[Variable])
+              else:
+                  if self.Debug:
+                      print "WARN : %s is not defined" % Each
+                  Line = Line.replace(Each, Each[2:-1])
+        return Line
+
+    def EvaluateExpress (self, Expr):
+        ExpExpr = self.ExpandMacros(Expr)
+        LogExpr = CLogicalExpression()
+        Result  = LogExpr.evaluateExpress (ExpExpr)
+        if self.Debug:
+            print "INFO : Eval Express [%s] : %s" % (Expr, Result)
+        return Result
+
+    def FormatListValue(self, ConfigDict):
+        Struct = ConfigDict['struct']
+        if Struct not in ['UINT8','UINT16','UINT32','UINT64']:
+            return
+
+        dataarray = []
+        binlist = ConfigDict['value'][1:-1].split(',')
+        for each in binlist:
+            each = each.strip()
+            if each.startswith('0x'):
+                value = int(each, 16)
+            else:
+                value = int(each)
+            dataarray.append(value)
+
+        unit = int(Struct[4:]) / 8
+        if int(ConfigDict['length']) != unit * len(dataarray):
+            raise Exception("Array size is not proper for '%s' !" % 
ConfigDict['cname'])
+
+        bytearray = []
+        for each in dataarray:
+            value = each
+            for loop in xrange(unit):
+                bytearray.append("0x%02X" % (value & 0xFF))
+                value = value >> 8
+        newvalue  = '{'  + ','.join(bytearray) + '}'
+        ConfigDict['value'] = newvalue
+        return ""
+
     def ParseDscFile (self, DscFile, FvDir):
         self._CfgItemList = []
         self._CfgPageDict = {}
@@ -158,20 +415,19 @@
         IsVpdSect       = False
         Found           = False
 
-        IfStack         = [True]
+        IfStack         = []
         ElifStack       = []
         Error           = 0
+        ConfigDict      = {}
 
         DscFd        = open(DscFile, "r")
         DscLines     = DscFd.readlines()
         DscFd.close()
 
-        ConfigDict      = {}
-
-        for DscLine in DscLines:
-            Handle     = False
-            DscLine = DscLine.strip()
-            Match = re.match("^\[(.+)\]", DscLine)
+        while len(DscLines):
+            DscLine  = DscLines.pop(0).strip()            
+            Handle   = False
+            Match    = re.match("^\[(.+)\]", DscLine)
             if Match is not None:
                 if  Match.group(1).lower() == "Defines".lower():
                     IsDefSect = True
@@ -210,66 +466,78 @@
                     IsVpdSect = False
             else:
                 if IsDefSect or IsUpdSect or IsVpdSect:
-                    if DscLine == "!else":
-                        IfStack[-1] = not IfStack[-1]
-                    elif DscLine == "!endif":
-                        IfStack.pop()
-                        Level = ElifStack.pop()
-                        while Level > 0:
+                    if re.match("^!else($|\s+#.+)", DscLine):
+                        if IfStack:
+                            IfStack[-1] = not IfStack[-1]
+                        else:
+                            print("ERROR: No paired '!if' found for '!else' 
for line '%s'" % DscLine)
+                            raise SystemExit
+                    elif re.match("^!endif($|\s+#.+)", DscLine):
+                        if IfStack:
                             IfStack.pop()
-                            Level = Level - 1
+                            Level = ElifStack.pop()
+                            if Level > 0:
+                                del IfStack[-Level:]
+                        else:
+                            print("ERROR: No paired '!if' found for '!endif' 
for line '%s'" % DscLine)
+                            raise SystemExit
                     else:
                         Result = False
-                        Match = re.match("!(ifdef|ifndef)\s+\$\((\w+)\)", 
DscLine)
-                        if Match is not None:
-                            if Match.group(2) in self._MacroDict:
-                                if Match.group(1) == 'ifdef':
-                                    Result = True
-                            else:
-                                if Match.group(1) == 'ifndef':
-                                    Result = True
+                        Match = re.match("!(ifdef|ifndef)\s+(.+)", DscLine)
+                        if Match:
+                            Result = self.EvaulateIfdef (Match.group(2))
+                            if Match.group(1) == 'ifndef':
+                                Result = not Result
+                            IfStack.append(Result)
                             ElifStack.append(0)
-                            IfStack.append(Result)
                         else:
-                            Match = 
re.match("!(if|elseif)\s+\$\\((\w+)\)\s*==\s*(\w+|\$\(\w+\))", DscLine)
-                            if Match is not None:
-                                if Match.group(2) in self._MacroDict:
-                                    MacroName = self._MacroDict[Match.group(2)]
-                                else:
-                                    MacroName = ''
-                                Value = Match.group(3)
-                                if Value.startswith('$'):
-                                    if Value[2:-1] in self._MacroDict:
-                                        Value = self._MacroDict[Value[2:-1]]
-                                    else:
-                                        Value = ''
-                                if MacroName == Value:
-                                    Result = True
+                            Match  = re.match("!(if|elseif)\s+(.+)", DscLine)
+                            if Match:
+                                Result = self.EvaluateExpress(Match.group(2))
                                 if Match.group(1) == "if":
                                     ElifStack.append(0)
                                     IfStack.append(Result)
                                 else:   #elseif
-                                    IfStack[-1] = not IfStack[-1]
-                                    IfStack.append(Result)
-                                    ElifStack[-1] = ElifStack[-1] + 1
+                                    if IfStack:
+                                        IfStack[-1] = not IfStack[-1]
+                                        IfStack.append(Result)
+                                        ElifStack[-1] = ElifStack[-1] + 1
+                                    else:
+                                        print("ERROR: No paired '!if' found 
for '!elif' for line '%s'" % DscLine)
+                                        raise SystemExit
                             else:
-                                if len(DscLine) > 0 and DscLine[0] == '!':
-                                    #
-                                    # Current it can only handle build switch.
-                                    # It does not support INF file in included 
dsc.
-                                    #
+                                if IfStack:
+                                    Handle = reduce(lambda x,y: x and y, 
IfStack)
                                 else:
-                                    if reduce(lambda x,y: x and y, IfStack):
-                                        Handle = True
-
+                                    Handle = True
+                                if Handle:
+                                    Match = re.match("!include\s+(.+)", 
DscLine)
+                                    if Match:
+                                        IncludeFilePath = Match.group(1)
+                                        IncludeFilePath = 
self.ExpandMacros(IncludeFilePath)
+                                        try:
+                                            IncludeDsc  = 
open(IncludeFilePath, "r")
+                                        except:
+                                            print("ERROR: Cannot open file 
'%s'" % IncludeFilePath)
+                                            raise SystemExit
+                                        NewDscLines = IncludeDsc.readlines()
+                                        IncludeDsc.close()
+                                        DscLines = NewDscLines + DscLines
+                                    else:
+                                        if DscLine.startswith('!'):
+                                            print("ERROR: Unrecoginized 
directive for line '%s'" % DscLine)
+                                            raise SystemExit
+                                        
             if not Handle:
                 continue
 
             if IsDefSect:
                 #DEFINE UPD_TOOL_GUID = 8C3D856A-9BE6-468E-850A-24F7A8D38E09
-                Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([-\w]+)", 
DscLine)
+                Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([-.\w]+)", 
DscLine)
                 if Match:
                     self._MacroDict[Match.group(1)] = Match.group(2)
+                    if self.Debug:
+                        print "INFO : DEFINE %s = [ %s ]" % (Match.group(1), 
Match.group(2))
             else:
                 Match = re.match("^\s*#\s+!(BSF|HDR)\s+(.+)", DscLine)
                 if Match:
@@ -338,7 +606,11 @@
                     if Match:
                         if Match.group(1) in self._MacroDict:
                             Value = self._MacroDict[Match.group(1)]
+
                     ConfigDict['value']  = Value
+                    if (len(Value) > 0)  and (Value[0] == '{'):
+                        Value = self.FormatListValue(ConfigDict)
+
                     if ConfigDict['name']  == '':
                         # Clear BSF specific items
                         ConfigDict['help']   = ''
@@ -502,26 +774,29 @@
         TxtFd.close()
         return 0
 
-    def CreateField (self, Name, Length, Offset, Struct):
+    def CreateField (self, Item, Name, Length, Offset, Struct):
         PosName    = 28
         PosComment = 30
 
         IsArray = False
-        if Length == 1:
-            Type = "UINT8"
-        elif Length == 2:
-            Type = "UINT16"
-        elif Length == 4:
-            Type = "UINT32"
-        elif Length == 8:
-            Type = "UINT64"
+        if Length in [1,2,4,8]:
+            Type = "UINT%d" % (Length * 8)
         else:
+            IsArray = True
             Type = "UINT8"
+
+        if Item['value'].startswith('{'):
+            Type = "UINT8"
             IsArray = True
 
         if Struct != '':
-            IsArray = False
             Type = Struct
+            if Struct in ['UINT8','UINT16','UINT32','UINT64']:
+                IsArray = True
+                Unit = int(Type[4:]) / 8
+                Length = Length / Unit
+            else:
+                IsArray = False
 
         if IsArray:
             Name = Name + '[%d]' % Length
@@ -644,12 +919,12 @@
                         NextVisible = True
                         Name = "Reserved" + Region[0] + "pdSpace%d" % ResvIdx
                         ResvIdx = ResvIdx + 1
-                        HeaderFd.write(self.CreateField (Name, Item["offset"] 
- ResvOffset, ResvOffset, ''))
+                        HeaderFd.write(self.CreateField (Item, Name, 
Item["offset"] - ResvOffset, ResvOffset, ''))
 
                 if  Offset < Item["offset"]:
                     if IsInternal or LastVisible:
                         Name = "Unused" + Region[0] + "pdSpace%d" % SpaceIdx
-                        LineBuffer.append(self.CreateField (Name, 
Item["offset"] - Offset, Offset, ''))
+                        LineBuffer.append(self.CreateField (Item, Name, 
Item["offset"] - Offset, Offset, ''))
                     SpaceIdx = SpaceIdx + 1
                     Offset   = Item["offset"]
 
@@ -665,7 +940,7 @@
                     for Each in LineBuffer:
                         HeaderFd.write (Each)
                     LineBuffer = []
-                    HeaderFd.write(self.CreateField (Item["cname"], 
Item["length"], Item["offset"], Item['struct']))
+                    HeaderFd.write(self.CreateField (Item, Item["cname"], 
Item["length"], Item["offset"], Item['struct']))
 
             HeaderFd.write("} " + Region[0] + "PD_DATA_REGION;\n\n")
         HeaderFd.write("#pragma pack()\n\n")
@@ -846,7 +1121,6 @@
             print "ERROR: %s !" % GenCfgOpt.Error
             return 5
 
-
         if GenCfgOpt.UpdateVpdSizeField() != 0:
             print "ERROR: %s !" % GenCfgOpt.Error
             return 6


------------------------------------------------------------------------------
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the 
conversation now. http://goparallel.sourceforge.net/
_______________________________________________
edk2-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-commits

Reply via email to