Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Hess Chen <hesheng.chen@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18600 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1126 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			1126 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
## @file
 | 
						|
# Common routines used by all tools
 | 
						|
#
 | 
						|
# Copyright (c) 2011 - 2014, 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
 | 
						|
#
 | 
						|
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
#
 | 
						|
 | 
						|
'''
 | 
						|
Misc
 | 
						|
'''
 | 
						|
 | 
						|
##
 | 
						|
# Import Modules
 | 
						|
#
 | 
						|
import os.path
 | 
						|
from os import access
 | 
						|
from os import F_OK
 | 
						|
from os import makedirs
 | 
						|
from os import getcwd
 | 
						|
from os import chdir
 | 
						|
from os import listdir
 | 
						|
from os import remove
 | 
						|
from os import rmdir
 | 
						|
from os import linesep
 | 
						|
from os import walk
 | 
						|
from os import environ
 | 
						|
import re
 | 
						|
from UserDict import IterableUserDict
 | 
						|
 | 
						|
import Logger.Log as Logger
 | 
						|
from Logger import StringTable as ST
 | 
						|
from Logger import ToolError
 | 
						|
from Library import GlobalData
 | 
						|
from Library.DataType import SUP_MODULE_LIST
 | 
						|
from Library.DataType import END_OF_LINE
 | 
						|
from Library.DataType import TAB_SPLIT
 | 
						|
from Library.DataType import TAB_LANGUAGE_EN_US
 | 
						|
from Library.DataType import TAB_LANGUAGE_EN
 | 
						|
from Library.DataType import TAB_LANGUAGE_EN_X
 | 
						|
from Library.DataType import TAB_UNI_FILE_SUFFIXS
 | 
						|
from Library.String import GetSplitValueList
 | 
						|
from Library.ParserValidate import IsValidHexVersion
 | 
						|
from Library.ParserValidate import IsValidPath
 | 
						|
from Object.POM.CommonObject import TextObject
 | 
						|
from Core.FileHook import __FileHookOpen__
 | 
						|
from Common.MultipleWorkspace import MultipleWorkspace as mws
 | 
						|
 | 
						|
## Convert GUID string in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx style to C 
 | 
						|
# structure style
 | 
						|
#
 | 
						|
# @param      Guid:    The GUID string
 | 
						|
#
 | 
						|
def GuidStringToGuidStructureString(Guid):
 | 
						|
    GuidList = Guid.split('-')
 | 
						|
    Result = '{'
 | 
						|
    for Index in range(0, 3, 1):
 | 
						|
        Result = Result + '0x' + GuidList[Index] + ', '
 | 
						|
    Result = Result + '{0x' + GuidList[3][0:2] + ', 0x' + GuidList[3][2:4]
 | 
						|
    for Index in range(0, 12, 2):
 | 
						|
        Result = Result + ', 0x' + GuidList[4][Index:Index + 2]
 | 
						|
    Result += '}}'
 | 
						|
    return Result
 | 
						|
 | 
						|
## Check whether GUID string is of format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
 | 
						|
#
 | 
						|
# @param      GuidValue:   The GUID value
 | 
						|
#
 | 
						|
def CheckGuidRegFormat(GuidValue):
 | 
						|
    ## Regular expression used to find out register format of GUID
 | 
						|
    #
 | 
						|
    RegFormatGuidPattern = re.compile("^\s*([0-9a-fA-F]){8}-"
 | 
						|
                                       "([0-9a-fA-F]){4}-"
 | 
						|
                                       "([0-9a-fA-F]){4}-"
 | 
						|
                                       "([0-9a-fA-F]){4}-"
 | 
						|
                                       "([0-9a-fA-F]){12}\s*$")
 | 
						|
 | 
						|
    if RegFormatGuidPattern.match(GuidValue):
 | 
						|
        return True
 | 
						|
    else:
 | 
						|
        return False
 | 
						|
 | 
						|
 | 
						|
## Convert GUID string in C structure style to 
 | 
						|
# xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
 | 
						|
#
 | 
						|
# @param      GuidValue:   The GUID value in C structure format
 | 
						|
#
 | 
						|
def GuidStructureStringToGuidString(GuidValue):
 | 
						|
    GuidValueString = GuidValue.lower().replace("{", "").replace("}", "").\
 | 
						|
    replace(" ", "").replace(";", "")
 | 
						|
    GuidValueList = GuidValueString.split(",")
 | 
						|
    if len(GuidValueList) != 11:
 | 
						|
        return ''
 | 
						|
    try:
 | 
						|
        return "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (
 | 
						|
                int(GuidValueList[0], 16),
 | 
						|
                int(GuidValueList[1], 16),
 | 
						|
                int(GuidValueList[2], 16),
 | 
						|
                int(GuidValueList[3], 16),
 | 
						|
                int(GuidValueList[4], 16),
 | 
						|
                int(GuidValueList[5], 16),
 | 
						|
                int(GuidValueList[6], 16),
 | 
						|
                int(GuidValueList[7], 16),
 | 
						|
                int(GuidValueList[8], 16),
 | 
						|
                int(GuidValueList[9], 16),
 | 
						|
                int(GuidValueList[10], 16)
 | 
						|
                )
 | 
						|
    except BaseException:
 | 
						|
        return ''
 | 
						|
 | 
						|
## Create directories
 | 
						|
#
 | 
						|
# @param      Directory:   The directory name
 | 
						|
#
 | 
						|
def CreateDirectory(Directory):
 | 
						|
    if Directory == None or Directory.strip() == "":
 | 
						|
        return True
 | 
						|
    try:
 | 
						|
        if not access(Directory, F_OK):
 | 
						|
            makedirs(Directory)
 | 
						|
    except BaseException:
 | 
						|
        return False
 | 
						|
    return True
 | 
						|
 | 
						|
## Remove directories, including files and sub-directories in it
 | 
						|
#
 | 
						|
# @param      Directory:   The directory name
 | 
						|
#
 | 
						|
def RemoveDirectory(Directory, Recursively=False):
 | 
						|
    if Directory == None or Directory.strip() == "" or not \
 | 
						|
    os.path.exists(Directory):
 | 
						|
        return
 | 
						|
    if Recursively:
 | 
						|
        CurrentDirectory = getcwd()
 | 
						|
        chdir(Directory)
 | 
						|
        for File in listdir("."):
 | 
						|
            if os.path.isdir(File):
 | 
						|
                RemoveDirectory(File, Recursively)
 | 
						|
            else:
 | 
						|
                remove(File)
 | 
						|
        chdir(CurrentDirectory)
 | 
						|
    rmdir(Directory)
 | 
						|
 | 
						|
