]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/Trim/Trim.py
Sync BaseTool trunk (version r2460) into EDKII BaseTools. The change mainly includes:
[mirror_edk2.git] / BaseTools / Source / Python / Trim / Trim.py
index dbfa84a5da0ab9697482d9846b72b77f97e0dde1..0416ecdcacdf0c629bea0a1d6e3c641f5daf5a4c 100644 (file)
@@ -1,8 +1,8 @@
 ## @file
 # Trim files preprocessed by compiler
 #
-# Copyright (c) 2007 - 2010, Intel Corporation
-# All rights reserved. This program and the accompanying materials
+# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
 # are licensed and made available under the terms and conditions of the BSD License
 # which accompanies this distribution.  The full text of the license may be found at
 # http://opensource.org/licenses/bsd-license.php
@@ -22,24 +22,37 @@ from optparse import OptionParser
 from optparse import make_option
 from Common.BuildToolError import *
 from Common.Misc import *
-
+from Common.BuildVersion import gBUILD_VERSION
 import Common.EdkLogger as EdkLogger
 
 # Version and Copyright
-__version_number__ = "0.10"
+__version_number__ = ("0.10" + " " + gBUILD_VERSION)
 __version__ = "%prog Version " + __version_number__
 __copyright__ = "Copyright (c) 2007-2010, Intel Corporation. All rights reserved."
 
 ## Regular expression for matching Line Control directive like "#line xxx"
 gLineControlDirective = re.compile('^\s*#(?:line)?\s+([0-9]+)\s+"*([^"]*)"')
 ## Regular expression for matching "typedef struct"
-gTypedefPattern = re.compile("^\s*typedef\s+struct\s*[{]*$", re.MULTILINE)
+gTypedefPattern = re.compile("^\s*typedef\s+struct(\s+\w+)?\s*[{]*$", re.MULTILINE)
 ## Regular expression for matching "#pragma pack"
 gPragmaPattern = re.compile("^\s*#pragma\s+pack", re.MULTILINE)
+
+#
+# The following number pattern match will only match if following criteria is met:
+# There is leading non-(alphanumeric or _) character, and no following alphanumeric or _
+# as the pattern is greedily match, so it is ok for the gDecNumberPattern or gHexNumberPattern to grab the maximum match
+#
 ## Regular expression for matching HEX number
-gHexNumberPattern = re.compile("0[xX]([0-9a-fA-F]+)")
+gHexNumberPattern = re.compile("(?<=[^a-zA-Z0-9_])(0[xX])([0-9a-fA-F]+)(U(?=$|[^a-zA-Z0-9_]))?")
+## Regular expression for matching decimal number with 'U' postfix
+gDecNumberPattern = re.compile("(?<=[^a-zA-Z0-9_])([0-9]+)U(?=$|[^a-zA-Z0-9_])")
+## Regular expression for matching constant with 'ULL' 'LL' postfix
+gLongNumberPattern = re.compile("(?<=[^a-zA-Z0-9_])(0[xX][0-9a-fA-F]+|[0-9]+)U?LL(?=$|[^a-zA-Z0-9_])")
+
 ## Regular expression for matching "Include ()" in asl file
 gAslIncludePattern = re.compile("^(\s*)[iI]nclude\s*\(\"?([^\"\(\)]+)\"\)", re.MULTILINE)
