From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 134.134.136.126, mailfrom: zhijux.fan@intel.com) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by groups.io with SMTP; Fri, 21 Jun 2019 03:02:23 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 21 Jun 2019 03:02:22 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.63,400,1557212400"; d="scan'208";a="160932389" Received: from fmsmsx108.amr.corp.intel.com ([10.18.124.206]) by fmsmga008.fm.intel.com with ESMTP; 21 Jun 2019 03:02:22 -0700 Received: from fmsmsx605.amr.corp.intel.com (10.18.126.85) by FMSMSX108.amr.corp.intel.com (10.18.124.206) with Microsoft SMTP Server (TLS) id 14.3.439.0; Fri, 21 Jun 2019 03:02:22 -0700 Received: from fmsmsx605.amr.corp.intel.com (10.18.126.85) by fmsmsx605.amr.corp.intel.com (10.18.126.85) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1713.5; Fri, 21 Jun 2019 03:02:21 -0700 Received: from shsmsx154.ccr.corp.intel.com (10.239.6.54) by fmsmsx605.amr.corp.intel.com (10.18.126.85) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.1.1713.5 via Frontend Transport; Fri, 21 Jun 2019 03:02:21 -0700 Received: from shsmsx101.ccr.corp.intel.com ([169.254.1.87]) by SHSMSX154.ccr.corp.intel.com ([169.254.7.156]) with mapi id 14.03.0439.000; Fri, 21 Jun 2019 18:02:20 +0800 From: "Fan, ZhijuX" To: Leif Lindholm CC: "devel@edk2.groups.io" , "Gao, Liming" , "Feng, Bob C" , Ard Biesheuvel , "Kinney, Michael D" Subject: Re: [edk2-platform patch 2/2] Platform/Intel:Add UniTool into edk2-platforms/Platform/Intel/Tools Thread-Topic: [edk2-platform patch 2/2] Platform/Intel:Add UniTool into edk2-platforms/Platform/Intel/Tools Thread-Index: AdUn1OLEUhPU+i5FRWas19TdlxjT4f//8KuA//9sw+A= Date: Fri, 21 Jun 2019 10:02:18 +0000 Message-ID: References: <20190621090405.fi3gs225afoxyaml@bivouac.eciton.net> In-Reply-To: <20190621090405.fi3gs225afoxyaml@bivouac.eciton.net> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-product: dlpe-windows dlp-version: 11.0.600.7 dlp-reaction: no-action x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Return-Path: zhijux.fan@intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable There are several reasons why argparse is not used: 1. The logic and parameters of this script are simple. 2. This script is ported from another directory, Only functional changes ha= ve been made to it,=20 and its architecture is basically unchanged, 3. Printing a Help Message when an error occurs is an original feature of t= he script,=20 so it is not modified for argparse. Any question, please let me know. Thanks. Best Regards Fan Zhiju > -----Original Message----- > From: Leif Lindholm [mailto:leif.lindholm@linaro.org] > Sent: Friday, June 21, 2019 5:04 PM > To: Fan, ZhijuX > Cc: devel@edk2.groups.io; Gao, Liming ; Feng, Bob C > ; Ard Biesheuvel ; > Kinney, Michael D > Subject: Re: [edk2-platform patch 2/2] Platform/Intel:Add UniTool into ed= k2- > platforms/Platform/Intel/Tools >=20 > On Fri, Jun 21, 2019 at 01:58:57AM +0000, Fan, ZhijuX wrote: > > BZ:https://bugzilla.tianocore.org/show_bug.cgi?id=3D1855 > > > > UniTool is one python script to generate UQI (Universal Question > > Identifier) unicode string for HII question PROMPT string. UQI string > > can be used to identify each HII question. > > The scripts function will sync up UQI definitions with uni files based > > on vfi/vfr/hfr/sd/sdi in the tree. > > > > This script can be run in both Py2 and Py3. > > > > Cc: Liming Gao > > Cc: Bob Feng > > Cc: Ard Biesheuvel > > Cc: Leif Lindholm > > Cc: Michael D Kinney > > Signed-off-by: Zhiju.Fan > > --- > > Platform/Intel/Tools/UniTool/UniTool.py | 515 > > ++++++++++++++++++++++++++++++++ > > 1 file changed, 515 insertions(+) > > create mode 100644 Platform/Intel/Tools/UniTool/UniTool.py > > > > diff --git a/Platform/Intel/Tools/UniTool/UniTool.py > > b/Platform/Intel/Tools/UniTool/UniTool.py > > new file mode 100644 > > index 0000000000..aec25b51c2 > > --- /dev/null > > +++ b/Platform/Intel/Tools/UniTool/UniTool.py > > @@ -0,0 +1,515 @@ > > +## @file > > +# generate UQI (Universal Question Identifier) unicode string for HII > > +question PROMPT string. UQI string can be used to # identify each HII > question. > > +# > > +# Copyright (c) 2019, Intel Corporation. All rights reserved. > > +# > > +# SPDX-License-Identifier: BSD-2-Clause-Patent # > > + > > +import re > > +import sys > > +import os > > +import getopt > > +import codecs > > +import fnmatch > > +import logging > > + > > +# global variable declarations > > +QuestionError =3D False > > +UqiList =3D re.compile('^#string[ \t]+([A-Z_0- > 9]+)[ \t]+#language[ \t]+uqi[ \t\r\n]+"(?:[x\S]{1,2})([0-9a-fA-F]{4,5})"'= , > > + re.M).findall > > +AllUqis =3D {} > > +StringDict =3D {} > > +GlobalVarId =3D {} > > +Options =3D {} > > + > > + > > +# > > > +********************************************************* > ************ > > +* # description: Prints help information # > > +# arguments: none > > +# > > +# returns: none > > +# > > + > > +def Usage(): >=20 > Why not use argparse? >=20 > / > Leif >=20 > > + print("Syntax: %s [-b] [-u] [-l] [-x] [-h] [-d 'rootDirectory1'] > > +[-d 'rootDirectory2'] [-d 'rootDirectory3']... [-q e|w] \ 'rootDirecto= ry0' > 'uqiFile'|'uqiFileDirectory' ['excludedDirectory1'] ['excludedDirectory2'= ] > ['excludedDirectory3']...\n%s" % > > + (os.path.basename(sys.argv[0]), > > + """\nFunction will sync up UQI definitions with uni files b= ased on > vfi/vfr/hfr/sd/sdi in the tree.\n > > + Required Arguments: > > + 'rootdirectory0' path to root directory > > + 'uqiFileDirectory' path to UQI file(UqiList.uni) > > + 'uqiFile' UQI file > > + > > + Options: > > + -h Show this help > > + -b Build option returns error if any new UQI= needs assigning > > + based on vfi/vfr/hfr/sd/sdi when no -u op= tion is specified > > + -u Create new UQIs that does not already exi= st in uqiFile for > > + any string requiring a UQI based on vfi/v= fr/hfr/sd/sdi > > + NOTE: 'uqiFile' cannot be readonly! > > + -l Language deletion option (keeps only Engl= ish and uqi) > > + moves all UQIs to 'uqiFile' > > + NOTE: Uni files cannot be readonly! > > + -x Exclude 'rootDirectory'/'excludedDirector= y1' & > > + 'rootDirectory'/'excludedDirectory2'... f= rom UQI list build > > + NOTE: Cannot be the same as rootDirectory > > + -d Add multiple root directories to process > > + -q Print warning(w) or return error(e) if di= fferent HII > questions > > + are referring same string token > > + > > + Return error if any duplicated UQI string or value in UQI list or= if no > definition > > + for any string referred by HII question when -b or -u is > > + specified > > + > > + NOTE: Options must be specified before parameters > > + """)) > > + sys.exit() > > + > > + > > +# > > > +********************************************************* > ************ > > +* > > +# description: Get uni file encoding > > +# > > +# arguments: Filename - name of uni file > > +# > > +# returns: utf-8 or utf-16 > > +# > > +def GetUniFileEncoding(Filename): > > + # > > + # Detect Byte Order Mark at beginning of file. Default to UTF-8 > > + # > > + Encoding =3D 'utf-8' > > + > > + # > > + # Read file > > + # > > + try: > > + with open(Filename, mode=3D'rb') as UniFile: > > + FileIn =3D UniFile.read() > > + except: > > + return Encoding > > + > > + if (FileIn.startswith(codecs.BOM_UTF16_BE) or > FileIn.startswith(codecs.BOM_UTF16_LE)): > > + Encoding =3D 'utf-16' > > + > > + return Encoding > > + > > + > > +# rewrite function os.path.walk > > +def Walk(Top, Func, Arg): > > + try: > > + Names =3D os.listdir(Top) > > + except os.error: > > + return > > + Func(Arg, Top, Names) > > + for Name in Names: > > + Name =3D os.path.join(Top, Name) > > + if os.path.isdir(Name): > > + Walk(Name, Func, Arg) > > + > > + > > +# > > > +********************************************************* > ************ > > +* # description: Parses commandline arguments and options > > +# Calls function processUni to build dictionary of string= s > > +# Calls other functions according to user specified optio= ns > > +# > > +# arguments: argv - contains all input from command line > > +# - must contain path to root directory > > +# - may contain options -h, -u, -l, -b or -x before = path > > +# > > +# returns: none > > +# > > +def main(argv): > > + ##### Read input arguments and options > > + global AllUqis, UqiList, QuestionError > > + try: > > + Opts, Args =3D getopt.getopt(argv[1:], "hulbxd:q:") # each le= tter is an > optional argument > > + except getopt.GetoptError: > > + Usage() > > + try: > > + DirNameList =3D [Args[0]] > > + QuestionOption =3D None > > + for EachOpt in Opts: > > + if EachOpt[0] =3D=3D '-d': > > + DirNameList.append(EachOpt[1]) > > + if EachOpt[0] =3D=3D '-q': > > + QuestionOption =3D EachOpt[1] > > + if (QuestionOption !=3D "e") and (QuestionOption !=3D = "w"): > > + print("\nERROR: invalid option value for -q option= \n") > > + return > > + Destname =3D Args[1] > > + if len(Args) > 2: > > + ExDirList =3D Args[2:] > > + except: > > + Usage() > > + > > + UpdateUQIs =3D False > > + LangOption =3D False > > + BuildOption =3D False > > + ExcludeOption =3D False > > + ExPathList =3D [] > > + > > + for Opt, Args in Opts: > > + if Opt =3D=3D "-h": > > + Usage() > > + if Opt =3D=3D "-b": > > + BuildOption =3D True > > + if Opt =3D=3D "-u": > > + BuildOption =3D True > > + UpdateUQIs =3D True > > + if Opt =3D=3D "-l": > > + LangOption =3D True > > + if Opt =3D=3D "-x": > > + ExcludeOption =3D True > > + try: > > + for EachExDir in ExDirList: > > + for EachRootDir in DirNameList: > > + if EachExDir =3D=3D EachRootDir: > > + print("\nERROR: excludedDirectory is same = as > rootDirectory\n") > > + return > > + ExPathList.append(EachRootDir + os.sep + EachExDir= ) > > + except: > > + Usage() > > + > > + global Options > > + Options =3D {'Destname': Destname, 'DirNameList': DirNameList, > 'ExPathList': ExPathList, 'BuildOption': BuildOption, > > + 'UpdateUQIs': UpdateUQIs, 'LangOption': LangOption, > 'ExcludeOption': ExcludeOption, > > + 'QuestionOption': QuestionOption} > > + print("UQI file: %s" % Destname) > > + for EachDirName in DirNameList: > > + Walk(EachDirName, processUni, None) > > + if QuestionError: > > + return > > + if os.path.isdir(Options['Destname']): > > + DestFileName =3D Options['Destname'] + os.sep + 'UqiList.uni' > > + else: > > + DestFileName =3D Options['Destname'] > > + if os.path.exists(DestFileName) and (DestFileName not in > list(AllUqis.keys())): > > + try: > > + Encoding =3D GetUniFileEncoding(DestFileName) > > + with codecs.open(DestFileName, 'r+', Encoding) as destFile= : > > + DestFileBuffer =3D destFile.read() > > + except IOError as e: > > + print("ERROR: " + e.args[1]) > > + return > > + AllUqis[DestFileName] =3D UqiList(DestFileBuffer) > > + if BuildOption: > > + ReturnVal =3D newUqi() > > + if (ReturnVal =3D=3D 1): > > + print('Please fix UQI ERROR(s) above before proceeding.') > > + else: > > + print("No UQI issues detected\n") > > + return > > + > > + > > +# > > > +********************************************************* > ************ > > +* # description: newUqi collects a list of all currently used uqi > > +values in the tree > > +# Halt build if any duplicated string or value in UQI lis= t. > > +# If -u option was specified, creates new UQIs that does = not > > +# already exist in uqiFile for any string requiring a UQI= . > > +# > > +# arguments: none > > +# > > +# returns: 0 on success > > +# 1 on error - this should cause the build to halt > > +# > > + > > +Syntax =3D "S" > > +SyntaxRE =3D re.compile('#string[ \t]+[A-Z_0-9]+[ \t]+#language[ > > +\t]+uqi[ \t\r\n]+"([x\S]{1,2}).*', re.DOTALL).findall > > + > > + > > +def newUqi(): > > + global Options, GlobalVarId, AllUqis, Syntax, SyntaxRE > > + UqiRange =3D [] > > + UqiStringList =3D [] > > + CreateUQI =3D [] > > + ReturnVal =3D 0 > > + BaseNumSpaces =3D 47 # Used to line up the UQI values in the > > +resulting uqiFile > > + > > + # Look for duplication in the current UQIs and collect current ran= ge of > UQIs > > + for path in AllUqis.keys(): > > + for UqiString in AllUqis[path]: # path contains the path and = Filename > of each uni file > > + # Checks for duplicated strings in UQI list > > + for TempString in UqiStringList: > > + if TempString =3D=3D UqiString[0]: > > + print("ERROR: UQI string %s was assigned more than= once and > will cause corruption!" % UqiString[0]) > > + print("Delete one occurrence of the string and rer= un tool.") > > + ReturnVal =3D 1 # halt build > > + > > + UqiStringList.append(UqiString[0]) > > + > > + # Checks for duplicated UQI values in UQI list > > + if int(UqiString[1], 16) in UqiRange: > > + print("ERROR: UQI value %04x was assigned more than on= ce and > will cause corruption!" % int(UqiString[1], > > + = 16)) > > + print("Delete one occurrance of the UQI and rerun tool= to create > alternate value.") > > + ReturnVal =3D 1 # halt build > > + UqiRange.append(int(UqiString[1], 16)) > > + > > + for StringValue in GlobalVarId.keys(): > > + StringFound =3D False > > + for path in StringDict.keys(): > > + for UniString in StringDict[path]: # path contains the pa= th and > Filename of each uni file > > + if (StringValue =3D=3D UniString): > > + StringFound =3D True > > + break > > + if not StringFound: > > + print("ERROR: No definition for %s referred by HII questio= n" % > (StringValue)) > > + ReturnVal =3D 1 # halt build > > + > > + # Require a UQI for any string in vfr/vfi files > > + for StringValue in GlobalVarId.keys(): > > + # Ignore strings defined as STRING_TOKEN(0) > > + if (StringValue !=3D "0"): > > + # Check if this string already exists in the UQI list > > + if (StringValue not in UqiStringList) and (StringValue not= in > CreateUQI): > > + CreateUQI.append(StringValue) > > + if not Options['UpdateUQIs']: > > + print("ERROR: No UQI for %s referred by HII questi= on" % > (StringValue)) > > + ReturnVal =3D 1 # halt build after printing all > > + error messages > > + > > + if (ReturnVal =3D=3D 1): > > + return ReturnVal > > + > > + # Update uqiFile with necessary UQIs > > + if Options['UpdateUQIs'] and CreateUQI: > > + if os.path.isdir(Options['Destname']): > > + DestFileName =3D Options['Destname'] + os.sep + 'UqiList.u= ni' > > + else: > > + DestFileName =3D Options['Destname'] > > + try: > > + Encoding =3D GetUniFileEncoding(DestFileName) > > + with codecs.open(DestFileName, 'r+', Encoding) as OutputFi= le: > > + PlatformUQI =3D OutputFile.read() > > + except IOError as e: > > + print("ERROR: " + e.args[1]) > > + if (e.args[0] =3D=3D 2): > > + try: > > + with codecs.open(DestFileName, 'w', Encoding) as O= utputFile: > > + print(DestFileName + " did not exist. Creatin= g new file.") > > + PlatformUQI =3D '' > > + except: > > + print("Error creating " + DestFileName + ".") > > + return 1 > > + if (e.args[1] =3D=3D "Permission denied"): > > + print( > > + "\n%s is Readonly. You must uncheck the ReadOnly = attibute to > run the -u option.\n" % DestFileName) > > + return 1 > > + > > + # Determines and sets the UQI number format > > + # TODO: there is probably a more elegant way to do this... > > + SyntaxL =3D SyntaxRE(PlatformUQI) > > + if len(SyntaxL) !=3D 0: > > + Syntax =3D SyntaxL[0] > > + > > + # script is reading the file in and writing it back instead of= appending > because the codecs module > > + # automatically adds a BOM wherever you start writing. This ca= used > build failure. > > + UqiRange.sort() > > + if (UqiRange =3D=3D []): > > + NextUqi =3D 0 > > + else: > > + NextUqi =3D UqiRange[len(UqiRange) - 1] + 1 > > + > > + for StringValue in CreateUQI: > > + print("%s will be assigned a new UQI value" % StringValue) > > + UqiRange.append(NextUqi) > > + # > > + # Lines up the UQI values in the resulting uqiFile > > + # > > + Spaces =3D " " * (BaseNumSpaces - len(StringValue)) > > + PlatformUQI +=3D '#string %s%s #language uqi \"%s%04x\"\r\= n' % > (StringValue, Spaces, Syntax, NextUqi) > > + print("#string %s%s #language uqi \"%s%04X\"" % (StringVa= lue, > Spaces, Syntax, NextUqi)) > > + NextUqi +=3D 1 > > + > > + with codecs.open(DestFileName, 'r+', Encoding) as OutputFile: > > + OutputFile.seek(0) > > + OutputFile.write(PlatformUQI) > > + > > + return 0 > > + > > + > > +# > > > +********************************************************* > ************ > > +* # description: Parses each uni file to collect dictionary of > > +strings > > +# Removes additional languages and overwrites current uni= files > > +# if -l option was specified > > +# > > +# arguments: path - directory location of file including file name > > +# Filename - name of file to be modified > > +# > > +# returns: error string if failure occurred; > > +# none if completed sucessfully > > +# > > +# the following are global so that parsefile is quicker > > + > > +FindUniString =3D re.compile( > > + '^#string[ \t]+([A-Z_0-9]+)(?:[ \t\r\n]+#language[ \t]+[a-zA-Z- > ]{2,5}[ \t\r\n]+".*"[ \t]*[\r]?[\n]?)*', > > + re.M).findall > > + > > +OtherLang =3D re.compile( > > + '^#string[ \t]+[A-Z_0-9]+(?:[ \t\r\n]+#language[ > > +\t]+[a-zA-Z-]{2,5}[ \t\r\n]+".*"[ \t]*[\r]?[\n]?)*', re.M).findall > > +EachLang =3D re.compile('[ \t\r\n]+#language[ \t]+([a-zA-Z-]{2,5})[ > > +\t\r\n]+".*"[ \t]*[\r]?[\n]?').findall > > + > > +UqiStrings =3D re.compile('^#string[ \t]+[A-Z_0-9]+[ \t]+#language[ > > +\t]+uqi[ \t\r\n]+".*"[ \t]*[\r]?[\n]?', re.M) > > + > > + > > +def parsefile(path, Filename): > > + global Options, StringDict, AllUqis, UqiList, FindUniString, > > +OtherLang, EachLang, UqiStrings > > + > > + FullPath =3D path + os.sep + Filename > > + > > + try: > > + UniEncoding =3D GetUniFileEncoding(FullPath) > > + with codecs.open(FullPath, 'r', UniEncoding) as UniFile: > > + Databuffer =3D UniFile.read() > > + except: > > + print("Error opening " + FullPath + " for reading.") > > + return > > + WriteFile =3D False > > + > > + if os.path.isdir(Options['Destname']): > > + DestFileName =3D Options['Destname'] + os.sep + 'UqiList.uni' > > + else: > > + DestFileName =3D Options['Destname'] > > + > > + if Options['LangOption']: > > + try: > > + UqiEncoding =3D GetUniFileEncoding(DestFileName) > > + with codecs.open(DestFileName, 'r+', UqiEncoding) as Outpu= tFile: > > + PlatformUQI =3D OutputFile.read() > > + except IOError as e: > > + print("ERROR: " + e.args[1]) > > + if (e.args[0] =3D=3D 2): > > + try: > > + with codecs.open(DestFileName, 'w', UqiEncoding) a= s > OutputFile: > > + print(DestFileName + " did not exist. Creatin= g new file.") > > + PlatformUQI =3D '' > > + except: > > + print("Error creating " + DestFileName + ".") > > + return > > + else: > > + print("Error opening " + DestFileName + " for appendin= g.") > > + return > > + > > + if (Filename !=3D DestFileName.split(os.sep)[-1]): > > + Uqis =3D re.findall(UqiStrings, Databuffer) > > + if Uqis: > > + for Uqi in Uqis: > > + PlatformUQI +=3D Uqi > > + with codecs.open(DestFileName, 'r+', UqiEncoding) as O= utputFile: > > + OutputFile.seek(0) > > + OutputFile.write(PlatformUQI) > > + Databuffer =3D re.sub(UqiStrings, '', Databuffer) > > + if Uqis: > > + WriteFile =3D True > > + print("Deleted uqis from %s" % FullPath) > > + stringlist =3D OtherLang(Databuffer) > > + for stringfound in stringlist: > > + ThisString =3D EachLang(stringfound) > > + for LanguageFound in ThisString: > > + if ((LanguageFound !=3D 'en') and (LanguageFound != =3D 'en-US') and > (LanguageFound !=3D 'eng') and ( > > + LanguageFound !=3D 'uqi')): > > + Databuffer =3D re.sub(re.escape(stringfound), = '', Databuffer) > > + WriteFile =3D True > > + print("Deleted %s from %s" % (LanguageFound, F= ullPath)) > > + if (Filename !=3D DestFileName.split(os.sep)[-1]): > > + # adding strings to dictionary > > + StringDict[r'%s' % FullPath] =3D FindUniString(Databuffer) > > + # adding UQIs to dictionary > > + AllUqis[r'%s' % FullPath] =3D UqiList(Databuffer) > > + > > + if WriteFile: > > + try: > > + with codecs.open(FullPath, 'w', UniEncoding) as UniFile: > > + UniFile.write(Databuffer) > > + except: > > + print("Error opening " + FullPath + " for writing.") > > + return > > + > > + > > +# > > > +********************************************************* > ************ > > +* # description: Searches tree for uni files > > +# Calls parsefile to collect dictionary of strings in eac= h uni file > > +# Calls searchVfiFile for each vfi or vfr file found > > +# > > +# arguments: argument list is built by os.path.walk function call > > +# arg - None > > +# dirname - directory location of files > > +# names - specific files to search in directory > > +# > > +# returns: none > > +# > > +def processUni(args, dirname, names): > > + global Options > > + # Remove excludedDirectory > > + if Options['ExcludeOption']: > > + for EachExDir in Options['ExPathList']: > > + for dir in names: > > + if os.path.join(dirname, dir) =3D=3D EachExDir: > > + names.remove(dir) > > + > > + for entry in names: > > + FullPath =3D dirname + os.sep + entry > > + if fnmatch.fnmatch(FullPath, '*.uni'): > > + parsefile(dirname, entry) > > + if fnmatch.fnmatch(FullPath, '*.vf*'): > > + searchVfiFile(FullPath) > > + if fnmatch.fnmatch(FullPath, '*.sd'): > > + searchVfiFile(FullPath) > > + if fnmatch.fnmatch(FullPath, '*.sdi'): > > + searchVfiFile(FullPath) > > + if fnmatch.fnmatch(FullPath, '*.hfr'): > > + searchVfiFile(FullPath) > > + return > > + > > + > > +# > > > +********************************************************* > ************ > > +* # description: Compose a dictionary of all strings that may need > > +UQIs assigned > > +# to them and key is the string > > +# > > +# arguments: Filename - name of file to search for strings > > +# > > +# returns: none > > +# > > + > > +# separate regexes for readability > > +StringGroups =3D re.compile( > > + > '^[ \t]*(?:oneof|numeric|checkbox|orderedlist)[ \t]+varid.+?(?:endoneof|e > ndnumeric|endcheckbox|endorderedlist);', > > + re.DOTALL | re.M).findall > > +StringVarIds =3D re.compile( > > + '[ \t]*(?:oneof|numeric|checkbox|orderedlist)[ \t]+varid[ \t]*=3D[ > > +\t]*([a-zA-Z_0-9]+\.[a-zA-Z_0-9]+)').findall > > +StringTokens =3D re.compile('prompt[ \t]*=3D[ \t]*STRING_TOKEN[ > > +\t]*\(([a-zA-Z_0-9]+)\)').findall > > + > > + > > +def searchVfiFile(Filename): > > + global Options, GlobalVarId, StringGroups, StringVarIds, StringTok= ens, > QuestionError > > + try: > > + with open(Filename, 'r') as VfiFile: > > + Databuffer =3D VfiFile.read() > > + > > + # Finds specified lines in file > > + VfiStringGroup =3D StringGroups(Databuffer) > > + > > + # Searches for prompts within specified lines > > + for EachGroup in VfiStringGroup: > > + for EachString in StringTokens(EachGroup): > > + # Ignore strings defined as STRING_TOKEN(0), > STRING_TOKEN(STR_EMPTY) or STRING_TOKEN(STR_NULL) > > + if (EachString !=3D "0") and (EachString !=3D "STR_EMP= TY") and > (EachString !=3D "STR_NULL"): > > + if EachString not in GlobalVarId: > > + GlobalVarId[EachString] =3D StringVarIds(EachG= roup) > > + else: > > + if (GlobalVarId[EachString][0] !=3D StringVarI= ds(EachGroup)[0]): > > + if Options['QuestionOption']: > > + if Options['QuestionOption'] =3D=3D "e= ": > > + QuestionError =3D True > > + print("ERROR:"), > > + if Options['QuestionOption'] =3D=3D "w= ": > > + print("WARNING:"), > > + print("%s referred by different HII qu= estions(%s and %s)" % > ( > > + EachString, GlobalVarId[EachString= ][0], > StringVarIds(EachGroup)[0])) > > + except: > > + print("Error opening file at %s for reading." % Filename) > > + > > + > > +if __name__ =3D=3D '__main__': > > + sys.exit(main(sys.argv)) > > -- > > 2.14.1.windows.1 > > >=20