## Store content in file
 | 
						|
#
 | 
						|
# This method is used to save file only when its content is changed. This is
 | 
						|
# quite useful for "make" system to decide what will be re-built and what 
 | 
						|
# won't.
 | 
						|
#
 | 
						|
# @param      File:            The path of file
 | 
						|
# @param      Content:         The new content of the file
 | 
						|
# @param      IsBinaryFile:    The flag indicating if the file is binary file 
 | 
						|
#                              or not
 | 
						|
#
 | 
						|
def SaveFileOnChange(File, Content, IsBinaryFile=True):
 | 
						|
    if not IsBinaryFile:
 | 
						|
        Content = Content.replace("\n", linesep)
 | 
						|
 | 
						|
    if os.path.exists(File):
 | 
						|
        try:
 | 
						|
            if Content == __FileHookOpen__(File, "rb").read():
 | 
						|
                return False
 | 
						|
        except BaseException:
 | 
						|
            Logger.Error(None, ToolError.FILE_OPEN_FAILURE, ExtraData=File)
 | 
						|
 | 
						|
    CreateDirectory(os.path.dirname(File))
 | 
						|
    try:
 | 
						|
        FileFd = __FileHookOpen__(File, "wb")
 | 
						|
        FileFd.write(Content)
 | 
						|
        FileFd.close()
 | 
						|
    except BaseException:
 | 
						|
        Logger.Error(None, ToolError.FILE_CREATE_FAILURE, ExtraData=File)
 | 
						|
 | 
						|
    return True
 | 
						|
 | 
						|
## Get all files of a directory
 | 
						|
#
 | 
						|
# @param Root:       Root dir
 | 
						|
# @param SkipList :  The files need be skipped
 | 
						|
#
 | 
						|
def GetFiles(Root, SkipList=None, FullPath=True):
 | 
						|
    OriPath = os.path.normpath(Root)
 | 
						|
    FileList = []
 | 
						|
    for Root, Dirs, Files in walk(Root):
 | 
						|
        if SkipList:
 | 
						|
            for Item in SkipList:
 | 
						|
                if Item in Dirs:
 | 
						|
                    Dirs.remove(Item)
 | 
						|
                if Item in Files:
 | 
						|
                    Files.remove(Item)
 | 
						|
        for Dir in Dirs:
 | 
						|
            if Dir.startswith('.'):
 | 
						|
                Dirs.remove(Dir)
 | 
						|
 | 
						|
        for File in Files:
 | 
						|
            if File.startswith('.'):
 | 
						|
                continue
 | 
						|
            File = os.path.normpath(os.path.join(Root, File))
 | 
						|
            if not FullPath:
 | 
						|
                File = File[len(OriPath) + 1:]
 | 
						|
            FileList.append(File)
 | 
						|
 | 
						|
    return FileList
 | 
						|
 | 
						|
## Get all non-metadata files of a directory
 | 
						|
#
 | 
						|
# @param Root:       Root Dir
 | 
						|
# @param SkipList :  List of path need be skipped
 | 
						|
# @param FullPath:  True if the returned file should be full path
 | 
						|
# @param PrefixPath: the path that need to be added to the files found
 | 
						|
# @return: the list of files found
 | 
						|
#  
 | 
						|
def GetNonMetaDataFiles(Root, SkipList, FullPath, PrefixPath):
 | 
						|
    FileList = GetFiles(Root, SkipList, FullPath)
 | 
						|
    NewFileList = []
 | 
						|
    for File in FileList:
 | 
						|
        ExtName = os.path.splitext(File)[1]
 | 
						|
        #
 | 
						|
        # skip '.dec', '.inf', '.dsc', '.fdf' files
 | 
						|
        #
 | 
						|
        if ExtName.lower() not in ['.dec', '.inf', '.dsc', '.fdf']:
 | 
						|
            NewFileList.append(os.path.normpath(os.path.join(PrefixPath, File)))
 | 
						|
 | 
						|
    return NewFileList
 | 
						|
 | 
						|
## Check if given file exists or not
 | 
						|
#
 | 
						|
# @param      File:    File name or path to be checked
 | 
						|
# @param      Dir:     The directory the file is relative to
 | 
						|
#
 | 
						|
def ValidFile(File, Ext=None):
 | 
						|
    File = File.replace('\\', '/')
 | 
						|
    if Ext != None:
 | 
						|
        FileExt = os.path.splitext(File)[1]
 | 
						|
        if FileExt.lower() != Ext.lower():
 | 
						|
            return False
 | 
						|
    if not os.path.exists(File):
 | 
						|
        return False
 | 
						|
    return True
 | 
						|
 | 
						|
## RealPath
 | 
						|
#
 | 
						|
# @param      File:    File name or path to be checked
 | 
						|
# @param      Dir:     The directory the file is relative to
 | 
						|
# @param      OverrideDir:     The override directory
 | 
						|
#
 | 
						|
def RealPath(File, Dir='', OverrideDir=''):
 | 
						|
    NewFile = os.path.normpath(os.path.join(Dir, File))
 | 
						|
    NewFile = GlobalData.gALL_FILES[NewFile]
 | 
						|
    if not NewFile and OverrideDir:
 | 
						|
        NewFile = os.path.normpath(os.path.join(OverrideDir, File))
 | 
						|
        NewFile = GlobalData.gALL_FILES[NewFile]
 | 
						|
    return NewFile
 | 
						|
 | 
						|
## RealPath2
 | 
						|
#
 | 
						|
# @param      File:    File name or path to be checked
 | 
						|
# @param      Dir:     The directory the file is relative to
 | 
						|
# @param      OverrideDir:     The override directory
 | 
						|
#
 | 
						|
def RealPath2(File, Dir='', OverrideDir=''):
 | 
						|
    if OverrideDir:
 | 
						|
        NewFile = GlobalData.gALL_FILES[os.path.normpath(os.path.join\
 | 
						|
                                                        (OverrideDir, File))]
 | 
						|
        if NewFile:
 | 
						|
            if OverrideDir[-1] == os.path.sep:
 | 
						|
                return NewFile[len(OverrideDir):], NewFile[0:len(OverrideDir)]
 | 
						|
            else:
 | 
						|
                return NewFile[len(OverrideDir) + 1:], \
 | 
						|
            NewFile[0:len(OverrideDir)]
 | 
						|
 | 
						|
    NewFile = GlobalData.gALL_FILES[os.path.normpath(os.path.join(Dir, File))]
 | 
						|
    if NewFile:
 | 
						|
        if Dir:
 | 
						|
            if Dir[-1] == os.path.sep:
 | 
						|
                return NewFile[len(Dir):], NewFile[0:len(Dir)]
 | 
						|
            else:
 | 
						|
                return NewFile[len(Dir) + 1:], NewFile[0:len(Dir)]
 | 
						|
        else:
 | 
						|
            return NewFile, ''
 | 
						|
 | 
						|
    return None, None
 | 
						|
 | 
						|
