[Openmp-commits] [openmp] [OpenMP][libomp] Remove Perl in favor of Python (PR #95307)
via Openmp-commits
openmp-commits at lists.llvm.org
Wed Jun 12 13:47:50 PDT 2024
github-actions[bot] wrote:
<!--LLVM CODE FORMAT COMMENT: {darker}-->
:warning: Python code formatter, darker found issues in your code. :warning:
<details>
<summary>
You can test this locally with the following command:
</summary>
``````````bash
darker --check --diff -r 4d95850d052336a785651030eafa0b24651801a0...96005e1a1f2e7fac92596f159cd4988e177949a5 openmp/runtime/tools/check-depends.py openmp/runtime/tools/check-execstack.py openmp/runtime/tools/generate-def.py openmp/runtime/tools/libomputils.py openmp/runtime/tools/message-converter.py
``````````
</details>
<details>
<summary>
View the diff from darker here.
</summary>
``````````diff
--- check-depends.py 2024-06-12 20:17:46.000000 +0000
+++ check-depends.py 2024-06-12 20:47:26.879492 +0000
@@ -1,48 +1,55 @@
#!/usr/bin/env python3
#
-#//===----------------------------------------------------------------------===//
-#//
-#// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-#// See https://llvm.org/LICENSE.txt for license information.
-#// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-#//
-#//===----------------------------------------------------------------------===//
+# //===----------------------------------------------------------------------===//
+# //
+# // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# // See https://llvm.org/LICENSE.txt for license information.
+# // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+# //
+# //===----------------------------------------------------------------------===//
#
import argparse
import os
import platform
import re
import sys
-from libomputils import ScriptError, error, execute_command, print_info_line, \
- print_error_line
+from libomputils import (
+ ScriptError,
+ error,
+ execute_command,
+ print_info_line,
+ print_error_line,
+)
+
def get_deps_readelf(filename):
- ''' Get list of dependencies from readelf '''
+ """Get list of dependencies from readelf"""
deps = []
# Force readelf call to be in English
- os.environ['LANG'] = 'C'
- r = execute_command(['readelf', '-d', filename])
+ os.environ["LANG"] = "C"
+ r = execute_command(["readelf", "-d", filename])
if r.returncode != 0:
- error('readelf -d {} failed'.format(filename))
- neededRegex = re.compile(r'\(NEEDED\)\s+Shared library: \[([a-zA-Z0-9_.-]+)\]')
+ error("readelf -d {} failed".format(filename))
+ neededRegex = re.compile(r"\(NEEDED\)\s+Shared library: \[([a-zA-Z0-9_.-]+)\]")
for line in r.stdout.split(os.linesep):
match = neededRegex.search(line)
if match:
deps.append(match.group(1))
return deps
+
def get_deps_otool(filename):
- ''' Get list of dependencies from otool '''
+ """Get list of dependencies from otool"""
deps = []
- r = execute_command(['otool', '-L', filename])
+ r = execute_command(["otool", "-L", filename])
if r.returncode != 0:
- error('otool -L {} failed'.format(filename))
- libRegex = re.compile(r'([^ \t]+)\s+\(compatibility version ')
- thisLibRegex = re.compile(r'@rpath/{}'.format(os.path.basename(filename)))
+ error("otool -L {} failed".format(filename))
+ libRegex = re.compile(r"([^ \t]+)\s+\(compatibility version ")
+ thisLibRegex = re.compile(r"@rpath/{}".format(os.path.basename(filename)))
for line in r.stdout.split(os.linesep):
match = thisLibRegex.search(line)
if match:
# Don't include the library itself as a needed dependency
continue
@@ -50,70 +57,78 @@
if match:
deps.append(match.group(1))
continue
return deps
+
def get_deps_link(filename):
- ''' Get list of dependecies from link (Windows OS) '''
+ """Get list of dependecies from link (Windows OS)"""
depsSet = set([])
f = filename.lower()
- args = ['link', '/DUMP']
- if f.endswith('.lib'):
- args.append('/DIRECTIVES')
- elif f.endswith('.dll') or f.endswith('.exe'):
- args.append('/DEPENDENTS')
+ args = ["link", "/DUMP"]
+ if f.endswith(".lib"):
+ args.append("/DIRECTIVES")
+ elif f.endswith(".dll") or f.endswith(".exe"):
+ args.append("/DEPENDENTS")
else:
- error('unrecognized file extension: {}'.format(filename))
+ error("unrecognized file extension: {}".format(filename))
args.append(filename)
r = execute_command(args)
if r.returncode != 0:
- error('{} failed'.format(args.command))
- if f.endswith('.lib'):
- regex = re.compile(r'\s*[-/]defaultlib:(.*)\s*$')
+ error("{} failed".format(args.command))
+ if f.endswith(".lib"):
+ regex = re.compile(r"\s*[-/]defaultlib:(.*)\s*$")
for line in r.stdout.split(os.linesep):
line = line.lower()
match = regex.search(line)
if match:
depsSet.add(match.group(1))
else:
started = False
- markerStart = re.compile(r'Image has the following depend')
- markerEnd = re.compile(r'Summary')
- markerEnd2 = re.compile(r'Image has the following delay load depend')
+ markerStart = re.compile(r"Image has the following depend")
+ markerEnd = re.compile(r"Summary")
+ markerEnd2 = re.compile(r"Image has the following delay load depend")
for line in r.stdout.split(os.linesep):
if not started:
if markerStart.search(line):
started = True
continue
- else: # Started parsing the libs
+ else: # Started parsing the libs
line = line.strip()
if not line:
continue
if markerEnd.search(line) or markerEnd2.search(line):
break
depsSet.add(line.lower())
return list(depsSet)
+
def main():
- parser = argparse.ArgumentParser(description='Check library dependencies')
- parser.add_argument('--bare', action='store_true',
- help='Produce plain, bare output: just a list'
- ' of libraries, a library per line')
- parser.add_argument('--expected', metavar='CSV_LIST',
- help='CSV_LIST is a comma-separated list of expected'
- ' dependencies (or "none"). checks the specified'
- ' library has only expected dependencies.')
+ parser = argparse.ArgumentParser(description="Check library dependencies")
+ parser.add_argument(
+ "--bare",
+ action="store_true",
+ help="Produce plain, bare output: just a list"
+ " of libraries, a library per line",
+ )
+ parser.add_argument(
+ "--expected",
+ metavar="CSV_LIST",
+ help="CSV_LIST is a comma-separated list of expected"
+ ' dependencies (or "none"). checks the specified'
+ " library has only expected dependencies.",
+ )
- parser.add_argument('library', help='The library file to check')
+ parser.add_argument("library", help="The library file to check")
commandArgs = parser.parse_args()
# Get dependencies
deps = []
system = platform.system()
- if system == 'Windows':
+ if system == "Windows":
deps = get_deps_link(commandArgs.library)
- elif system == 'Darwin':
+ elif system == "Darwin":
deps = get_deps_otool(commandArgs.library)
else:
deps = get_deps_readelf(commandArgs.library)
deps = sorted(deps)
@@ -124,27 +139,28 @@
# Calculate unexpected dependencies if expected list specified
unexpected = []
if commandArgs.expected:
# none => any dependency is unexpected
- if commandArgs.expected == 'none':
+ if commandArgs.expected == "none":
unexpected = list(deps)
else:
- expected = [d.strip() for d in commandArgs.expected.split(',')]
+ expected = [d.strip() for d in commandArgs.expected.split(",")]
unexpected = [d for d in deps if d not in expected]
# Regular output
- print_info_line('Dependencies:')
+ print_info_line("Dependencies:")
for dep in deps:
- print_info_line(' {}'.format(dep))
+ print_info_line(" {}".format(dep))
if unexpected:
- print_error_line('Unexpected Dependencies:')
+ print_error_line("Unexpected Dependencies:")
for dep in unexpected:
- print_error_line(' {}'.format(dep))
- error('found unexpected dependencies')
+ print_error_line(" {}".format(dep))
+ error("found unexpected dependencies")
-if __name__ == '__main__':
+
+if __name__ == "__main__":
try:
main()
except ScriptError as e:
print_error_line(str(e))
sys.exit(1)
--- check-execstack.py 2024-06-12 20:17:46.000000 +0000
+++ check-execstack.py 2024-06-12 20:47:26.904382 +0000
@@ -1,56 +1,63 @@
#!/usr/bin/env python3
#
-#//===----------------------------------------------------------------------===//
-#//
-#// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-#// See https://llvm.org/LICENSE.txt for license information.
-#// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-#//
-#//===----------------------------------------------------------------------===//
+# //===----------------------------------------------------------------------===//
+# //
+# // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# // See https://llvm.org/LICENSE.txt for license information.
+# // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+# //
+# //===----------------------------------------------------------------------===//
#
import argparse
import os
import re
import sys
from libomputils import ScriptError, error, print_error_line, execute_command
+
def is_stack_executable_readelf(library):
- ''' Returns true if stack of library file is executable '''
- r = execute_command(['readelf', '-l', '-W', library])
+ """Returns true if stack of library file is executable"""
+ r = execute_command(["readelf", "-l", "-W", library])
if r.returncode != 0:
- error('{} failed'.format(r.command))
+ error("{} failed".format(r.command))
stack_lines = []
for line in r.stdout.split(os.linesep):
- if re.search('STACK', line):
+ if re.search("STACK", line):
stack_lines.append(line.strip())
if not stack_lines:
- error('{}: Not stack segment found'.format(library))
+ error("{}: Not stack segment found".format(library))
if len(stack_lines) > 1:
- error('{}: More than one stack segment found'.format(library))
- h = r'0x[0-9a-fA-F]+'
- m = re.search(r'((GNU_)?STACK)\s+({0})\s+({0})\s+({0})\s+({0})\s+({0})'
- ' ([R ][W ][E ])'.format(h), stack_lines[0])
+ error("{}: More than one stack segment found".format(library))
+ h = r"0x[0-9a-fA-F]+"
+ m = re.search(
+ r"((GNU_)?STACK)\s+({0})\s+({0})\s+({0})\s+({0})\s+({0})"
+ " ([R ][W ][E ])".format(h),
+ stack_lines[0],
+ )
if not m:
- error('{}: Cannot parse stack segment line'.format(library))
+ error("{}: Cannot parse stack segment line".format(library))
if m:
- flags = m.group(8)
- if 'E' in flags:
- return True
+ flags = m.group(8)
+ if "E" in flags:
+ return True
return False
+
def main():
- parser = argparse.ArgumentParser(description='Check library does not have'
- ' executable stack')
- parser.add_argument('library', help='The library file to check')
+ parser = argparse.ArgumentParser(
+ description="Check library does not have" " executable stack"
+ )
+ parser.add_argument("library", help="The library file to check")
commandArgs = parser.parse_args()
if is_stack_executable_readelf(commandArgs.library):
- error('{}: Stack is executable'.format(commandArgs.library))
+ error("{}: Stack is executable".format(commandArgs.library))
-if __name__ == '__main__':
+
+if __name__ == "__main__":
try:
main()
except ScriptError as e:
print_error_line(str(e))
sys.exit(1)
--- generate-def.py 2024-06-12 20:17:46.000000 +0000
+++ generate-def.py 2024-06-12 20:47:26.971937 +0000
@@ -1,76 +1,86 @@
#!/usr/bin/env python3
#
-#//===----------------------------------------------------------------------===//
-#//
-#// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-#// See https://llvm.org/LICENSE.txt for license information.
-#// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-#//
-#//===----------------------------------------------------------------------===//
+# //===----------------------------------------------------------------------===//
+# //
+# // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# // See https://llvm.org/LICENSE.txt for license information.
+# // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+# //
+# //===----------------------------------------------------------------------===//
#
import argparse
import os
import re
import sys
from libomputils import error, ScriptError, print_error_line
+
class DllExports(object):
def __init__(self):
self.filename = None
self.exports = {}
self.ordinals = set([])
+
def add_uppercase_entries(self):
# Ignored entries are C/C++ only functions
- ignores = ['omp_alloc', 'omp_free', 'omp_calloc', 'omp_realloc',
- 'omp_aligned_alloc', 'omp_aligned_calloc']
+ ignores = [
+ "omp_alloc",
+ "omp_free",
+ "omp_calloc",
+ "omp_realloc",
+ "omp_aligned_alloc",
+ "omp_aligned_calloc",
+ ]
keys = list(self.exports.keys())
for entry in keys:
info = self.exports[entry]
- if info['obsolete'] or info['is_data'] or entry in ignores:
+ if info["obsolete"] or info["is_data"] or entry in ignores:
continue
- if entry.startswith('omp_') or entry.startswith('kmp_'):
+ if entry.startswith("omp_") or entry.startswith("kmp_"):
newentry = entry.upper()
- if info['ordinal']:
- newordinal = info['ordinal'] + 1000
+ if info["ordinal"]:
+ newordinal = info["ordinal"] + 1000
else:
newordinal = None
self.exports[newentry] = {
- 'obsolete': False,
- 'is_data' : False,
- 'ordinal' : newordinal}
+ "obsolete": False,
+ "is_data": False,
+ "ordinal": newordinal,
+ }
+
@staticmethod
def create(inputFile, defs=None):
- ''' Creates DllExports object from inputFile '''
+ """Creates DllExports object from inputFile"""
dllexports = DllExports()
dllexports.filename = inputFile
# Create a (possibly empty) list of definitions
if defs:
definitions = set(list(defs))
else:
definitions = set([])
# Different kinds of lines to parse
- kw = r'[a-zA-Z_][a-zA-Z0-9_]*'
- ifndef = re.compile(r'%ifndef\s+({})'.format(kw))
- ifdef = re.compile(r'%ifdef\s+({})'.format(kw))
- endif = re.compile(r'%endif')
- export = re.compile(r'(-)?\s*({0})(=({0}))?(\s+([0-9]+|DATA))?'.format(kw))
+ kw = r"[a-zA-Z_][a-zA-Z0-9_]*"
+ ifndef = re.compile(r"%ifndef\s+({})".format(kw))
+ ifdef = re.compile(r"%ifdef\s+({})".format(kw))
+ endif = re.compile(r"%endif")
+ export = re.compile(r"(-)?\s*({0})(=({0}))?(\s+([0-9]+|DATA))?".format(kw))
def err(fil, num, msg):
- error('{}: {}: {}'.format(fil, num, msg))
+ error("{}: {}: {}".format(fil, num, msg))
defs_stack = []
with open(inputFile) as f:
for lineNumber, line in enumerate(f):
line = line.strip()
# Skip empty lines
if not line:
continue
# Skip comment lines
- if line.startswith('#'):
+ if line.startswith("#"):
continue
# Encountered %ifndef DEF
m = ifndef.search(line)
if m:
defs_stack.append(m.group(1) not in definitions)
@@ -82,110 +92,151 @@
continue
# Encountered %endif
m = endif.search(line)
if m:
if not defs_stack:
- err(inputFile, lineNumber, 'orphan %endif directive')
+ err(inputFile, lineNumber, "orphan %endif directive")
defs_stack.pop()
continue
# Skip lines when not all %ifdef or %ifndef are true
if defs_stack and not all(defs_stack):
continue
# Encountered an export line
m = export.search(line)
if m:
- obsolete = (m.group(1) is not None)
+ obsolete = m.group(1) is not None
entry = m.group(2)
rename = m.group(4)
ordinal = m.group(6)
if entry in dllexports.exports:
- err(inputFile, lineNumber, 'already specified entry: {}'.format(entry))
+ err(
+ inputFile,
+ lineNumber,
+ "already specified entry: {}".format(entry),
+ )
if rename:
- entry += '={}'.format(rename)
+ entry += "={}".format(rename)
# No ordinal number nor DATA specified
if not ordinal:
ordinal = None
is_data = False
# DATA ordinal
- elif ordinal == 'DATA':
+ elif ordinal == "DATA":
ordinal = None
is_data = True
# Regular ordinal number
else:
is_data = False
try:
ordinal = int(ordinal)
except:
- err(inputFile, lineNumber, 'Bad ordinal value: {}'.format(ordinal))
- if (ordinal >= 1000 and (entry.startswith('omp_') or
- entry.startswith('kmp_'))):
- err(inputFile, lineNumber,
- 'Ordinal of user-callable entry must be < 1000')
- if (ordinal >= 1000 and ordinal < 2000):
- err(inputFile, lineNumber,
- 'Ordinals between 1000 and 1999 are reserved.')
+ err(
+ inputFile,
+ lineNumber,
+ "Bad ordinal value: {}".format(ordinal),
+ )
+ if ordinal >= 1000 and (
+ entry.startswith("omp_") or entry.startswith("kmp_")
+ ):
+ err(
+ inputFile,
+ lineNumber,
+ "Ordinal of user-callable entry must be < 1000",
+ )
+ if ordinal >= 1000 and ordinal < 2000:
+ err(
+ inputFile,
+ lineNumber,
+ "Ordinals between 1000 and 1999 are reserved.",
+ )
if ordinal in dllexports.ordinals:
- err(inputFile, lineNumber,
- 'Ordinal {} has already been used.'.format(ordinal))
- dllexports.exports[entry] = {'ordinal': ordinal,
- 'obsolete': obsolete,
- 'is_data': is_data}
- continue
- err(inputFile, lineNumber,
- 'Cannot parse line:{}"{}"'.format(os.linesep, line))
+ err(
+ inputFile,
+ lineNumber,
+ "Ordinal {} has already been used.".format(ordinal),
+ )
+ dllexports.exports[entry] = {
+ "ordinal": ordinal,
+ "obsolete": obsolete,
+ "is_data": is_data,
+ }
+ continue
+ err(
+ inputFile,
+ lineNumber,
+ 'Cannot parse line:{}"{}"'.format(os.linesep, line),
+ )
if defs_stack:
- error('syntax error: Unterminated %if directive')
+ error("syntax error: Unterminated %if directive")
return dllexports
+
def generate_def(dllexports, f, no_ordinals=False, name=None):
- ''' Using dllexports data, write the exports to file, f '''
+ """Using dllexports data, write the exports to file, f"""
if name:
- f.write('LIBRARY {}\n'.format(name))
- f.write('EXPORTS\n')
+ f.write("LIBRARY {}\n".format(name))
+ f.write("EXPORTS\n")
for entry in sorted(list(dllexports.exports.keys())):
info = dllexports.exports[entry]
- if info['obsolete']:
+ if info["obsolete"]:
continue
- f.write(' {:<40} '.format(entry))
- if info['is_data']:
- f.write('DATA\n')
- elif no_ordinals or not info['ordinal']:
- f.write('\n')
+ f.write(" {:<40} ".format(entry))
+ if info["is_data"]:
+ f.write("DATA\n")
+ elif no_ordinals or not info["ordinal"]:
+ f.write("\n")
else:
- f.write('@{}\n'.format(info['ordinal']))
+ f.write("@{}\n".format(info["ordinal"]))
+
def main():
parser = argparse.ArgumentParser(
- description='Reads input file of dllexports, processes conditional'
- ' directives, checks content for consistency, and generates'
- ' output file suitable for linker')
- parser.add_argument('-D', metavar='DEF', action='append', dest='defs',
- help='Define a variable. Can specify'
- ' this more than once.')
- parser.add_argument('--no-ordinals', action='store_true',
- help='Specify that no ordinal numbers should be generated')
- parser.add_argument('-n', '--name', dest='name',
- help='Specify library name for def file LIBRARY statement')
- parser.add_argument('-o', '--output', metavar='FILE', dest='output',
- help='Specify output file name. If not specified,'
- ' output is sent to stdout')
- parser.add_argument('dllexports',
- help='The input file describing dllexports')
+ description="Reads input file of dllexports, processes conditional"
+ " directives, checks content for consistency, and generates"
+ " output file suitable for linker"
+ )
+ parser.add_argument(
+ "-D",
+ metavar="DEF",
+ action="append",
+ dest="defs",
+ help="Define a variable. Can specify" " this more than once.",
+ )
+ parser.add_argument(
+ "--no-ordinals",
+ action="store_true",
+ help="Specify that no ordinal numbers should be generated",
+ )
+ parser.add_argument(
+ "-n",
+ "--name",
+ dest="name",
+ help="Specify library name for def file LIBRARY statement",
+ )
+ parser.add_argument(
+ "-o",
+ "--output",
+ metavar="FILE",
+ dest="output",
+ help="Specify output file name. If not specified," " output is sent to stdout",
+ )
+ parser.add_argument("dllexports", help="The input file describing dllexports")
commandArgs = parser.parse_args()
defs = set([])
if commandArgs.defs:
defs = set(commandArgs.defs)
dllexports = DllExports.create(commandArgs.dllexports, defs)
dllexports.add_uppercase_entries()
try:
- output = open(commandArgs.output, 'w') if commandArgs.output else sys.stdout
+ output = open(commandArgs.output, "w") if commandArgs.output else sys.stdout
generate_def(dllexports, output, commandArgs.no_ordinals, commandArgs.name)
finally:
if commandArgs.output:
output.close()
-if __name__ == '__main__':
+
+if __name__ == "__main__":
try:
main()
except ScriptError as e:
print_error_line(str(e))
sys.exit(1)
--- libomputils.py 2024-06-12 20:17:46.000000 +0000
+++ libomputils.py 2024-06-12 20:47:27.002677 +0000
@@ -1,55 +1,65 @@
#
-#//===----------------------------------------------------------------------===//
-#//
-#// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-#// See https://llvm.org/LICENSE.txt for license information.
-#// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-#//
-#//===----------------------------------------------------------------------===//
+# //===----------------------------------------------------------------------===//
+# //
+# // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# // See https://llvm.org/LICENSE.txt for license information.
+# // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+# //
+# //===----------------------------------------------------------------------===//
#
import os
import subprocess
import sys
+
class ScriptError(Exception):
- ''' Convenience class for user errors generated '''
+ """Convenience class for user errors generated"""
+
def __init__(self, msg):
super(Exception, self).__init__(msg)
+
def error(msg):
raise ScriptError(msg)
-def print_line(msg, form='i'):
- print('{}: ({}) {}'.format(os.path.basename(sys.argv[0]), form, msg))
+
+def print_line(msg, form="i"):
+ print("{}: ({}) {}".format(os.path.basename(sys.argv[0]), form, msg))
+
def print_info_line(msg):
print_line(msg)
+
def print_error_line(msg):
- print_line(msg, form='x')
+ print_line(msg, form="x")
+
class RunResult:
- '''
+ """
Auxiliary class for execute_command() containing the
results of running a command
- '''
+ """
+
def __init__(self, args, stdout, stderr, returncode):
self.executable = args[0]
- self.stdout = stdout.decode('utf-8')
- self.stderr = stderr.decode('utf-8')
+ self.stdout = stdout.decode("utf-8")
+ self.stderr = stderr.decode("utf-8")
self.returncode = returncode
- self.command = ' '.join(args)
+ self.command = " ".join(args)
+
def execute_command(args):
- '''
+ """
Run a command with arguments: args
Return RunResult containing stdout, stderr, returncode
- '''
+ """
handle = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = handle.communicate()
returncode = handle.wait()
return RunResult(args, stdout, stderr, returncode)
+
# end of file
--- message-converter.py 2024-06-12 20:17:46.000000 +0000
+++ message-converter.py 2024-06-12 20:47:27.114111 +0000
@@ -1,318 +1,371 @@
#!/usr/bin/env python3
#
-#//===----------------------------------------------------------------------===//
-#//
-#// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-#// See https://llvm.org/LICENSE.txt for license information.
-#// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-#//
-#//===----------------------------------------------------------------------===//
+# //===----------------------------------------------------------------------===//
+# //
+# // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# // See https://llvm.org/LICENSE.txt for license information.
+# // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+# //
+# //===----------------------------------------------------------------------===//
#
import argparse
import datetime
import os
import platform
import re
import sys
from libomputils import ScriptError, error
+
class ParseMessageDataError(ScriptError):
- ''' Convenience class for parsing message data file errors '''
+ """Convenience class for parsing message data file errors"""
+
def __init__(self, filename, line, msg):
super(ParseMessageDataError, self).__init__(msg)
self.filename = filename
self.line = line
+
+
def parse_error(filename, line, msg):
raise ParseMessageDataError(filename, line, msg)
+
def display_language_id(inputFile):
- ''' Quickly parse file for LangId and print it '''
+ """Quickly parse file for LangId and print it"""
regex = re.compile(r'^LangId\s+"([0-9]+)"')
- with open(inputFile, encoding='utf-8') as f:
+ with open(inputFile, encoding="utf-8") as f:
for line in f:
m = regex.search(line)
if not m:
continue
print(m.group(1))
+
class Message(object):
special = {
- 'n': '\n',
- 't': '\t',
+ "n": "\n",
+ "t": "\t",
}
+
def __init__(self, lineNumber, name, text):
self.lineNumber = lineNumber
self.name = name
self.text = text
+
def toSrc(self):
- if platform.system() == 'Windows':
- return re.sub(r'%([0-9])\$(s|l?[du])', r'%\1!\2!', self.text)
+ if platform.system() == "Windows":
+ return re.sub(r"%([0-9])\$(s|l?[du])", r"%\1!\2!", self.text)
return str(self.text)
+
def toMC(self):
retval = self.toSrc()
for special, substitute in Message.special.items():
- retval = re.sub(r'\\{}'.format(special), substitute, retval)
+ retval = re.sub(r"\\{}".format(special), substitute, retval)
return retval
+
class MessageData(object):
- '''
+ """
Convenience class representing message data parsed from i18n/* files
Generate these objects using static create() factory method
- '''
+ """
+
sectionInfo = {
- 'meta': {'short': 'prp', 'long': 'meta', 'set': 1, 'base': 1 << 16},
- 'strings': {'short': 'str', 'long': 'strings', 'set': 2, 'base': 2 << 16},
- 'formats': {'short': 'fmt', 'long': 'formats', 'set': 3, 'base': 3 << 16},
- 'messages': {'short': 'msg', 'long': 'messages', 'set': 4, 'base': 4 << 16},
- 'hints': {'short': 'hnt', 'long': 'hints', 'set': 5, 'base': 5 << 16},
+ "meta": {"short": "prp", "long": "meta", "set": 1, "base": 1 << 16},
+ "strings": {"short": "str", "long": "strings", "set": 2, "base": 2 << 16},
+ "formats": {"short": "fmt", "long": "formats", "set": 3, "base": 3 << 16},
+ "messages": {"short": "msg", "long": "messages", "set": 4, "base": 4 << 16},
+ "hints": {"short": "hnt", "long": "hints", "set": 5, "base": 5 << 16},
}
- orderedSections = ['meta', 'strings', 'formats', 'messages', 'hints']
+ orderedSections = ["meta", "strings", "formats", "messages", "hints"]
+
def __init__(self):
self.filename = None
self.sections = {}
+
def getMeta(self, name):
- metaList = self.sections['meta']
+ metaList = self.sections["meta"]
for meta in metaList:
if meta.name == name:
return meta.text
- error('No "{}" detected in meta data'
- ' for file {}'.format(name, self.filename))
+ error(
+ 'No "{}" detected in meta data' " for file {}".format(name, self.filename)
+ )
+
@staticmethod
def create(inputFile):
- ''' Creates MessageData object from inputFile '''
+ """Creates MessageData object from inputFile"""
data = MessageData()
data.filename = os.path.abspath(inputFile)
obsolete = 1
- sectionRegex = re.compile(r'-\*- ([a-zA-Z0-9_]+) -\*-')
+ sectionRegex = re.compile(r"-\*- ([a-zA-Z0-9_]+) -\*-")
keyValueRegex = re.compile(r'([a-zA-Z_][a-zA-Z0-9_]*)\s+"(.*)"')
moreValueRegex = re.compile(r'"(.*)"')
- with open(inputFile, 'r', encoding='utf-8') as f:
+ with open(inputFile, "r", encoding="utf-8") as f:
currentSection = None
currentKey = None
for lineNumber, line in enumerate(f, 1):
line = line.strip()
# Skip empty lines
if not line:
continue
# Skip comment lines
- if line.startswith('#'):
+ if line.startswith("#"):
continue
# Matched a section header
match = sectionRegex.search(line)
if match:
currentSection = match.group(1).lower()
if currentSection in data.sections:
- parse_error(inputFile, lineNumber,
- 'section: {} already defined'.format(currentSection))
+ parse_error(
+ inputFile,
+ lineNumber,
+ "section: {} already defined".format(currentSection),
+ )
data.sections[currentSection] = []
continue
# Matched a Key "Value" line (most lines)
match = keyValueRegex.search(line)
if match:
if not currentSection:
- parse_error(inputFile, lineNumber,
- 'no section defined yet.')
+ parse_error(inputFile, lineNumber, "no section defined yet.")
key = match.group(1)
- if key == 'OBSOLETE':
- key = 'OBSOLETE{}'.format(obsolete)
+ if key == "OBSOLETE":
+ key = "OBSOLETE{}".format(obsolete)
obsolete += 1
value = match.group(2)
currentKey = key
- data.sections[currentSection].append(Message(lineNumber, key, value))
+ data.sections[currentSection].append(
+ Message(lineNumber, key, value)
+ )
continue
# Matched a Continuation of string line
match = moreValueRegex.search(line)
if match:
value = match.group(1)
if not currentSection:
- parse_error(inputFile, lineNumber,
- 'no section defined yet.')
+ parse_error(inputFile, lineNumber, "no section defined yet.")
if not currentKey:
- parse_error(inputFile, lineNumber,
- 'no key defined yet.')
+ parse_error(inputFile, lineNumber, "no key defined yet.")
data.sections[currentSection][-1].text += value
continue
# Unknown line syntax
- parse_error(inputFile, lineNumber, 'bad line:\n{}'.format(line))
+ parse_error(inputFile, lineNumber, "bad line:\n{}".format(line))
return data
-def insert_header(f, data, commentChar='//'):
- f.write('{0} Do not edit this file! {0}\n'
- '{0} The file was generated from'
- ' {1} by {2} on {3}. {0}\n\n'.format(
+
+def insert_header(f, data, commentChar="//"):
+ f.write(
+ "{0} Do not edit this file! {0}\n"
+ "{0} The file was generated from"
+ " {1} by {2} on {3}. {0}\n\n".format(
commentChar,
os.path.basename(data.filename),
os.path.basename(__file__),
- datetime.datetime.now().ctime()))
+ datetime.datetime.now().ctime(),
+ )
+ )
+
def generate_enum_file(enumFile, prefix, data):
- ''' Create the include file with message enums '''
+ """Create the include file with message enums"""
global g_sections
- with open(enumFile, 'w') as f:
+ with open(enumFile, "w") as f:
insert_header(f, data)
- f.write('enum {0}_id {1}\n'
- '\n'
- ' // A special id for absence of message.\n'
- ' {0}_null = 0,\n'
- '\n'.format(prefix, '{'))
+ f.write(
+ "enum {0}_id {1}\n"
+ "\n"
+ " // A special id for absence of message.\n"
+ " {0}_null = 0,\n"
+ "\n".format(prefix, "{")
+ )
for section in MessageData.orderedSections:
messages = data.sections[section]
info = MessageData.sectionInfo[section]
- shortName = info['short']
- longName = info['long']
- base = info['base']
- setIdx = info['set']
- f.write(' // Set #{}, {}.\n'
- ' {}_{}_first = {},\n'.format(
- setIdx, longName, prefix, shortName, base))
+ shortName = info["short"]
+ longName = info["long"]
+ base = info["base"]
+ setIdx = info["set"]
+ f.write(
+ " // Set #{}, {}.\n"
+ " {}_{}_first = {},\n".format(
+ setIdx, longName, prefix, shortName, base
+ )
+ )
for message in messages:
- f.write(' {}_{}_{},\n'.format(prefix, shortName, message.name))
- f.write(' {}_{}_last,\n\n'.format(prefix, shortName))
- f.write(' {0}_xxx_lastest\n\n'
- '{1}; // enum {0}_id\n\n'
- 'typedef enum {0}_id {0}_id_t;\n\n\n'
- '// end of file //\n'.format(prefix, '}'))
+ f.write(" {}_{}_{},\n".format(prefix, shortName, message.name))
+ f.write(" {}_{}_last,\n\n".format(prefix, shortName))
+ f.write(
+ " {0}_xxx_lastest\n\n"
+ "{1}; // enum {0}_id\n\n"
+ "typedef enum {0}_id {0}_id_t;\n\n\n"
+ "// end of file //\n".format(prefix, "}")
+ )
+
def generate_signature_file(signatureFile, data):
- ''' Create the signature file '''
- sigRegex = re.compile(r'(%[0-9]\$(s|l?[du]))')
- with open(signatureFile, 'w') as f:
- f.write('// message catalog signature file //\n\n')
- for section in MessageData.orderedSections:
- messages = data.sections[section]
- longName = MessageData.sectionInfo[section]['long']
- f.write('-*- {}-*-\n\n'.format(longName.upper()))
+ """Create the signature file"""
+ sigRegex = re.compile(r"(%[0-9]\$(s|l?[du]))")
+ with open(signatureFile, "w") as f:
+ f.write("// message catalog signature file //\n\n")
+ for section in MessageData.orderedSections:
+ messages = data.sections[section]
+ longName = MessageData.sectionInfo[section]["long"]
+ f.write("-*- {}-*-\n\n".format(longName.upper()))
for message in messages:
sigs = sorted(list(set([a for a, b in sigRegex.findall(message.text)])))
i = 0
# Insert empty placeholders if necessary
while i != len(sigs):
num = i + 1
- if not sigs[i].startswith('%{}'.format(num)):
- sigs.insert(i, '%{}$-'.format(num))
+ if not sigs[i].startswith("%{}".format(num)):
+ sigs.insert(i, "%{}$-".format(num))
else:
i += 1
- f.write('{:<40} {}\n'.format(message.name, ' '.join(sigs)))
- f.write('\n')
- f.write('// end of file //\n')
+ f.write("{:<40} {}\n".format(message.name, " ".join(sigs)))
+ f.write("\n")
+ f.write("// end of file //\n")
+
def generate_default_messages_file(defaultFile, prefix, data):
- ''' Create the include file with message strings organized '''
- with open(defaultFile, 'w', encoding='utf-8') as f:
+ """Create the include file with message strings organized"""
+ with open(defaultFile, "w", encoding="utf-8") as f:
insert_header(f, data)
for section in MessageData.orderedSections:
- f.write('static char const *\n'
- '__{}_default_{}[] =\n'
- ' {}\n'
- ' NULL,\n'.format(prefix, section, '{'))
+ f.write(
+ "static char const *\n"
+ "__{}_default_{}[] =\n"
+ " {}\n"
+ " NULL,\n".format(prefix, section, "{")
+ )
messages = data.sections[section]
for message in messages:
f.write(' "{}",\n'.format(message.toSrc()))
- f.write(' NULL\n'
- ' {};\n\n'.format('}'))
- f.write('struct kmp_i18n_section {0}\n'
- ' int size;\n'
- ' char const ** str;\n'
- '{1}; // struct kmp_i18n_section\n'
- 'typedef struct kmp_i18n_section kmp_i18n_section_t;\n\n'
- 'static kmp_i18n_section_t\n'
- '__{2}_sections[] =\n'
- ' {0}\n'
- ' {0} 0, NULL {1},\n'.format('{', '}', prefix))
-
- for section in MessageData.orderedSections:
- messages = data.sections[section]
- f.write(' {} {}, __{}_default_{} {},\n'.format(
- '{', len(messages), prefix, section, '}'))
+ f.write(" NULL\n" " {};\n\n".format("}"))
+ f.write(
+ "struct kmp_i18n_section {0}\n"
+ " int size;\n"
+ " char const ** str;\n"
+ "{1}; // struct kmp_i18n_section\n"
+ "typedef struct kmp_i18n_section kmp_i18n_section_t;\n\n"
+ "static kmp_i18n_section_t\n"
+ "__{2}_sections[] =\n"
+ " {0}\n"
+ " {0} 0, NULL {1},\n".format("{", "}", prefix)
+ )
+
+ for section in MessageData.orderedSections:
+ messages = data.sections[section]
+ f.write(
+ " {} {}, __{}_default_{} {},\n".format(
+ "{", len(messages), prefix, section, "}"
+ )
+ )
numSections = len(MessageData.orderedSections)
- f.write(' {0} 0, NULL {1}\n'
- ' {1};\n\n'
- 'struct kmp_i18n_table {0}\n'
- ' int size;\n'
- ' kmp_i18n_section_t * sect;\n'
- '{1}; // struct kmp_i18n_table\n'
- 'typedef struct kmp_i18n_table kmp_i18n_table_t;\n\n'
- 'static kmp_i18n_table_t __kmp_i18n_default_table =\n'
- ' {0}\n'
- ' {3},\n'
- ' __{2}_sections\n'
- ' {1};\n\n'
- '// end of file //\n'.format('{', '}', prefix, numSections))
+ f.write(
+ " {0} 0, NULL {1}\n"
+ " {1};\n\n"
+ "struct kmp_i18n_table {0}\n"
+ " int size;\n"
+ " kmp_i18n_section_t * sect;\n"
+ "{1}; // struct kmp_i18n_table\n"
+ "typedef struct kmp_i18n_table kmp_i18n_table_t;\n\n"
+ "static kmp_i18n_table_t __kmp_i18n_default_table =\n"
+ " {0}\n"
+ " {3},\n"
+ " __{2}_sections\n"
+ " {1};\n\n"
+ "// end of file //\n".format("{", "}", prefix, numSections)
+ )
+
def generate_message_file_unix(messageFile, data):
- '''
+ """
Create the message file for Unix OSes
Encoding is in UTF-8
- '''
- with open(messageFile, 'w', encoding='utf-8') as f:
- insert_header(f, data, commentChar='$')
+ """
+ with open(messageFile, "w", encoding="utf-8") as f:
+ insert_header(f, data, commentChar="$")
f.write('$quote "\n\n')
for section in MessageData.orderedSections:
- setIdx = MessageData.sectionInfo[section]['set']
- f.write('$ ------------------------------------------------------------------------------\n'
- '$ {}\n'
- '$ ------------------------------------------------------------------------------\n\n'
- '$set {}\n\n'.format(section, setIdx))
+ setIdx = MessageData.sectionInfo[section]["set"]
+ f.write(
+ "$ ------------------------------------------------------------------------------\n"
+ "$ {}\n"
+ "$ ------------------------------------------------------------------------------\n\n"
+ "$set {}\n\n".format(section, setIdx)
+ )
messages = data.sections[section]
for num, message in enumerate(messages, 1):
f.write('{} "{}"\n'.format(num, message.toSrc()))
- f.write('\n')
- f.write('\n$ end of file $')
+ f.write("\n")
+ f.write("\n$ end of file $")
+
def generate_message_file_windows(messageFile, data):
- '''
+ """
Create the message file for Windows OS
Encoding is in UTF-16LE
- '''
- language = data.getMeta('Language')
- langId = data.getMeta('LangId')
- with open(messageFile, 'w', encoding='utf-16-le') as f:
- insert_header(f, data, commentChar=';')
- f.write('\nLanguageNames = ({0}={1}:msg_{1})\n\n'.format(language, langId))
- f.write('FacilityNames=(\n')
- for section in MessageData.orderedSections:
- setIdx = MessageData.sectionInfo[section]['set']
- shortName = MessageData.sectionInfo[section]['short']
- f.write(' {}={}\n'.format(shortName, setIdx))
- f.write(')\n\n')
-
- for section in MessageData.orderedSections:
- shortName = MessageData.sectionInfo[section]['short']
+ """
+ language = data.getMeta("Language")
+ langId = data.getMeta("LangId")
+ with open(messageFile, "w", encoding="utf-16-le") as f:
+ insert_header(f, data, commentChar=";")
+ f.write("\nLanguageNames = ({0}={1}:msg_{1})\n\n".format(language, langId))
+ f.write("FacilityNames=(\n")
+ for section in MessageData.orderedSections:
+ setIdx = MessageData.sectionInfo[section]["set"]
+ shortName = MessageData.sectionInfo[section]["short"]
+ f.write(" {}={}\n".format(shortName, setIdx))
+ f.write(")\n\n")
+
+ for section in MessageData.orderedSections:
+ shortName = MessageData.sectionInfo[section]["short"]
n = 0
messages = data.sections[section]
for message in messages:
n += 1
- f.write('MessageId={}\n'
- 'Facility={}\n'
- 'Language={}\n'
- '{}\n.\n\n'.format(n, shortName, language,
- message.toMC()))
- f.write('\n; end of file ;')
+ f.write(
+ "MessageId={}\n"
+ "Facility={}\n"
+ "Language={}\n"
+ "{}\n.\n\n".format(n, shortName, language, message.toMC())
+ )
+ f.write("\n; end of file ;")
+
def main():
- parser = argparse.ArgumentParser(description='Generate message data files')
- parser.add_argument('--lang-id', action='store_true',
- help='Print language identifier of the message catalog source file')
- parser.add_argument('--prefix', default='kmp_i18n',
- help='Prefix to be used for all C identifiers (type and variable names)'
- ' in enum and default message files.')
- parser.add_argument('--enum', metavar='FILE',
- help='Generate enum file named FILE')
- parser.add_argument('--default', metavar='FILE',
- help='Generate default messages file named FILE')
- parser.add_argument('--signature', metavar='FILE',
- help='Generate signature file named FILE')
- parser.add_argument('--message', metavar='FILE',
- help='Generate message file named FILE')
- parser.add_argument('inputfile')
+ parser = argparse.ArgumentParser(description="Generate message data files")
+ parser.add_argument(
+ "--lang-id",
+ action="store_true",
+ help="Print language identifier of the message catalog source file",
+ )
+ parser.add_argument(
+ "--prefix",
+ default="kmp_i18n",
+ help="Prefix to be used for all C identifiers (type and variable names)"
+ " in enum and default message files.",
+ )
+ parser.add_argument("--enum", metavar="FILE", help="Generate enum file named FILE")
+ parser.add_argument(
+ "--default", metavar="FILE", help="Generate default messages file named FILE"
+ )
+ parser.add_argument(
+ "--signature", metavar="FILE", help="Generate signature file named FILE"
+ )
+ parser.add_argument(
+ "--message", metavar="FILE", help="Generate message file named FILE"
+ )
+ parser.add_argument("inputfile")
commandArgs = parser.parse_args()
if commandArgs.lang_id:
display_language_id(commandArgs.inputfile)
return
@@ -323,18 +376,19 @@
if commandArgs.default:
generate_default_messages_file(commandArgs.default, prefix, data)
if commandArgs.signature:
generate_signature_file(commandArgs.signature, data)
if commandArgs.message:
- if platform.system() == 'Windows':
+ if platform.system() == "Windows":
generate_message_file_windows(commandArgs.message, data)
else:
generate_message_file_unix(commandArgs.message, data)
-if __name__ == '__main__':
+
+if __name__ == "__main__":
try:
main()
except ScriptError as e:
- print('error: {}'.format(e))
+ print("error: {}".format(e))
sys.exit(1)
# end of file
``````````
</details>
https://github.com/llvm/llvm-project/pull/95307
More information about the Openmp-commits
mailing list