4 # //===----------------------------------------------------------------------===//
6 # // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
7 # // See https://llvm.org/LICENSE.txt for license information.
8 # // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
10 # //===----------------------------------------------------------------------===//
17 from libomputils
import error
, ScriptError
, print_error_line
20 class DllExports(object):
24 self
.ordinals
= set([])
26 def add_uppercase_entries(self
):
27 # Ignored entries are C/C++ only functions
36 keys
= list(self
.exports
.keys())
38 info
= self
.exports
[entry
]
39 if info
["obsolete"] or info
["is_data"] or entry
in ignores
:
41 if entry
.startswith("omp_") or entry
.startswith("kmp_"):
42 newentry
= entry
.upper()
44 newordinal
= info
["ordinal"] + 1000
47 self
.exports
[newentry
] = {
50 "ordinal": newordinal
,
54 def create(inputFile
, defs
=None):
55 """Creates DllExports object from inputFile"""
56 dllexports
= DllExports()
57 dllexports
.filename
= inputFile
58 # Create a (possibly empty) list of definitions
60 definitions
= set(list(defs
))
63 # Different kinds of lines to parse
64 kw
= r
"[a-zA-Z_][a-zA-Z0-9_]*"
65 ifndef
= re
.compile(r
"%ifndef\s+({})".format(kw
))
66 ifdef
= re
.compile(r
"%ifdef\s+({})".format(kw
))
67 endif
= re
.compile(r
"%endif")
68 export
= re
.compile(r
"(-)?\s*({0})(=({0}))?(\s+([0-9]+|DATA))?".format(kw
))
70 def err(fil
, num
, msg
):
71 error("{}: {}: {}".format(fil
, num
, msg
))
74 with
open(inputFile
) as f
:
75 for lineNumber
, line
in enumerate(f
):
81 if line
.startswith("#"):
83 # Encountered %ifndef DEF
84 m
= ifndef
.search(line
)
86 defs_stack
.append(m
.group(1) not in definitions
)
88 # Encountered %ifdef DEF
89 m
= ifdef
.search(line
)
91 defs_stack
.append(m
.group(1) in definitions
)
94 m
= endif
.search(line
)
97 err(inputFile
, lineNumber
, "orphan %endif directive")
100 # Skip lines when not all %ifdef or %ifndef are true
101 if defs_stack
and not all(defs_stack
):
103 # Encountered an export line
104 m
= export
.search(line
)
106 obsolete
= m
.group(1) is not None
110 if entry
in dllexports
.exports
:
114 "already specified entry: {}".format(entry
),
117 entry
+= "={}".format(rename
)
118 # No ordinal number nor DATA specified
123 elif ordinal
== "DATA":
126 # Regular ordinal number
130 ordinal
= int(ordinal
)
135 "Bad ordinal value: {}".format(ordinal
),
137 if ordinal
>= 1000 and (
138 entry
.startswith("omp_") or entry
.startswith("kmp_")
143 "Ordinal of user-callable entry must be < 1000",
145 if ordinal
>= 1000 and ordinal
< 2000:
149 "Ordinals between 1000 and 1999 are reserved.",
151 if ordinal
in dllexports
.ordinals
:
155 "Ordinal {} has already been used.".format(ordinal
),
157 dllexports
.exports
[entry
] = {
159 "obsolete": obsolete
,
166 'Cannot parse line:{}"{}"'.format(os
.linesep
, line
),
169 error("syntax error: Unterminated %if directive")
173 def generate_def(dllexports
, f
, no_ordinals
=False, name
=None):
174 """Using dllexports data, write the exports to file, f"""
176 f
.write("LIBRARY {}\n".format(name
))
178 for entry
in sorted(list(dllexports
.exports
.keys())):
179 info
= dllexports
.exports
[entry
]
182 f
.write(" {:<40} ".format(entry
))
185 elif no_ordinals
or not info
["ordinal"]:
188 f
.write("@{}\n".format(info
["ordinal"]))
192 parser
= argparse
.ArgumentParser(
193 description
="Reads input file of dllexports, processes conditional"
194 " directives, checks content for consistency, and generates"
195 " output file suitable for linker"
202 help="Define a variable. Can specify" " this more than once.",
207 help="Specify that no ordinal numbers should be generated",
213 help="Specify library name for def file LIBRARY statement",
220 help="Specify output file name. If not specified," " output is sent to stdout",
222 parser
.add_argument("dllexports", help="The input file describing dllexports")
223 commandArgs
= parser
.parse_args()
226 defs
= set(commandArgs
.defs
)
227 dllexports
= DllExports
.create(commandArgs
.dllexports
, defs
)
228 dllexports
.add_uppercase_entries()
230 output
= open(commandArgs
.output
, "w") if commandArgs
.output
else sys
.stdout
231 generate_def(dllexports
, output
, commandArgs
.no_ordinals
, commandArgs
.name
)
233 if commandArgs
.output
:
237 if __name__
== "__main__":
240 except ScriptError
as e
:
241 print_error_line(str(e
))