## A dict which can access its keys and/or values orderly
 | 
						|
#
 | 
						|
#  The class implements a new kind of dict which its keys or values can be
 | 
						|
#  accessed in the order they are added into the dict. It guarantees the order
 | 
						|
#  by making use of an internal list to keep a copy of keys.
 | 
						|
#
 | 
						|
class Sdict(IterableUserDict):
 | 
						|
    ## Constructor
 | 
						|
    #
 | 
						|
    def __init__(self):
 | 
						|
        IterableUserDict.__init__(self)
 | 
						|
        self._key_list = []
 | 
						|
 | 
						|
    ## [] operator
 | 
						|
    #
 | 
						|
    def __setitem__(self, Key, Value):
 | 
						|
        if Key not in self._key_list:
 | 
						|
            self._key_list.append(Key)
 | 
						|
        IterableUserDict.__setitem__(self, Key, Value)
 | 
						|
 | 
						|
    ## del operator
 | 
						|
    #
 | 
						|
    def __delitem__(self, Key):
 | 
						|
        self._key_list.remove(Key)
 | 
						|
        IterableUserDict.__delitem__(self, Key)
 | 
						|
 | 
						|
    ## used in "for k in dict" loop to ensure the correct order
 | 
						|
    #
 | 
						|
    def __iter__(self):
 | 
						|
        return self.iterkeys()
 | 
						|
 | 
						|
    ## len() support
 | 
						|
    #
 | 
						|
    def __len__(self):
 | 
						|
        return len(self._key_list)
 | 
						|
 | 
						|
    ## "in" test support
 | 
						|
    #
 | 
						|
    def __contains__(self, Key):
 | 
						|
        return Key in self._key_list
 | 
						|
 | 
						|
    ## indexof support
 | 
						|
    #
 | 
						|
    def index(self, Key):
 | 
						|
        return self._key_list.index(Key)
 | 
						|
 | 
						|
    ## insert support
 | 
						|
    #
 | 
						|
    def insert(self, Key, Newkey, Newvalue, Order):
 | 
						|
        Index = self._key_list.index(Key)
 | 
						|
        if Order == 'BEFORE':
 | 
						|
            self._key_list.insert(Index, Newkey)
 | 
						|
            IterableUserDict.__setitem__(self, Newkey, Newvalue)
 | 
						|
        elif Order == 'AFTER':
 | 
						|
            self._key_list.insert(Index + 1, Newkey)
 | 
						|
            IterableUserDict.__setitem__(self, Newkey, Newvalue)
 | 
						|
 | 
						|
    ## append support
 | 
						|
    #
 | 
						|
    def append(self, Sdict2):
 | 
						|
        for Key in Sdict2:
 | 
						|
            if Key not in self._key_list:
 | 
						|
                self._key_list.append(Key)
 | 
						|
            IterableUserDict.__setitem__(self, Key, Sdict2[Key])
 | 
						|
    ## hash key
 | 
						|
    #
 | 
						|
    def has_key(self, Key):
 | 
						|
        return Key in self._key_list
 | 
						|
 | 
						|
    ## Empty the dict
 | 
						|
    #
 | 
						|
    def clear(self):
 | 
						|
        self._key_list = []
 | 
						|
        IterableUserDict.clear(self)
 | 
						|
 | 
						|
    ## Return a copy of keys
 | 
						|
    #
 | 
						|
    def keys(self):
 | 
						|
        Keys = []
 | 
						|
        for Key in self._key_list:
 | 
						|
            Keys.append(Key)
 | 
						|
        return Keys
 | 
						|
 | 
						|
    ## Return a copy of values
 | 
						|
    #
 | 
						|
    def values(self):
 | 
						|
        Values = []
 | 
						|
        for Key in self._key_list:
 | 
						|
            Values.append(self[Key])
 | 
						|
        return Values
 | 
						|
 | 
						|
    ## Return a copy of (key, value) list
 | 
						|
    #
 | 
						|
    def items(self):
 | 
						|
        Items = []
 | 
						|
        for Key in self._key_list:
 | 
						|
            Items.append((Key, self[Key]))
 | 
						|
        return Items
 | 
						|
 | 
						|
    ## Iteration support
 | 
						|
    #
 | 
						|
    def iteritems(self):
 | 
						|
        return iter(self.items())
 | 
						|
 | 
						|
    ## Keys interation support
 | 
						|
    #
 | 
						|
    def iterkeys(self):
 | 
						|
        return iter(self.keys())
 | 
						|
 | 
						|
    ## Values interation support
 | 
						|
    #
 | 
						|
    def itervalues(self):
 | 
						|
        return iter(self.values())
 | 
						|
 | 
						|
    ## Return value related to a key, and remove the (key, value) from the dict
 | 
						|
    #
 | 
						|
    def pop(self, Key, *Dv):
 | 
						|
        Value = None
 | 
						|
        if Key in self._key_list:
 | 
						|
            Value = self[Key]
 | 
						|
            self.__delitem__(Key)
 | 
						|
        elif len(Dv) != 0 :
 | 
						|
            Value = Dv[0]
 | 
						|
        return Value
 | 
						|
 | 
						|
    ## Return (key, value) pair, and remove the (key, value) from the dict
 | 
						|
    #
 | 
						|
    def popitem(self):
 | 
						|
        Key = self._key_list[-1]
 | 
						|
        Value = self[Key]
 | 
						|
        self.__delitem__(Key)
 | 
						|
        return Key, Value
 | 
						|
    ## update method
 | 
						|
    #
 | 
						|
    def update(self, Dict=None, **Kwargs):
 | 
						|
        if Dict != None:
 | 
						|
            for Key1, Val1 in Dict.items():
 | 
						|
                self[Key1] = Val1
 | 
						|
        if len(Kwargs):
 | 
						|
            for Key1, Val1 in Kwargs.items():
 | 
						|
                self[Key1] = Val1
 | 
						|
 | 
						|
## CommonPath
 | 
						|
#
 | 
						|
# @param PathList: PathList
 | 
						|