+## Regular expression for matching C style #include "XXX.asl" in asl file
+gAslCIncludePattern = re.compile(r'^(\s*)#include\s*[<"]\s*([-\\/\w.]+)\s*([>"])', re.MULTILINE)
 ## Patterns used to convert EDK conventions to EDK2 ECP conventions
 gImportCodePatterns = [
     [
@@ -76,11 +89,6 @@ gImportCodePatterns = [
         '\\1EfiLibReportStatusCode ('
     ],
 
-    [
-        re.compile('#include\s+["<]LoadFile\.h[">]', re.MULTILINE),
-        '#include <FvLoadFile.h>'
-    ],
-
     [
         re.compile('#include\s+EFI_GUID_DEFINITION\s*\(FirmwareFileSystem\)', re.MULTILINE),
         '#include EFI_GUID_DEFINITION (FirmwareFileSystem)\n#include EFI_GUID_DEFINITION (FirmwareFileSystem2)'
@@ -123,7 +131,7 @@ gIncludedAslFile = []
 # @param  Target    File to store the trimmed content
 # @param  Convert   If True, convert standard HEX format to MASM format
 #
-def TrimPreprocessedFile(Source, Target, Convert):
+def TrimPreprocessedFile(Source, Target, ConvertHex, TrimLong):
     CreateDirectory(os.path.dirname(Target))
     try:
         f = open (Source, 'r')
@@ -169,8 +177,15 @@ def TrimPreprocessedFile(Source, Target, Convert):
                               % (LineIndexOfOriginalFile + 1))
 
         # convert HEX number format if indicated
-        if Convert:
-            Line = gHexNumberPattern.sub(r"0\1h", Line)
+        if ConvertHex:
+            Line = gHexNumberPattern.sub(r"0\2h", Line)
+        else:
+            Line = gHexNumberPattern.sub(r"\1\2", Line)
+        if TrimLong:
+            Line = gLongNumberPattern.sub(r"\1", Line)
+
+        # convert Decimal number format
+        Line = gDecNumberPattern.sub(r"\1", Line)
 
         if LineNumber != None:
             EdkLogger.verbose("Got line directive: line=%d" % LineNumber)
@@ -269,31 +284,61 @@ def TrimPreprocessedVfr(Source, Target):
 
 ## Read the content  ASL file, including ASL included, recursively
 #
-# @param  Source    File to be read
-# @param  Indent    Spaces before the Include() statement
+# @param  Source            File to be read
+# @param  Indent            Spaces before the Include() statement
+# @param  IncludePathList   The list of external include file
+# @param  LocalSearchPath   If LocalSearchPath is specified, this path will be searched
+#                           first for the included file; otherwise, only the path specified
+#                           in the IncludePathList will be searched.
 #
-def DoInclude(Source, Indent=''):
+def DoInclude(Source, Indent='', IncludePathList=[], LocalSearchPath=None):
     NewFileContent = []
-    # avoid A "include" B and B "include" A
-    if Source in gIncludedAslFile:
-        EdkLogger.warn("Trim", "Circular include",
-                       ExtraData= "%s -> %s" % (" -> ".join(gIncludedAslFile), Source))
-        return []
-    gIncludedAslFile.append(Source)
 
     try:
-        F = open(Source,'r')
+        #
+        # Search LocalSearchPath first if it is specified.
+        #
+        if LocalSearchPath:
+            SearchPathList = [LocalSearchPath] + IncludePathList
+        else:
+            SearchPathList = IncludePathList
+  
+        for IncludePath in SearchPathList:
+            IncludeFile = os.path.join(IncludePath, Source)
+            if os.path.isfile(IncludeFile):
+                F = open(IncludeFile, "r")
+                break
+        else:
+            EdkLogger.error("Trim", "Failed to find include file %s" % Source)
     except:
         EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=Source)
 
+    
+    # avoid A "include" B and B "include" A
+    IncludeFile = os.path.abspath(os.path.normpath(IncludeFile))
+    if IncludeFile in gIncludedAslFile:
+        EdkLogger.warn("Trim", "Circular include",
+                       ExtraData= "%s -> %s" % (" -> ".join(gIncludedAslFile), IncludeFile))
+        return []
+    gIncludedAslFile.append(IncludeFile)
+    
     for Line in F:
+        LocalSearchPath = None
         Result = gAslIncludePattern.findall(Line)
         if len(Result) == 0:
-            NewFileContent.append("%s%s" % (Indent, Line))
-            continue
+            Result = gAslCIncludePattern.findall(Line)
+            if len(Result) == 0 or os.path.splitext(Result[0][1])[1].lower() not in [".asl", ".asi"]:
+                NewFileContent.append("%s%s" % (Indent, Line))
+                continue
+            #
+            # We should first search the local directory if current file are using pattern #include "XXX" 
+            #
+            if Result[0][2] == '"':
+                LocalSearchPath = os.path.dirname(IncludeFile)
         CurrentIndent = Indent + Result[0][0]
         IncludedFile = Result[0][1]
-        NewFileContent.extend(DoInclude(IncludedFile, CurrentIndent))
+        NewFileContent.extend(DoInclude(IncludedFile, CurrentIndent, IncludePathList, LocalSearchPath))
+        NewFileContent.append("\n")
 
     gIncludedAslFile.pop()
     F.close()
@@ -305,19 +350,44 @@ def DoInclude(Source, Indent=''):
 #
 # Replace ASL include statement with the content the included file
 #
-# @param  Source    File to be trimmed
-# @param  Target    File to store the trimmed content
+# @param  Source          File to be trimmed
+# @param  Target          File to store the trimmed content
+# @param  IncludePathFile The file to log the external include path 
 #
-def TrimAslFile(Source, Target):
+def TrimAslFile(Source, Target, IncludePathFile):
     CreateDirectory(os.path.dirname(Target))
     
-    Cwd = os.getcwd()
     SourceDir = os.path.dirname(Source)
     if SourceDir == '':
         SourceDir = '.'
-    os.chdir(SourceDir)
-    Lines = DoInclude(Source)
-    os.chdir(Cwd)
+    
+    #
+    # Add source directory as the first search directory
+    #
+    IncludePathList = [SourceDir]
+    
+    #
+    # If additional include path file is specified, append them all
+    # to the search directory list.
+    #
+    if IncludePathFile:
+        try:
+            LineNum = 0
+            for Line in open(IncludePathFile,'r'):
+                LineNum += 1
+                if Line.startswith("/I") or Line.startswith ("-I"):
+                    IncludePathList.append(Line[2:].strip())
+                else:
+                    EdkLogger.warn("Trim", "Invalid include line in include list file.", IncludePathFile, LineNum)
+        except:
+            EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=IncludePathFile)
+
+    Lines = DoInclude(Source, '', IncludePathList)
+
+    #
+    # Undef MIN and MAX to avoid collision in ASL source code
+    #
+    Lines.insert(0, "#undef MIN\n#undef MAX\n")
 
     # save all lines trimmed
     try:
