18from libomputils
import ScriptError, error
22 """Convenience class for handling the target platform for configuration/compilation"""
24 system_override =
None
26 Target system name override by the user.
27 It follows the conventions from https://docs.python.org/3/library/platform.html#platform.system
32 Set a system override for the target.
33 Please follow the style from https://docs.python.org/3/library/platform.html#platform.system
35 TargetPlatform.system_override = override_system
40 It follows the conventions from https://docs.python.org/3/library/platform.html#platform.system
42 if TargetPlatform.system_override
is None:
43 return platform.system()
44 return TargetPlatform.system_override
48 """Convenience class for parsing message data file errors"""
51 super(ParseMessageDataError, self).
__init__(msg)
61 """Quickly parse file for LangId and print it"""
62 regex = re.compile(
r'^LangId\s+"([0-9]+)"')
63 with open(inputFile, encoding=
"utf-8")
as f:
65 m = regex.search(line)
83 if TargetPlatform.system().casefold() ==
"Windows".casefold():
84 return re.sub(
r"%([0-9])\$(s|l?[du])",
r"%\1!\2!", self.
text)
89 for special, substitute
in Message.special.items():
90 retval = re.sub(
r"\\{}".format(special), substitute, retval)
96 Convenience class representing message data parsed from i18n/* files
98 Generate these objects using static create() factory method
102 "meta": {
"short":
"prp",
"long":
"meta",
"set": 1,
"base": 1 << 16},
103 "strings": {
"short":
"str",
"long":
"strings",
"set": 2,
"base": 2 << 16},
104 "formats": {
"short":
"fmt",
"long":
"formats",
"set": 3,
"base": 3 << 16},
105 "messages": {
"short":
"msg",
"long":
"messages",
"set": 4,
"base": 4 << 16},
106 "hints": {
"short":
"hnt",
"long":
"hints",
"set": 5,
"base": 5 << 16},
108 orderedSections = [
"meta",
"strings",
"formats",
"messages",
"hints"]
116 for meta
in metaList:
117 if meta.name == name:
120 'No "{}" detected in meta data' " for file {}".format(name, self.
filename)
125 """Creates MessageData object from inputFile"""
127 data.filename = os.path.abspath(inputFile)
129 sectionRegex = re.compile(
r"-\*- ([a-zA-Z0-9_]+) -\*-")
130 keyValueRegex = re.compile(
r'([a-zA-Z_][a-zA-Z0-9_]*)\s+"(.*)"')
131 moreValueRegex = re.compile(
r'"(.*)"')
133 with open(inputFile,
"r", encoding=
"utf-8")
as f:
134 currentSection =
None
136 for lineNumber, line
in enumerate(f, 1):
142 if line.startswith(
"#"):
145 match = sectionRegex.search(line)
147 currentSection = match.group(1).lower()
148 if currentSection
in data.sections:
152 "section: {} already defined".format(currentSection),
154 data.sections[currentSection] = []
157 match = keyValueRegex.search(line)
159 if not currentSection:
160 parse_error(inputFile, lineNumber,
"no section defined yet.")
162 if key ==
"OBSOLETE":
163 key =
"OBSOLETE{}".format(obsolete)
165 value = match.group(2)
167 data.sections[currentSection].append(
168 Message(lineNumber, key, value)
172 match = moreValueRegex.search(line)
174 value = match.group(1)
175 if not currentSection:
176 parse_error(inputFile, lineNumber,
"no section defined yet.")
178 parse_error(inputFile, lineNumber,
"no key defined yet.")
179 data.sections[currentSection][-1].text += value
182 parse_error(inputFile, lineNumber,
"bad line:\n{}".format(line))
188 "{0} Do not edit this file! {0}\n"
189 "{0} The file was generated from"
190 " {1} by {2}. {0}\n\n".format(
192 os.path.basename(data.filename),
193 os.path.basename(__file__),
199 """Create the include file with message enums"""
201 with open(enumFile,
"w")
as f:
206 " // A special id for absence of message.\n"
208 "\n".format(prefix,
"{")
210 for section
in MessageData.orderedSections:
211 messages = data.sections[section]
212 info = MessageData.sectionInfo[section]
213 shortName = info[
"short"]
214 longName = info[
"long"]
219 " {}_{}_first = {},\n".format(
220 setIdx, longName, prefix, shortName, base
223 for message
in messages:
224 f.write(
" {}_{}_{},\n".format(prefix, shortName, message.name))
225 f.write(
" {}_{}_last,\n\n".format(prefix, shortName))
227 " {0}_xxx_lastest\n\n"
228 "{1}; // enum {0}_id\n\n"
229 "typedef enum {0}_id {0}_id_t;\n\n\n"
230 "// end of file //\n".format(prefix,
"}")
235 """Create the signature file"""
236 sigRegex = re.compile(
r"(%[0-9]\$(s|l?[du]))")
237 with open(signatureFile,
"w")
as f:
238 f.write(
"// message catalog signature file //\n\n")
239 for section
in MessageData.orderedSections:
240 messages = data.sections[section]
241 longName = MessageData.sectionInfo[section][
"long"]
242 f.write(
"-*- {}-*-\n\n".format(longName.upper()))
243 for message
in messages:
244 sigs = sorted(list(set([a
for a, b
in sigRegex.findall(message.text)])))
247 while i != len(sigs):
249 if not sigs[i].startswith(
"%{}".format(num)):
250 sigs.insert(i,
"%{}$-".format(num))
253 f.write(
"{:<40} {}\n".format(message.name,
" ".join(sigs)))
255 f.write(
"// end of file //\n")
259 """Create the include file with message strings organized"""
260 with open(defaultFile,
"w", encoding=
"utf-8")
as f:
262 for section
in MessageData.orderedSections:
264 "static char const *\n"
265 "__{}_default_{}[] =\n"
267 " NULL,\n".format(prefix, section,
"{")
269 messages = data.sections[section]
270 for message
in messages:
271 f.write(
' "{}",\n'.format(message.toSrc()))
272 f.write(
" NULL\n" " {};\n\n".format(
"}"))
274 "struct kmp_i18n_section {0}\n"
276 " char const ** str;\n"
277 "{1}; // struct kmp_i18n_section\n"
278 "typedef struct kmp_i18n_section kmp_i18n_section_t;\n\n"
279 "static kmp_i18n_section_t\n"
280 "__{2}_sections[] =\n"
282 " {0} 0, NULL {1},\n".format(
"{",
"}", prefix)
285 for section
in MessageData.orderedSections:
286 messages = data.sections[section]
288 " {} {}, __{}_default_{} {},\n".format(
289 "{", len(messages), prefix, section,
"}"
292 numSections = len(MessageData.orderedSections)
296 "struct kmp_i18n_table {0}\n"
298 " kmp_i18n_section_t * sect;\n"
299 "{1}; // struct kmp_i18n_table\n"
300 "typedef struct kmp_i18n_table kmp_i18n_table_t;\n\n"
301 "static kmp_i18n_table_t __kmp_i18n_default_table =\n"
306 "// end of file //\n".format(
"{",
"}", prefix, numSections)
312 Create the message file for Unix OSes
316 with open(messageFile,
"w", encoding=
"utf-8")
as f:
318 f.write(
'$quote "\n\n')
319 for section
in MessageData.orderedSections:
320 setIdx = MessageData.sectionInfo[section][
"set"]
322 "$ ------------------------------------------------------------------------------\n"
324 "$ ------------------------------------------------------------------------------\n\n"
325 "$set {}\n\n".format(section, setIdx)
327 messages = data.sections[section]
328 for num, message
in enumerate(messages, 1):
329 f.write(
'{} "{}"\n'.format(num, message.toSrc()))
331 f.write(
"\n$ end of file $")
336 Create the message file for Windows OS
338 Encoding is in UTF-16LE
340 language = data.getMeta(
"Language")
341 langId = data.getMeta(
"LangId")
342 with open(messageFile,
"w", encoding=
"utf-16-le")
as f:
344 f.write(
"\nLanguageNames = ({0}={1}:msg_{1})\n\n".format(language, langId))
345 f.write(
"FacilityNames=(\n")
346 for section
in MessageData.orderedSections:
347 setIdx = MessageData.sectionInfo[section][
"set"]
348 shortName = MessageData.sectionInfo[section][
"short"]
349 f.write(
" {}={}\n".format(shortName, setIdx))
352 for section
in MessageData.orderedSections:
353 shortName = MessageData.sectionInfo[section][
"short"]
355 messages = data.sections[section]
356 for message
in messages:
362 "{}\n.\n\n".format(n, shortName, language, message.toMC())
364 f.write(
"\n; end of file ;")
368 parser = argparse.ArgumentParser(description=
"Generate message data files")
372 help=
"Print language identifier of the message catalog source file",
377 help=
"Prefix to be used for all C identifiers (type and variable names)"
378 " in enum and default message files.",
380 parser.add_argument(
"--enum", metavar=
"FILE", help=
"Generate enum file named FILE")
382 "--default", metavar=
"FILE", help=
"Generate default messages file named FILE"
385 "--signature", metavar=
"FILE", help=
"Generate signature file named FILE"
388 "--message", metavar=
"FILE", help=
"Generate message file named FILE"
391 "--target-system-override",
392 metavar=
"TARGET_SYSTEM_NAME",
393 help=
"Target System override.\n"
394 "By default the target system is the host system\n"
395 "See possible values at https://docs.python.org/3/library/platform.html#platform.system",
397 parser.add_argument(
"inputfile")
398 commandArgs = parser.parse_args()
400 if commandArgs.lang_id:
403 data = MessageData.create(commandArgs.inputfile)
404 prefix = commandArgs.prefix
405 if commandArgs.target_system_override:
406 TargetPlatform.set_system_override(commandArgs.target_system_override)
409 if commandArgs.default:
411 if commandArgs.signature:
413 if commandArgs.message:
414 if TargetPlatform.system().casefold() ==
"Windows".casefold():
420if __name__ ==
"__main__":
423 except ScriptError
as e:
424 print(
"error: {}".format(e))
__init__(self, lineNumber, name, text)
__init__(self, filename, line, msg)
generate_enum_file(enumFile, prefix, data)
generate_default_messages_file(defaultFile, prefix, data)
generate_signature_file(signatureFile, data)
display_language_id(inputFile)
generate_message_file_unix(messageFile, data)
generate_message_file_windows(messageFile, data)
parse_error(filename, line, msg)
insert_header(f, data, commentChar="//")