#
 | 
						|
def CommonPath(PathList):
 | 
						|
    Path1 = min(PathList).split(os.path.sep)
 | 
						|
    Path2 = max(PathList).split(os.path.sep)
 | 
						|
    for Index in xrange(min(len(Path1), len(Path2))):
 | 
						|
        if Path1[Index] != Path2[Index]:
 | 
						|
            return os.path.sep.join(Path1[:Index])
 | 
						|
    return os.path.sep.join(Path1)
 | 
						|
 | 
						|
## PathClass
 | 
						|
#
 | 
						|
class PathClass(object):
 | 
						|
    def __init__(self, File='', Root='', AlterRoot='', Type='', IsBinary=False,
 | 
						|
                 Arch='COMMON', ToolChainFamily='', Target='', TagName='', \
 | 
						|
                 ToolCode=''):
 | 
						|
        self.Arch = Arch
 | 
						|
        self.File = str(File)
 | 
						|
        if os.path.isabs(self.File):
 | 
						|
            self.Root = ''
 | 
						|
            self.AlterRoot = ''
 | 
						|
        else:
 | 
						|
            self.Root = str(Root)
 | 
						|
            self.AlterRoot = str(AlterRoot)
 | 
						|
 | 
						|
        #
 | 
						|
        # Remove any '.' and '..' in path
 | 
						|
        #
 | 
						|
        if self.Root:
 | 
						|
            self.Path = os.path.normpath(os.path.join(self.Root, self.File))
 | 
						|
            self.Root = os.path.normpath(CommonPath([self.Root, self.Path]))
 | 
						|
            #
 | 
						|
            # eliminate the side-effect of 'C:'
 | 
						|
            #
 | 
						|
            if self.Root[-1] == ':':
 | 
						|
                self.Root += os.path.sep
 | 
						|
            #
 | 
						|
            # file path should not start with path separator
 | 
						|
            #
 | 
						|
            if self.Root[-1] == os.path.sep:
 | 
						|
                self.File = self.Path[len(self.Root):]
 | 
						|
            else:
 | 
						|
                self.File = self.Path[len(self.Root) + 1:]
 | 
						|
        else:
 | 
						|
            self.Path = os.path.normpath(self.File)
 | 
						|
 | 
						|
        self.SubDir, self.Name = os.path.split(self.File)
 | 
						|
        self.BaseName, self.Ext = os.path.splitext(self.Name)
 | 
						|
 | 
						|
        if self.Root:
 | 
						|
            if self.SubDir:
 | 
						|
                self.Dir = os.path.join(self.Root, self.SubDir)
 | 
						|
            else:
 | 
						|
                self.Dir = self.Root
 | 
						|
        else:
 | 
						|
            self.Dir = self.SubDir
 | 
						|
 | 
						|
        if IsBinary:
 | 
						|
            self.Type = Type
 | 
						|
        else:
 | 
						|
            self.Type = self.Ext.lower()
 | 
						|
 | 
						|
        self.IsBinary = IsBinary
 | 
						|
        self.Target = Target
 | 
						|
        self.TagName = TagName
 | 
						|
        self.ToolCode = ToolCode
 | 
						|
        self.ToolChainFamily = ToolChainFamily
 | 
						|
 | 
						|
        self._Key = None
 | 
						|
 | 
						|
    ## Convert the object of this class to a string
 | 
						|
    #
 | 
						|
    #  Convert member Path of the class to a string
 | 
						|
    #
 | 
						|
    def __str__(self):
 | 
						|
        return self.Path
 | 
						|
 | 
						|
    ## Override __eq__ function
 | 
						|
    #
 | 
						|
    # Check whether PathClass are the same
 | 
						|
    #
 | 
						|
    def __eq__(self, Other):
 | 
						|
        if type(Other) == type(self):
 | 
						|
            return self.Path == Other.Path
 | 
						|
        else:
 | 
						|
            return self.Path == str(Other)
 | 
						|
 | 
						|
    ## Override __hash__ function
 | 
						|
    #
 | 
						|
    # Use Path as key in hash table
 | 
						|
    #
 | 
						|
    def __hash__(self):
 | 
						|
        return hash(self.Path)
 | 
						|
 | 
						|
    ## _GetFileKey
 | 
						|
    #
 | 
						|
    def _GetFileKey(self):
 | 
						|
        if self._Key == None:
 | 
						|
            self._Key = self.Path.upper()
 | 
						|
        return self._Key
 | 
						|
    ## Validate
 | 
						|
    #
 | 
						|
    def Validate(self, Type='', CaseSensitive=True):
 | 
						|
        if GlobalData.gCASE_INSENSITIVE:
 | 
						|
            CaseSensitive = False
 | 
						|
        if Type and Type.lower() != self.Type:
 | 
						|
            return ToolError.FILE_TYPE_MISMATCH, '%s (expect %s but got %s)' % \
 | 
						|
        (self.File, Type, self.Type)
 | 
						|
 | 
						|
        RealFile, RealRoot = RealPath2(self.File, self.Root, self.AlterRoot)
 | 
						|
        if not RealRoot and not RealFile:
 | 
						|
            RealFile = self.File
 | 
						|
            if self.AlterRoot:
 | 
						|
                RealFile = os.path.join(self.AlterRoot, self.File)
 | 
						|
            elif self.Root:
 | 
						|
                RealFile = os.path.join(self.Root, self.File)
 | 
						|
            return ToolError.FILE_NOT_FOUND, os.path.join(self.AlterRoot, RealFile)
 | 
						|
 | 
						|
        ErrorCode = 0
 | 
						|
        ErrorInfo = ''
 | 
						|
        if RealRoot != self.Root or RealFile != self.File:
 | 
						|
            if CaseSensitive and (RealFile != self.File or \
 | 
						|
                                  (RealRoot != self.Root and RealRoot != \
 | 
						|
                                   self.AlterRoot)):
 | 
						|
                ErrorCode = ToolError.FILE_CASE_MISMATCH
 | 
						|
                ErrorInfo = self.File + '\n\t' + RealFile + \
 | 
						|
                 " [in file system]"
 | 
						|
 | 
						|
            self.SubDir, self.Name = os.path.split(RealFile)
 | 
						|
            self.BaseName, self.Ext = os.path.splitext(self.Name)
 | 
						|
            if self.SubDir:
 | 
						|
                self.Dir = os.path.join(RealRoot, self.SubDir)
 | 
						|
            else:
 | 
						|
                self.Dir = RealRoot
 | 
						|
            self.File = RealFile
 | 
						|
            self.Root = RealRoot
 | 
						|
            self.Path = os.path.join(RealRoot, RealFile)
 | 
						|
        return ErrorCode, ErrorInfo
 | 
						|
 | 
						|
    Key = property(_GetFileKey)
 | 
						|
 | 
						|