@@ -334,7 +404,7 @@ def TrimAslFile(Source, Target):
 # @param  Source    File or directory to be trimmed
 # @param  Target    File or directory to store the trimmed content
 #
-def TrimR8Sources(Source, Target):
+def TrimEdkSources(Source, Target):
     if os.path.isdir(Source):
         for CurrentDir, Dirs, Files in os.walk(Source):
             if '.svn' in Dirs:
@@ -346,17 +416,17 @@ def TrimR8Sources(Source, Target):
                 Dummy, Ext = os.path.splitext(FileName)
                 if Ext.upper() not in ['.C', '.H']: continue
                 if Target == None or Target == '':
-                    TrimR8SourceCode(
+                    TrimEdkSourceCode(
                         os.path.join(CurrentDir, FileName),
                         os.path.join(CurrentDir, FileName)
                         )
                 else:
-                    TrimR8SourceCode(
+                    TrimEdkSourceCode(
                         os.path.join(CurrentDir, FileName),
                         os.path.join(Target, CurrentDir[len(Source)+1:], FileName)
                         )
     else:
-        TrimR8SourceCode(Source, Target)
+        TrimEdkSourceCode(Source, Target)
 
 ## Trim one EDK source code file
 #
@@ -389,7 +459,7 @@ def TrimR8Sources(Source, Target):
 # @param  Source    File to be trimmed
 # @param  Target    File to store the trimmed content
 #
-def TrimR8SourceCode(Source, Target):
+def TrimEdkSourceCode(Source, Target):
     EdkLogger.verbose("\t%s -> %s" % (Source, Target))
     CreateDirectory(os.path.dirname(Target))
 
@@ -435,12 +505,16 @@ def Options():
                           help="The input file is preprocessed VFR file"),
         make_option("-a", "--asl-file", dest="FileType", const="Asl", action="store_const",
                           help="The input file is ASL file"),
-        make_option("-8", "--r8-source-code", dest="FileType", const="R8SourceCode", action="store_const",
-                          help="The input file is source code for R8 to be trimmed for ECP"),
+        make_option("-8", "--Edk-source-code", dest="FileType", const="EdkSourceCode", action="store_const",
+                          help="The input file is source code for Edk to be trimmed for ECP"),
 
         make_option("-c", "--convert-hex", dest="ConvertHex", action="store_true",
                           help="Convert standard hex format (0xabcd) to MASM format (abcdh)"),
 
+        make_option("-l", "--trim-long", dest="TrimLong", action="store_true",
+                          help="Remove postfix of long number"),
+        make_option("-i", "--include-path-file", dest="IncludePathFile",
+                          help="The input file is include path list to search for ASL include file"),
         make_option("-o", "--output", dest="OutputFile",
                           help="File to store the trimmed content"),
         make_option("-v", "--verbose", dest="LogLevel", action="store_const", const=EdkLogger.VERBOSE,
@@ -453,7 +527,7 @@ def Options():
     ]
 
     # use clearer usage to override default usage message
-    UsageString = "%prog [-s|-r|-a] [-c] [-v|-d <debug_level>|-q] [-o <output_file>] <input_file>"
+    UsageString = "%prog [-s|-r|-a] [-c] [-v|-d <debug_level>|-q] [-i <include_path_file>] [-o <output_file>] <input_file>"
 
     Parser = OptionParser(description=__copyright__, version=__version__, option_list=OptionList, usage=UsageString)
     Parser.set_defaults(FileType="Vfr")
@@ -499,13 +573,13 @@ def Main():
         elif CommandOptions.FileType == "Asl":
             if CommandOptions.OutputFile == None:
                 CommandOptions.OutputFile = os.path.splitext(InputFile)[0] + '.iii'
-            TrimAslFile(InputFile, CommandOptions.OutputFile)
-        elif CommandOptions.FileType == "R8SourceCode":
-            TrimR8Sources(InputFile, CommandOptions.OutputFile)
+            TrimAslFile(InputFile, CommandOptions.OutputFile, CommandOptions.IncludePathFile)
+        elif CommandOptions.FileType == "EdkSourceCode":
+            TrimEdkSources(InputFile, CommandOptions.OutputFile)
         else :
             if CommandOptions.OutputFile == None:
                 CommandOptions.OutputFile = os.path.splitext(InputFile)[0] + '.iii'
-            TrimPreprocessedFile(InputFile, CommandOptions.OutputFile, CommandOptions.ConvertHex)
+            TrimPreprocessedFile(InputFile, CommandOptions.OutputFile, CommandOptions.ConvertHex, CommandOptions.TrimLong)
     except FatalError, X:
         import platform
         import traceback