1. Add a recovery mode for UPT failure 2. Add UNI file support 3. Add binary file header support 4. Add support for PCD error message 5. Add support for replace 6. Format generated INF/DEC files 7. Update dependency check 8. Other minor fixes Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Hess Chen <hesheng.chen@intel.com> Reviewed-by: Gao, Liming <liming.gao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15896 6f19259b-4bc3-4df7-8a09-765794883524
724 lines
20 KiB
Python
724 lines
20 KiB
Python
## @file ParserValidate.py
|
|
# Functions for parser validation
|
|
#
|
|
# 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.
|
|
#
|
|
|
|
'''
|
|
PaserValidate
|
|
'''
|
|
|
|
import os.path
|
|
import re
|
|
import platform
|
|
|
|
from Library.DataType import MODULE_LIST
|
|
from Library.DataType import COMPONENT_TYPE_LIST
|
|
from Library.DataType import PCD_USAGE_TYPE_LIST_OF_MODULE
|
|
from Library.DataType import TAB_SPACE_SPLIT
|
|
from Library.String import GetSplitValueList
|
|
from Library.ExpressionValidate import IsValidBareCString
|
|
from Library.ExpressionValidate import IsValidFeatureFlagExp
|
|
|
|
## __HexDigit() method
|
|
#
|
|
# Whether char input is a Hex data bit
|
|
#
|
|
# @param TempChar: The char to test
|
|
#
|
|
def __HexDigit(TempChar):
|
|
if (TempChar >= 'a' and TempChar <= 'f') or \
|
|
(TempChar >= 'A' and TempChar <= 'F') \
|
|
or (TempChar >= '0' and TempChar <= '9'):
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
## IsValidHex() method
|
|
#
|
|
# Whether char input is a Hex data.
|
|
#
|
|
# @param TempChar: The char to test
|
|
#
|
|
def IsValidHex(HexStr):
|
|
if not HexStr.upper().startswith("0X"):
|
|
return False
|
|
CharList = [c for c in HexStr[2:] if not __HexDigit(c)]
|
|
if len(CharList) == 0:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
## Judge the input string is valid bool type or not.
|
|
#
|
|
# <TRUE> ::= {"TRUE"} {"true"} {"True"} {"0x1"} {"0x01"}
|
|
# <FALSE> ::= {"FALSE"} {"false"} {"False"} {"0x0"} {"0x00"}
|
|
# <BoolType> ::= {<TRUE>} {<FALSE>}
|
|
#
|
|
# @param BoolString: A string contained the value need to be judged.
|
|
#
|
|
def IsValidBoolType(BoolString):
|
|
#
|
|
# Valid Ture
|
|
#
|
|
if BoolString == 'TRUE' or \
|
|
BoolString == 'True' or \
|
|
BoolString == 'true' or \
|
|
BoolString == '0x1' or \
|
|
BoolString == '0x01':
|
|
return True
|
|
#
|
|
# Valid False
|
|
#
|
|
elif BoolString == 'FALSE' or \
|
|
BoolString == 'False' or \
|
|
BoolString == 'false' or \
|
|
BoolString == '0x0' or \
|
|
BoolString == '0x00':
|
|
return True
|
|
#
|
|
# Invalid bool type
|
|
#
|
|
else:
|
|
return False
|
|
|
|
## Is Valid Module Type List or not
|
|
#
|
|
# @param ModuleTypeList: A list contain ModuleType strings need to be
|
|
# judged.
|
|
#
|
|
def IsValidInfMoudleTypeList(ModuleTypeList):
|
|
for ModuleType in ModuleTypeList:
|
|
return IsValidInfMoudleType(ModuleType)
|
|
|
|
## Is Valid Module Type or not
|
|
#
|
|
# @param ModuleType: A string contain ModuleType need to be judged.
|
|
#
|
|
def IsValidInfMoudleType(ModuleType):
|
|
if ModuleType in MODULE_LIST:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
## Is Valid Component Type or not
|
|
#
|
|
# @param ComponentType: A string contain ComponentType need to be judged.
|
|
#
|
|
def IsValidInfComponentType(ComponentType):
|
|
if ComponentType.upper() in COMPONENT_TYPE_LIST:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
|
|
## Is valid Tool Family or not
|
|
#
|
|
# @param ToolFamily: A string contain Tool Family need to be judged.
|
|
# Famlily := [A-Z]([a-zA-Z0-9])*
|
|
#
|
|
def IsValidToolFamily(ToolFamily):
|
|
ReIsValieFamily = re.compile(r"^[A-Z]+[A-Za-z0-9]{0,}$", re.DOTALL)
|
|
if ReIsValieFamily.match(ToolFamily) == None:
|
|
return False
|
|
return True
|
|
|
|
## Is valid Tool TagName or not
|
|
#
|
|
# The TagName sample is MYTOOLS and VS2005.
|
|
#
|
|
# @param TagName: A string contain Tool TagName need to be judged.
|
|
#
|
|
def IsValidToolTagName(TagName):
|
|
if TagName.strip() == '':
|
|
return True
|
|
if TagName.strip() == '*':
|
|
return True
|
|
if not IsValidWord(TagName):
|
|
return False
|
|
return True
|
|
|
|
## Is valid arch or not
|
|
#
|
|
# @param Arch The arch string need to be validated
|
|
# <OA> ::= (a-zA-Z)(A-Za-z0-9){0,}
|
|
# <arch> ::= {"IA32"} {"X64"} {"IPF"} {"EBC"} {<OA>}
|
|
# {"common"}
|
|
# @param Arch: Input arch
|
|
#
|
|
def IsValidArch(Arch):
|
|
if Arch == 'common':
|
|
return True
|
|
ReIsValieArch = re.compile(r"^[a-zA-Z]+[a-zA-Z0-9]{0,}$", re.DOTALL)
|
|
if ReIsValieArch.match(Arch) == None:
|
|
return False
|
|
return True
|
|
|
|
## Is valid family or not
|
|
#
|
|
# <Family> ::= {"MSFT"} {"GCC"} {"INTEL"} {<Usr>} {"*"}
|
|
# <Usr> ::= [A-Z][A-Za-z0-9]{0,}
|
|
#
|
|
# @param family: The family string need to be validated
|
|
#
|
|
def IsValidFamily(Family):
|
|
Family = Family.strip()
|
|
if Family == '*':
|
|
return True
|
|
|
|
if Family == '':
|
|
return True
|
|
|
|
ReIsValidFamily = re.compile(r"^[A-Z]+[A-Za-z0-9]{0,}$", re.DOTALL)
|
|
if ReIsValidFamily.match(Family) == None:
|
|
return False
|
|
return True
|
|
|
|
## Is valid build option name or not
|
|
#
|
|
# @param BuildOptionName: The BuildOptionName string need to be validated
|
|
#
|
|
def IsValidBuildOptionName(BuildOptionName):
|
|
if not BuildOptionName:
|
|
return False
|
|
|
|
ToolOptionList = GetSplitValueList(BuildOptionName, '_', 4)
|
|
|
|
if len(ToolOptionList) != 5:
|
|
return False
|
|
|
|
ReIsValidBuildOption1 = re.compile(r"^\s*(\*)|([A-Z][a-zA-Z0-9]*)$")
|
|
ReIsValidBuildOption2 = re.compile(r"^\s*(\*)|([a-zA-Z][a-zA-Z0-9]*)$")
|
|
|
|
if ReIsValidBuildOption1.match(ToolOptionList[0]) == None:
|
|
return False
|
|
|
|
if ReIsValidBuildOption1.match(ToolOptionList[1]) == None:
|
|
return False
|
|
|
|
if ReIsValidBuildOption2.match(ToolOptionList[2]) == None:
|
|
return False
|
|
|
|
if ToolOptionList[3] == "*" and ToolOptionList[4] not in ['FAMILY', 'DLL', 'DPATH']:
|
|
return False
|
|
|
|
return True
|
|
|
|
## IsValidToken
|
|
#
|
|
# Check if pattern string matches total token
|
|
#
|
|
# @param ReString: regular string
|
|
# @param Token: Token to be matched
|
|
#
|
|
def IsValidToken(ReString, Token):
|
|
Match = re.compile(ReString).match(Token)
|
|
return Match and Match.start() == 0 and Match.end() == len(Token)
|
|
|
|
## IsValidPath
|
|
#
|
|
# Check if path exist
|
|
#
|
|
# @param Path: Absolute path or relative path to be checked
|
|
# @param Root: Root path
|
|
#
|
|
def IsValidPath(Path, Root):
|
|
Path = Path.strip()
|
|
OrigPath = Path.replace('\\', '/')
|
|
|
|
Path = os.path.normpath(Path).replace('\\', '/')
|
|
Root = os.path.normpath(Root).replace('\\', '/')
|
|
FullPath = os.path.normpath(os.path.join(Root, Path)).replace('\\', '/')
|
|
|
|
if not os.path.exists(FullPath):
|
|
return False
|
|
|
|
#
|
|
# If Path is absolute path.
|
|
# It should be in Root.
|
|
#
|
|
if os.path.isabs(Path):
|
|
if not Path.startswith(Root):
|
|
return False
|
|
return True
|
|
|
|
#
|
|
# Check illegal character
|
|
#
|
|
for Rel in ['/', './', '../']:
|
|
if OrigPath.startswith(Rel):
|
|
return False
|
|
for Rel in ['//', '/./', '/../']:
|
|
if Rel in OrigPath:
|
|
return False
|
|
for Rel in ['/.', '/..', '/']:
|
|
if OrigPath.endswith(Rel):
|
|
return False
|
|
|
|
Path = Path.rstrip('/')
|
|
|
|
#
|
|
# Check relative path
|
|
#
|
|
for Word in Path.split('/'):
|
|
if not IsValidWord(Word):
|
|
return False
|
|
|
|
return True
|
|
|
|
## IsValidInstallPath
|
|
#
|
|
# Check if an install path valid or not.
|
|
#
|
|
# Absolute path or path starts with '.' or path contains '..' are invalid.
|
|
#
|
|
# @param Path: path to be checked
|
|
#
|
|
def IsValidInstallPath(Path):
|
|
if platform.platform().find("Windows") >= 0:
|
|
if os.path.isabs(Path):
|
|
return False
|
|
else:
|
|
if Path[1:2] == ':':
|
|
return False
|
|
if os.path.isabs(Path):
|
|
return False
|
|
if Path.startswith('.'):
|
|
return False
|
|
|
|
if Path.find('..') != -1:
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
## IsValidCFormatGuid
|
|
#
|
|
# Check if GUID format has the from of {8,4,4,{2,2,2,2,2,2,2,2}}
|
|
#
|
|
# @param Guid: Guid to be checked
|
|
#
|
|
def IsValidCFormatGuid(Guid):
|
|
#
|
|
# Valid: { 0xf0b11735, 0x87a0, 0x4193, {0xb2, 0x66, 0x53, 0x8c, 0x38,
|
|
# 0xaf, 0x48, 0xce }}
|
|
# Invalid: { 0xf0b11735, 0x87a0, 0x4193, {0xb2, 0x66, 0x53, 0x8c, 0x38,
|
|
# 0xaf, 0x48, 0xce }} 0x123
|
|
# Invalid: { 0xf0b1 1735, 0x87a0, 0x4193, {0xb2, 0x66, 0x53, 0x8c, 0x38,
|
|
# 0xaf, 0x48, 0xce }}
|
|
#
|
|
List = ['{', 10, ',', 6, ',', 6, ',{', 4, ',', 4, ',', 4,
|
|
',', 4, ',', 4, ',', 4, ',', 4, ',', 4, '}}']
|
|
Index = 0
|
|
Value = ''
|
|
SepValue = ''
|
|
for Char in Guid:
|
|
if Char not in '{},\t ':
|
|
Value += Char
|
|
continue
|
|
if Value:
|
|
try:
|
|
#
|
|
# Index may out of bound
|
|
#
|
|
if not SepValue or SepValue != List[Index]:
|
|
return False
|
|
Index += 1
|
|
SepValue = ''
|
|
|
|
if not Value.startswith('0x') and not Value.startswith('0X'):
|
|
return False
|
|
|
|
#
|
|
# Index may out of bound
|
|
#
|
|
if type(List[Index]) != type(1) or \
|
|
len(Value) > List[Index] or len(Value) < 3:
|
|
return False
|
|
|
|
#
|
|
# Check if string can be converted to integer
|
|
# Throw exception if not
|
|
#
|
|
int(Value, 16)
|
|
except BaseException:
|
|
#
|
|
# Exception caught means invalid format
|
|
#
|
|
return False
|
|
Value = ''
|
|
Index += 1
|
|
if Char in '{},':
|
|
SepValue += Char
|
|
|
|
return SepValue == '}}' and Value == ''
|
|
|
|
## IsValidPcdType
|
|
#
|
|
# Check whether the PCD type is valid
|
|
#
|
|
# @param PcdTypeString: The PcdType string need to be checked.
|
|
#
|
|
def IsValidPcdType(PcdTypeString):
|
|
if PcdTypeString.upper() in PCD_USAGE_TYPE_LIST_OF_MODULE:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
## IsValidWord
|
|
#
|
|
# Check whether the word is valid.
|
|
# <Word> ::= (a-zA-Z0-9_)(a-zA-Z0-9_-){0,} Alphanumeric characters with
|
|
# optional
|
|
# dash "-" and/or underscore "_" characters. No whitespace
|
|
# characters are permitted.
|
|
#
|
|
# @param Word: The word string need to be checked.
|
|
#
|
|
def IsValidWord(Word):
|
|
if not Word:
|
|
return False
|
|
#
|
|
# The first char should be alpha, _ or Digit.
|
|
#
|
|
if not Word[0].isalnum() and \
|
|
not Word[0] == '_' and \
|
|
not Word[0].isdigit():
|
|
return False
|
|
|
|
LastChar = ''
|
|
for Char in Word[1:]:
|
|
if (not Char.isalpha()) and \
|
|
(not Char.isdigit()) and \
|
|
Char != '-' and \
|
|
Char != '_' and \
|
|
Char != '.':
|
|
return False
|
|
if Char == '.' and LastChar == '.':
|
|
return False
|
|
LastChar = Char
|
|
|
|
return True
|
|
|
|
|
|
## IsValidSimpleWord
|
|
#
|
|
# Check whether the SimpleWord is valid.
|
|
# <SimpleWord> ::= (a-zA-Z0-9)(a-zA-Z0-9_-){0,}
|
|
# A word that cannot contain a period character.
|
|
#
|
|
# @param Word: The word string need to be checked.
|
|
#
|
|
def IsValidSimpleWord(Word):
|
|
ReIsValidSimpleWord = \
|
|
re.compile(r"^[0-9A-Za-z][0-9A-Za-z\-_]*$", re.DOTALL)
|
|
Word = Word.strip()
|
|
if not Word:
|
|
return False
|
|
|
|
if not ReIsValidSimpleWord.match(Word):
|
|
return False
|
|
|
|
return True
|
|
|
|
## IsValidDecVersion
|
|
#
|
|
# Check whether the decimal version is valid.
|
|
# <DecVersion> ::= (0-9){1,} ["." (0-9){1,}]
|
|
#
|
|
# @param Word: The word string need to be checked.
|
|
#
|
|
def IsValidDecVersion(Word):
|
|
if Word.find('.') > -1:
|
|
ReIsValidDecVersion = re.compile(r"[0-9]+\.?[0-9]+$")
|
|
else:
|
|
ReIsValidDecVersion = re.compile(r"[0-9]+$")
|
|
if ReIsValidDecVersion.match(Word) == None:
|
|
return False
|
|
return True
|
|
|
|
## IsValidHexVersion
|
|
#
|
|
# Check whether the hex version is valid.
|
|
# <HexVersion> ::= "0x" <Major> <Minor>
|
|
# <Major> ::= <HexDigit>{4}
|
|
# <Minor> ::= <HexDigit>{4}
|
|
#
|
|
# @param Word: The word string need to be checked.
|
|
#
|
|
def IsValidHexVersion(Word):
|
|
ReIsValidHexVersion = re.compile(r"[0][xX][0-9A-Fa-f]{8}$", re.DOTALL)
|
|
if ReIsValidHexVersion.match(Word) == None:
|
|
return False
|
|
|
|
return True
|
|
|
|
## IsValidBuildNumber
|
|
#
|
|
# Check whether the BUILD_NUMBER is valid.
|
|
# ["BUILD_NUMBER" "=" <Integer>{1,4} <EOL>]
|
|
#
|
|
# @param Word: The BUILD_NUMBER string need to be checked.
|
|
#
|
|
def IsValidBuildNumber(Word):
|
|
ReIsValieBuildNumber = re.compile(r"[0-9]{1,4}$", re.DOTALL)
|
|
if ReIsValieBuildNumber.match(Word) == None:
|
|
return False
|
|
|
|
return True
|
|
|
|
## IsValidDepex
|
|
#
|
|
# Check whether the Depex is valid.
|
|
#
|
|
# @param Word: The Depex string need to be checked.
|
|
#
|
|
def IsValidDepex(Word):
|
|
Index = Word.upper().find("PUSH")
|
|
if Index > -1:
|
|
return IsValidCFormatGuid(Word[Index+4:].strip())
|
|
|
|
ReIsValidCName = re.compile(r"^[A-Za-z_][0-9A-Za-z_\s\.]*$", re.DOTALL)
|
|
if ReIsValidCName.match(Word) == None:
|
|
return False
|
|
|
|
return True
|
|
|
|
## IsValidNormalizedString
|
|
#
|
|
# Check
|
|
# <NormalizedString> ::= <DblQuote> [{<Word>} {<Space>}]{1,} <DblQuote>
|
|
# <Space> ::= 0x20
|
|
#
|
|
# @param String: string to be checked
|
|
#
|
|
def IsValidNormalizedString(String):
|
|
if String == '':
|
|
return True
|
|
|
|
for Char in String:
|
|
if Char == '\t':
|
|
return False
|
|
|
|
StringList = GetSplitValueList(String, TAB_SPACE_SPLIT)
|
|
|
|
for Item in StringList:
|
|
if not Item:
|
|
continue
|
|
if not IsValidWord(Item):
|
|
return False
|
|
|
|
return True
|
|
|
|
## IsValidIdString
|
|
#
|
|
# Check whether the IdString is valid.
|
|
#
|
|
# @param IdString: The IdString need to be checked.
|
|
#
|
|
def IsValidIdString(String):
|
|
if IsValidSimpleWord(String.strip()):
|
|
return True
|
|
|
|
if String.strip().startswith('"') and \
|
|
String.strip().endswith('"'):
|
|
String = String[1:-1]
|
|
if String.strip() == "":
|
|
return True
|
|
if IsValidNormalizedString(String):
|
|
return True
|
|
|
|
return False
|
|
|
|
## IsValidVersionString
|
|
#
|
|
# Check whether the VersionString is valid.
|
|
# <AsciiString> ::= [ [<WhiteSpace>]{0,} [<AsciiChars>]{0,} ] {0,}
|
|
# <WhiteSpace> ::= {<Tab>} {<Space>}
|
|
# <Tab> ::= 0x09
|
|
# <Space> ::= 0x20
|
|
# <AsciiChars> ::= (0x21 - 0x7E)
|
|
#
|
|
# @param VersionString: The VersionString need to be checked.
|
|
#
|
|
def IsValidVersionString(VersionString):
|
|
VersionString = VersionString.strip()
|
|
for Char in VersionString:
|
|
if not (Char >= 0x21 and Char <= 0x7E):
|
|
return False
|
|
|
|
return True
|
|
|
|
## IsValidPcdValue
|
|
#
|
|
# Check whether the PcdValue is valid.
|
|
#
|
|
# @param VersionString: The PcdValue need to be checked.
|
|
#
|
|
def IsValidPcdValue(PcdValue):
|
|
for Char in PcdValue:
|
|
if Char == '\n' or Char == '\t' or Char == '\f':
|
|
return False
|
|
|
|
#
|
|
# <Boolean>
|
|
#
|
|
if IsValidFeatureFlagExp(PcdValue, True)[0]:
|
|
return True
|
|
|
|
#
|
|
# <Number> ::= {<Integer>} {<HexNumber>}
|
|
# <Integer> ::= {(0-9)} {(1-9)(0-9){1,}}
|
|
# <HexNumber> ::= "0x" <HexDigit>{1,}
|
|
# <HexDigit> ::= (a-fA-F0-9)
|
|
#
|
|
if IsValidHex(PcdValue):
|
|
return True
|
|
|
|
ReIsValidIntegerSingle = re.compile(r"^\s*[0-9]\s*$", re.DOTALL)
|
|
if ReIsValidIntegerSingle.match(PcdValue) != None:
|
|
return True
|
|
|
|
ReIsValidIntegerMulti = re.compile(r"^\s*[1-9][0-9]+\s*$", re.DOTALL)
|
|
if ReIsValidIntegerMulti.match(PcdValue) != None:
|
|
return True
|
|
|
|
#
|
|
# <StringVal> ::= {<StringType>} {<Array>} {"$(" <MACRO> ")"}
|
|
# <StringType> ::= {<UnicodeString>} {<CString>}
|
|
#
|
|
ReIsValidStringType = re.compile(r"^\s*[\"L].*[\"]\s*$")
|
|
if ReIsValidStringType.match(PcdValue):
|
|
IsTrue = False
|
|
if PcdValue.strip().startswith('L\"'):
|
|
StringValue = PcdValue.strip().lstrip('L\"').rstrip('\"')
|
|
if IsValidBareCString(StringValue):
|
|
IsTrue = True
|
|
elif PcdValue.strip().startswith('\"'):
|
|
StringValue = PcdValue.strip().lstrip('\"').rstrip('\"')
|
|
if IsValidBareCString(StringValue):
|
|
IsTrue = True
|
|
if IsTrue:
|
|
return IsTrue
|
|
|
|
#
|
|
# <Array> ::= {<CArray>} {<NList>} {<CFormatGUID>}
|
|
# <CArray> ::= "{" [<NList>] <CArray>{0,} "}"
|
|
# <NList> ::= <HexByte> ["," <HexByte>]{0,}
|
|
# <HexDigit> ::= (a-fA-F0-9)
|
|
# <HexByte> ::= "0x" <HexDigit>{1,2}
|
|
#
|
|
if IsValidCFormatGuid(PcdValue):
|
|
return True
|
|
|
|
ReIsValidByteHex = re.compile(r"^\s*0x[0-9a-fA-F]{1,2}\s*$", re.DOTALL)
|
|
if PcdValue.strip().startswith('{') and PcdValue.strip().endswith('}') :
|
|
StringValue = PcdValue.strip().lstrip('{').rstrip('}')
|
|
ValueList = StringValue.split(',')
|
|
AllValidFlag = True
|
|
for ValueItem in ValueList:
|
|
if not ReIsValidByteHex.match(ValueItem.strip()):
|
|
AllValidFlag = False
|
|
|
|
if AllValidFlag:
|
|
return True
|
|
|
|
#
|
|
# NList
|
|
#
|
|
AllValidFlag = True
|
|
ValueList = PcdValue.split(',')
|
|
for ValueItem in ValueList:
|
|
if not ReIsValidByteHex.match(ValueItem.strip()):
|
|
AllValidFlag = False
|
|
|
|
if AllValidFlag:
|
|
return True
|
|
|
|
return False
|
|
|
|
## IsValidCVariableName
|
|
#
|
|
# Check whether the PcdValue is valid.
|
|
#
|
|
# @param VersionString: The PcdValue need to be checked.
|
|
#
|
|
def IsValidCVariableName(CName):
|
|
ReIsValidCName = re.compile(r"^[A-Za-z_][0-9A-Za-z_]*$", re.DOTALL)
|
|
if ReIsValidCName.match(CName) == None:
|
|
return False
|
|
|
|
return True
|
|
|
|
## IsValidIdentifier
|
|
#
|
|
# <Identifier> ::= <NonDigit> <Chars>{0,}
|
|
# <Chars> ::= (a-zA-Z0-9_)
|
|
# <NonDigit> ::= (a-zA-Z_)
|
|
#
|
|
# @param Ident: identifier to be checked
|
|
#
|
|
def IsValidIdentifier(Ident):
|
|
ReIdent = re.compile(r"^[A-Za-z_][0-9A-Za-z_]*$", re.DOTALL)
|
|
if ReIdent.match(Ident) == None:
|
|
return False
|
|
|
|
return True
|
|
|
|
## IsValidDecVersionVal
|
|
#
|
|
# {(0-9){1,} "." (0-99)}
|
|
#
|
|
# @param Ver: version to be checked
|
|
#
|
|
def IsValidDecVersionVal(Ver):
|
|
ReVersion = re.compile(r"[0-9]+(\.[0-9]{1,2})$")
|
|
|
|
if ReVersion.match(Ver) == None:
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
## IsValidLibName
|
|
#
|
|
# (A-Z)(a-zA-Z0-9){0,} and could not be "NULL"
|
|
#
|
|
def IsValidLibName(LibName):
|
|
if LibName == 'NULL':
|
|
return False
|
|
ReLibName = re.compile("^[A-Z]+[a-zA-Z0-9]*$")
|
|
if not ReLibName.match(LibName):
|
|
return False
|
|
|
|
return True
|
|
|
|
# IsValidUserId
|
|
#
|
|
# <UserId> ::= (a-zA-Z)(a-zA-Z0-9_.){0,}
|
|
# Words that contain period "." must be encapsulated in double quotation marks.
|
|
#
|
|
def IsValidUserId(UserId):
|
|
UserId = UserId.strip()
|
|
Quoted = False
|
|
if UserId.startswith('"') and UserId.endswith('"'):
|
|
Quoted = True
|
|
UserId = UserId[1:-1]
|
|
if not UserId or not UserId[0].isalpha():
|
|
return False
|
|
for Char in UserId[1:]:
|
|
if not Char.isalnum() and not Char in '_.':
|
|
return False
|
|
if Char == '.' and not Quoted:
|
|
return False
|
|
return True
|
|
|