## Get current workspace
 | 
						|
#
 | 
						|
#  get WORKSPACE from environment variable if present,if not use current working directory as WORKSPACE
 | 
						|
#
 | 
						|
def GetWorkspace():
 | 
						|
    #
 | 
						|
    # check WORKSPACE
 | 
						|
    #
 | 
						|
    if "WORKSPACE" in environ:
 | 
						|
        WorkspaceDir = os.path.normpath(environ["WORKSPACE"])
 | 
						|
        if not os.path.exists(WorkspaceDir):
 | 
						|
            Logger.Error("UPT",
 | 
						|
                         ToolError.UPT_ENVIRON_MISSING_ERROR,
 | 
						|
                         ST.ERR_WORKSPACE_NOTEXIST,
 | 
						|
                         ExtraData="%s" % WorkspaceDir)
 | 
						|
    else:
 | 
						|
        WorkspaceDir = os.getcwd()
 | 
						|
 | 
						|
    if WorkspaceDir[-1] == ':':
 | 
						|
        WorkspaceDir += os.sep
 | 
						|
 | 
						|
    PackagesPath = os.environ.get("PACKAGES_PATH")
 | 
						|
    mws.setWs(WorkspaceDir, PackagesPath)
 | 
						|
 | 
						|
    return WorkspaceDir, mws.PACKAGES_PATH
 | 
						|
 | 
						|
## Get relative path
 | 
						|
#
 | 
						|
#  use full path and workspace to get relative path
 | 
						|
#  the destination of this function is mainly to resolve the root path issue(like c: or c:\)  
 | 
						|
#
 | 
						|
#  @param Fullpath: a string of fullpath
 | 
						|
#  @param Workspace: a string of workspace
 | 
						|
#
 | 
						|
def GetRelativePath(Fullpath, Workspace):
 | 
						|
    
 | 
						|
    RelativePath = ''
 | 
						|
    if Workspace.endswith(os.sep):
 | 
						|
        RelativePath = Fullpath[Fullpath.upper().find(Workspace.upper())+len(Workspace):]
 | 
						|
    else:
 | 
						|
        RelativePath = Fullpath[Fullpath.upper().find(Workspace.upper())+len(Workspace)+1:]
 | 
						|
        
 | 
						|
    return RelativePath
 | 
						|
    
 | 
						|
## Check whether all module types are in list
 | 
						|
#
 | 
						|
# check whether all module types (SUP_MODULE_LIST) are in list
 | 
						|
#  
 | 
						|
# @param ModuleList:  a list of ModuleType
 | 
						|
#
 | 
						|
def IsAllModuleList(ModuleList):
 | 
						|
    NewModuleList = [Module.upper() for Module in ModuleList]
 | 
						|
    for Module in SUP_MODULE_LIST:
 | 
						|
        if Module not in NewModuleList:
 | 
						|
            return False
 | 
						|
    else:
 | 
						|
        return True
 | 
						|
 | 
						|
## Dictionary that use comment(GenericComment, TailComment) as value,
 | 
						|
# if a new comment which key already in the dic is inserted, then the 
 | 
						|
# comment will be merged.
 | 
						|
# Key is (Statement, SupArch), when TailComment is added, it will ident 
 | 
						|
# according to Statement
 | 
						|
#
 | 
						|
class MergeCommentDict(dict):
 | 
						|
    ## []= operator
 | 
						|
    #
 | 
						|
    def __setitem__(self, Key, CommentVal):
 | 
						|
        GenericComment, TailComment = CommentVal
 | 
						|
        if Key in self:
 | 
						|
            OrigVal1, OrigVal2 = dict.__getitem__(self, Key)
 | 
						|
            Statement = Key[0]
 | 
						|
            dict.__setitem__(self, Key, (OrigVal1 + GenericComment, OrigVal2 \
 | 
						|
                                         + len(Statement) * ' ' + TailComment))
 | 
						|
        else:
 | 
						|
            dict.__setitem__(self, Key, (GenericComment, TailComment))
 | 
						|
 | 
						|
    ## =[] operator
 | 
						|
    #
 | 
						|
    def __getitem__(self, Key):
 | 
						|
        return dict.__getitem__(self, Key)
 | 
						|
 | 
						|
 | 
						|
## GenDummyHelpTextObj
 | 
						|
#
 | 
						|
# @retval HelpTxt:   Generated dummy help text object
 | 
						|
#
 | 
						|
def GenDummyHelpTextObj():
 | 
						|
    HelpTxt = TextObject()
 | 
						|
    HelpTxt.SetLang(TAB_LANGUAGE_EN_US)
 | 
						|
    HelpTxt.SetString(' ')
 | 
						|
    return HelpTxt
 | 
						|
 | 
						|
## ConvertVersionToDecimal, the minor version should be within 0 - 99
 | 
						|
# <HexVersion>          ::=  "0x" <Major> <Minor>
 | 
						|
# <Major>               ::=  (a-fA-F0-9){4}
 | 
						|
# <Minor>               ::=  (a-fA-F0-9){4}
 | 
						|
# <DecVersion>          ::=  (0-65535) ["." (0-99)]
 | 
						|
# 
 | 
						|
# @param StringIn:  The string contains version defined in INF file.
 | 
						|
#                   It can be Decimal or Hex
 | 
						|
#
 | 
						|
def ConvertVersionToDecimal(StringIn):
 | 
						|
    if IsValidHexVersion(StringIn):
 | 
						|
        Value = int(StringIn, 16)
 | 
						|
        Major = Value >> 16
 | 
						|
        Minor = Value & 0xFFFF
 | 
						|
        MinorStr = str(Minor)
 | 
						|
        if len(MinorStr) == 1:
 | 
						|
            MinorStr = '0' + MinorStr
 | 
						|
        return str(Major) + '.' + MinorStr
 | 
						|
    else:
 | 
						|
        if StringIn.find(TAB_SPLIT) != -1:
 | 
						|
            return StringIn
 | 
						|
        elif StringIn:
 | 
						|
            return StringIn + '.0'
 | 
						|
        else:
 | 
						|
            #
 | 
						|
            # when StringIn is '', return it directly
 | 
						|
            #
 | 
						|
            return StringIn
 | 
						|
 | 
						|
## GetHelpStringByRemoveHashKey
 | 
						|
#
 | 
						|
# Remove hash key at the header of string and return the remain.
 | 
						|
#
 | 
						|
# @param String:  The string need to be processed.
 | 
						|
#
 | 
						|
def GetHelpStringByRemoveHashKey(String):
 | 
						|
    ReturnString = ''
 | 
						|
    PattenRemoveHashKey = re.compile(r"^[#+\s]+", re.DOTALL)
 | 
						|
    String = String.strip()
 | 
						|
    if String == '':
 | 
						|
        return String
 | 
						|
 | 
						|
    LineList = GetSplitValueList(String, END_OF_LINE)
 | 
						|
    for Line in LineList:
 | 
						|
        ValueList = PattenRemoveHashKey.split(Line)
 | 
						|
        if len(ValueList) == 1:
 | 
						|
            ReturnString += ValueList[0] + END_OF_LINE
 | 
						|
        else:
 | 
						|
            ReturnString += ValueList[1] + END_OF_LINE
 | 
						|
 | 
						|
    if ReturnString.endswith('\n') and not ReturnString.endswith('\n\n') and ReturnString != '\n':
 | 
						|
        ReturnString = ReturnString[:-1]
 | 
						|
 | 
						|
    return ReturnString
 | 
						|
 | 
						|
## ConvPathFromAbsToRel
 | 
						|
#
 | 
						|
# Get relative file path from absolute path.
 | 
						|
#
 | 
						|
# @param Path:  The string contain file absolute path.
 | 
						|
# @param Root:  The string contain the parent path of Path in.
 | 
						|
#
 | 
						|
#
 | 
						|
def ConvPathFromAbsToRel(Path, Root):
 | 
						|
    Path = os.path.normpath(Path)
 | 
						|
    Root = os.path.normpath(Root)
 | 
						|
    FullPath = os.path.normpath(os.path.join(Root, Path))
 | 
						|
 | 
						|
    #
 | 
						|
    # If Path is absolute path.
 | 
						|
    # It should be in Root.
 | 
						|
    #
 | 
						|
    if os.path.isabs(Path):
 | 
						|
        return FullPath[FullPath.find(Root) + len(Root) + 1:]
 | 
						|
 | 
						|
    else:
 | 
						|
        return Path
 | 
						|
 | 
						|
## ConvertPath
 | 
						|
#
 | 
						|
# Convert special characters to '_', '\' to '/'
 | 
						|
# return converted path: Test!1.inf -> Test_1.inf
 | 
						|
#
 | 
						|
# @param Path: Path to be converted
 | 
						|
#
 | 
						|
def ConvertPath(Path):
 | 
						|
    RetPath = ''
 | 
						|
    for Char in Path.strip():
 | 
						|
        if Char.isalnum() or Char in '.-_/':
 | 
						|
            RetPath = RetPath + Char
 | 
						|
        elif Char == '\\':
 | 
						|
            RetPath = RetPath + '/'
 | 
						|
        else:
 | 
						|
            RetPath = RetPath + '_'
 | 
						|
    return RetPath
 | 
						|
 | 
						|
## ConvertSpec
 | 
						|
#
 | 
						|
# during install, convert the Spec string extract from UPD into INF allowable definition, 
 | 
						|
# the difference is period is allowed in the former (not the first letter) but not in the latter.
 | 
						|
# return converted Spec string
 | 
						|
#
 | 
						|
# @param SpecStr: SpecStr to be converted
 | 
						|
#
 | 
						|
def ConvertSpec(SpecStr):
 | 
						|
    RetStr = ''
 | 
						|
    for Char in SpecStr:
 | 
						|
        if Char.isalnum() or Char == '_':
 | 
						|
            RetStr = RetStr + Char
 | 
						|
        else:
 | 
						|
            RetStr = RetStr + '_'
 | 
						|
 | 
						|
    return RetStr
 | 
						|
 | 
						|
 | 
						|
## IsEqualList
 | 
						|
#
 | 
						|
# Judge two lists are identical(contain same item).
 | 
						|
# The rule is elements in List A are in List B and elements in List B are in List A.
 | 
						|
#
 | 
						|
# @param ListA, ListB  Lists need to be judged.
 | 
						|
# 
 | 
						|
# @return True  ListA and ListB are identical
 | 
						|
# @return False ListA and ListB are different with each other
 | 
						|
#
 | 
						|
def IsEqualList(ListA, ListB):
 | 
						|
    if ListA == ListB:
 | 
						|
        return True
 | 
						|
 | 
						|
    for ItemA in ListA:
 | 
						|
        if not ItemA in ListB:
 | 
						|
            return False
 | 
						|
 | 
						|
    for ItemB in ListB:
 | 
						|
        if not ItemB in ListA:
 | 
						|
            return False
 | 
						|
 | 
						|
    return True
 | 
						|
 | 
						|
## ConvertArchList
 | 
						|
#
 | 
						|
# Convert item in ArchList if the start character is lower case.
 | 
						|
# In UDP spec, Arch is only allowed as: [A-Z]([a-zA-Z0-9])* 
 | 
						|
#
 | 
						|
# @param ArchList The ArchList need to be converted.
 | 
						|
# 
 | 
						|
# @return NewList  The ArchList been converted.
 | 
						|
#
 | 
						|
def ConvertArchList(ArchList):
 | 
						|
    NewArchList = []
 | 
						|
    if not ArchList:
 | 
						|
        return NewArchList
 | 
						|
 | 
						|
    if type(ArchList) == list:
 | 
						|
        for Arch in ArchList:
 | 
						|
            Arch = Arch.upper()
 | 
						|
            NewArchList.append(Arch)
 | 
						|
    elif type(ArchList) == str:
 | 
						|
        ArchList = ArchList.upper()
 | 
						|
        NewArchList.append(ArchList)
 | 
						|
 | 
						|
    return NewArchList
 | 
						|
 | 
						|
## ProcessLineExtender
 | 
						|
#
 | 
						|
# Process the LineExtender of Line in LineList.
 | 
						|
# If one line ends with a line extender, then it will be combined together with next line.
 | 
						|
#
 | 
						|
# @param LineList The LineList need to be processed.
 | 
						|
# 
 | 
						|
# @return NewList  The ArchList been processed.
 | 
						|
#
 | 
						|
def ProcessLineExtender(LineList):
 | 
						|
    NewList = []
 | 
						|
    Count = 0
 | 
						|
    while Count < len(LineList):
 | 
						|
        if LineList[Count].strip().endswith("\\") and Count + 1 < len(LineList):
 | 
						|
            NewList.append(LineList[Count].strip()[:-2] + LineList[Count + 1])
 | 
						|
            Count = Count + 1
 | 
						|
        else:
 | 
						|
            NewList.append(LineList[Count])
 | 
						|
 | 
						|
        Count = Count + 1
 | 
						|
 | 
						|
    return NewList
 | 
						|
 | 
						|
## ProcessEdkComment
 | 
						|
#
 | 
						|
# Process EDK style comment in LineList: c style /* */ comment or cpp style // comment 
 | 
						|
#
 | 
						|
#
 | 
						|
# @param LineList The LineList need to be processed.
 | 
						|
# 
 | 
						|
# @return LineList  The LineList been processed.
 | 
						|
# @return FirstPos  Where Edk comment is first found, -1 if not found
 | 
						|
#
 | 
						|
def ProcessEdkComment(LineList):
 | 
						|
    FindEdkBlockComment = False
 | 
						|
    Count = 0
 | 
						|
    StartPos = -1
 | 
						|
    EndPos = -1
 | 
						|
    FirstPos = -1
 | 
						|
    
 | 
						|
    while(Count < len(LineList)):
 | 
						|
        Line = LineList[Count].strip()
 | 
						|
        if Line.startswith("/*"):
 | 
						|
            #
 | 
						|
            # handling c style comment
 | 
						|
            #
 | 
						|
            StartPos = Count
 | 
						|
            while Count < len(LineList):
 | 
						|
                Line = LineList[Count].strip()
 | 
						|
                if Line.endswith("*/"):
 | 
						|
                    if (Count == StartPos) and Line.strip() == '/*/':
 | 
						|
                        Count = Count + 1
 | 
						|
                        continue
 | 
						|
                    EndPos = Count
 | 
						|
                    FindEdkBlockComment = True
 | 
						|
                    break
 | 
						|
                Count = Count + 1
 | 
						|
            
 | 
						|
            if FindEdkBlockComment:
 | 
						|
                if FirstPos == -1:
 | 
						|
                    FirstPos = StartPos
 | 
						|
                for Index in xrange(StartPos, EndPos+1):
 | 
						|
                    LineList[Index] = ''
 | 
						|
                FindEdkBlockComment = False
 | 
						|
        elif Line.find("//") != -1 and not Line.startswith("#"):
 | 
						|
            #
 | 
						|
            # handling cpp style comment
 | 
						|
            #
 | 
						|
            LineList[Count] = Line.replace("//", '#')
 | 
						|
            if FirstPos == -1:
 | 
						|
                FirstPos = Count
 | 
						|
        
 | 
						|
        Count = Count + 1
 | 
						|
    
 | 
						|
    return LineList, FirstPos
 | 
						|
 | 
						|
## GetLibInstanceInfo
 | 
						|
#
 | 
						|
# Get the information from Library Instance INF file.
 | 
						|
#
 | 
						|
# @param string.  A string start with # and followed by INF file path
 | 
						|
# @param WorkSpace. The WorkSpace directory used to combined with INF file path.
 | 
						|
#
 | 
						|
# @return GUID, Version
 | 
						|
def GetLibInstanceInfo(String, WorkSpace, LineNo):
 | 
						|
 | 
						|
    FileGuidString = ""
 | 
						|
    VerString = ""
 | 
						|
 | 
						|
    OrignalString = String
 | 
						|
    String = String.strip()
 | 
						|
    if not String:
 | 
						|
        return None, None
 | 
						|
    #
 | 
						|
    # Remove "#" characters at the beginning
 | 
						|
    #
 | 
						|
    String = GetHelpStringByRemoveHashKey(String)
 | 
						|
    String = String.strip()
 | 
						|
 | 
						|
    #
 | 
						|
    # Validate file name exist.
 | 
						|
    #
 | 
						|
    FullFileName = os.path.normpath(os.path.realpath(os.path.join(WorkSpace, String)))
 | 
						|
    if not (ValidFile(FullFileName)):
 | 
						|
        Logger.Error("InfParser",
 | 
						|
                     ToolError.FORMAT_INVALID,
 | 
						|
                     ST.ERR_FILELIST_EXIST % (String),
 | 
						|
                     File=GlobalData.gINF_MODULE_NAME,
 | 
						|
                     Line=LineNo,
 | 
						|
                     ExtraData=OrignalString)
 | 
						|
 | 
						|
    #
 | 
						|
    # Validate file exist/format.
 | 
						|
    #
 | 
						|
    if IsValidPath(String, WorkSpace):
 | 
						|
        IsValidFileFlag = True
 | 
						|
    else:
 | 
						|
        Logger.Error("InfParser",
 | 
						|
                     ToolError.FORMAT_INVALID,
 | 
						|
                     ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID % (String),
 | 
						|
                     File=GlobalData.gINF_MODULE_NAME,
 | 
						|
                     Line=LineNo,
 | 
						|
                     ExtraData=OrignalString)
 | 
						|
        return False
 | 
						|
    if IsValidFileFlag:
 | 
						|
        FileLinesList = []
 | 
						|
 | 
						|
        try:
 | 
						|
            FInputfile = open(FullFileName, "rb", 0)
 | 
						|
            try:
 | 
						|
                FileLinesList = FInputfile.readlines()
 | 
						|
            except BaseException:
 | 
						|
                Logger.Error("InfParser",
 | 
						|
                             ToolError.FILE_READ_FAILURE,
 | 
						|
                             ST.ERR_FILE_OPEN_FAILURE,
 | 
						|
                             File=FullFileName)
 | 
						|
            finally:
 | 
						|
                FInputfile.close()
 | 
						|
        except BaseException:
 | 
						|
            Logger.Error("InfParser",
 | 
						|
                         ToolError.FILE_READ_FAILURE,
 | 
						|
                         ST.ERR_FILE_OPEN_FAILURE,
 | 
						|
                         File=FullFileName)
 | 
						|
 | 
						|
        ReFileGuidPattern = re.compile("^\s*FILE_GUID\s*=.*$")
 | 
						|
        ReVerStringPattern = re.compile("^\s*VERSION_STRING\s*=.*$")
 | 
						|
 | 
						|
        FileLinesList = ProcessLineExtender(FileLinesList)
 | 
						|
 | 
						|
        for Line in FileLinesList:
 | 
						|
            if ReFileGuidPattern.match(Line):
 | 
						|
                FileGuidString = Line
 | 
						|
            if ReVerStringPattern.match(Line):
 | 
						|
                VerString = Line
 | 
						|
 | 
						|
        if FileGuidString:
 | 
						|
            FileGuidString = GetSplitValueList(FileGuidString, '=', 1)[1]
 | 
						|
        if VerString:
 | 
						|
            VerString = GetSplitValueList(VerString, '=', 1)[1]
 | 
						|
 | 
						|
        return FileGuidString, VerString
 | 
						|
 | 
						|
## GetLocalValue
 | 
						|
#
 | 
						|
# Generate the local value for INF and DEC file. If Lang attribute not present, then use this value.
 | 
						|
# If present, and there is no element without the Lang attribute, and one of the elements has the rfc1766 code is 
 | 
						|
# "en-x-tianocore", or "en-US" if "en-x-tianocore" was not found, or "en" if "en-US" was not found, or startswith 'en' 
 | 
						|
# if 'en' was not found, then use this value.
 | 
						|
# If multiple entries of a tag exist which have the same language code, use the last entry.
 | 
						|
#
 | 
						|
# @param ValueList  A list need to be processed.
 | 
						|
# @param UseFirstValue: True to use the first value, False to use the last value 
 | 
						|
#
 | 
						|
# @return LocalValue
 | 
						|
def GetLocalValue(ValueList, UseFirstValue=False):
 | 
						|
    Value1 = ''
 | 
						|
    Value2 = ''
 | 
						|
    Value3 = ''
 | 
						|
    Value4 = ''
 | 
						|
    Value5 = ''
 | 
						|
    for (Key, Value) in ValueList:
 | 
						|
        if Key == TAB_LANGUAGE_EN_X:
 | 
						|
            if UseFirstValue:
 | 
						|
                if not Value1:
 | 
						|
                    Value1 = Value
 | 
						|
            else:
 | 
						|
                Value1 = Value
 | 
						|
        if Key == TAB_LANGUAGE_EN_US:
 | 
						|
            if UseFirstValue:
 | 
						|
                if not Value2:
 | 
						|
                    Value2 = Value
 | 
						|
            else:
 | 
						|
                Value2 = Value
 | 
						|
        if Key == TAB_LANGUAGE_EN:
 | 
						|
            if UseFirstValue:
 | 
						|
                if not Value3:
 | 
						|
                    Value3 = Value
 | 
						|
            else:
 | 
						|
                Value3 = Value
 | 
						|
        if Key.startswith(TAB_LANGUAGE_EN):
 | 
						|
            if UseFirstValue:
 | 
						|
                if not Value4:
 | 
						|
                    Value4 = Value
 | 
						|
            else:
 | 
						|
                Value4 = Value
 | 
						|
        if Key == '':
 | 
						|
            if UseFirstValue:
 | 
						|
                if not Value5:
 | 
						|
                    Value5 = Value
 | 
						|
            else:
 | 
						|
                Value5 = Value
 | 
						|
            
 | 
						|
    if Value1:
 | 
						|
        return Value1
 | 
						|
    if Value2:
 | 
						|
        return Value2
 | 
						|
    if Value3:
 | 
						|
        return Value3
 | 
						|
    if Value4:
 | 
						|
        return Value4
 | 
						|
    if Value5:
 | 
						|
        return Value5
 | 
						|
    
 | 
						|
    return ''
 | 
						|
 | 
						|
 | 
						|
## GetCharIndexOutStr
 | 
						|
#
 | 
						|
# Get comment character index outside a string
 | 
						|
#
 | 
						|
# @param Line:              The string to be checked
 | 
						|
# @param CommentCharacter:  Comment char, used to ignore comment content
 | 
						|
#
 | 
						|
# @retval Index
 | 
						|
#
 | 
						|
def GetCharIndexOutStr(CommentCharacter, Line):
 | 
						|
    #
 | 
						|
    # remove whitespace
 | 
						|
    #
 | 
						|
    Line = Line.strip()
 | 
						|
 | 
						|
    #
 | 
						|
    # Check whether comment character is in a string
 | 
						|
    #
 | 
						|
    InString = False
 | 
						|
    for Index in range(0, len(Line)):
 | 
						|
        if Line[Index] == '"':
 | 
						|
            InString = not InString
 | 
						|
        elif Line[Index] == CommentCharacter and InString :
 | 
						|
            pass
 | 
						|
        elif Line[Index] == CommentCharacter and (Index +1) < len(Line) and Line[Index+1] == CommentCharacter \
 | 
						|
            and not InString :
 | 
						|
            return Index
 | 
						|
    return -1
 | 
						|
 | 
						|
## ValidateUNIFilePath
 | 
						|
#
 | 
						|
# Check the UNI file path
 | 
						|
#
 | 
						|
# @param FilePath: The UNI file path 
 | 
						|
#
 | 
						|
def ValidateUNIFilePath(Path):
 | 
						|
    Suffix = Path[Path.rfind(TAB_SPLIT):]
 | 
						|
    
 | 
						|
    #
 | 
						|
    # Check if the suffix is one of the '.uni', '.UNI', '.Uni' 
 | 
						|
    #
 | 
						|
    if Suffix not in TAB_UNI_FILE_SUFFIXS:
 | 
						|
        Logger.Error("Unicode File Parser", 
 | 
						|
                        ToolError.FORMAT_INVALID, 
 | 
						|
                        Message=ST.ERR_UNI_FILE_SUFFIX_WRONG, 
 | 
						|
                        ExtraData=Path)    
 | 
						|
    
 | 
						|
    #
 | 
						|
    # Check if '..' in the file name(without suffixe)
 | 
						|
    #
 | 
						|
    if (TAB_SPLIT + TAB_SPLIT) in Path:
 | 
						|
        Logger.Error("Unicode File Parser", 
 | 
						|
                        ToolError.FORMAT_INVALID, 
 | 
						|
                        Message=ST.ERR_UNI_FILE_NAME_INVALID, 
 | 
						|
                        ExtraData=Path)    
 | 
						|
    
 | 
						|
    #
 | 
						|
    # Check if the file name is valid according to the DEC and INF specification
 | 
						|
    #
 | 
						|
    Pattern = '[a-zA-Z0-9_][a-zA-Z0-9_\-\.]*'
 | 
						|
    FileName = Path.replace(Suffix, '')
 | 
						|
    InvalidCh = re.sub(Pattern, '', FileName)
 | 
						|
    if InvalidCh:
 | 
						|
        Logger.Error("Unicode File Parser", 
 | 
						|
                        ToolError.FORMAT_INVALID, 
 | 
						|
                        Message=ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID, 
 | 
						|
                        ExtraData=Path)    
 | 
						|
 |