-
+# encoding=utf-8
#
# Usage:
# gen_xmlpool.py /path/to/t_option.h localedir lang lang lang ...
# `{localedir}/{language}/LC_MESSAGES/options.mo`.
#
-from __future__ import print_function
+from __future__ import print_function, unicode_literals
import argparse
import gettext
import io
import re
import sys
-parser = argparse.ArgumentParser()
-parser.add_argument('template')
-parser.add_argument('localedir')
-parser.add_argument('languages', nargs='*')
-args = parser.parse_args()
-
if sys.version_info < (3, 0):
gettext_method = 'ugettext'
else:
# " -> '' is a hack. Quotes (") aren't possible in XML attributes.
# Better use Unicode characters for typographic quotes in option
# descriptions and translations.
+ last_quote = '”'
i = 0
r = ''
- while i < len(s):
- # Special case: escape double quote with \u201c or \u201d, depending
+ for c in s:
+ # Special case: escape double quote with “ or ”, depending
# on whether it's an open or close quote. This is needed because plain
# double quotes are not possible in XML attributes.
- if s[i] == '"':
- if i == len(s) - 1 or s[i + 1].isspace():
- # close quote
- q = u'\u201c'
+ if c == '"':
+ if last_quote == '”':
+ q = '“'
else:
- # open quote
- q = u'\u201d'
+ q = '”'
+ last_quote = q
r = r + q
- elif s[i] in escapeSeqs:
- r = r + escapeSeqs[s[i]]
+ elif c in escapeSeqs:
+ r = r + escapeSeqs[c]
else:
- r = r + s[i]
- i = i + 1
+ r = r + c
return r
# Expand escape sequences in C strings (needed for gettext lookup)
escapeSeqs = {'a' : '\a', 'b' : '\b', 'f' : '\f', 'n' : '\n',
'r' : '\r', 't' : '\t', 'v' : '\v',
'"' : '"', '\\' : '\\'}
- i = 0
escape = False
hexa = False
octa = False
num = 0
digits = 0
r = u''
- while i < len(s):
+ for c in s:
if not escape:
- if s[i] == '\\':
+ if c == '\\':
escape = True
else:
- r = r + s[i]
+ r = r + c
elif hexa:
- if (s[i] >= '0' and s[i] <= '9') or \
- (s[i] >= 'a' and s[i] <= 'f') or \
- (s[i] >= 'A' and s[i] <= 'F'):
- num = num * 16 + int(s[i],16)
+ if (c >= '0' and c <= '9') or \
+ (c >= 'a' and c <= 'f') or \
+ (c >= 'A' and c <= 'F'):
+ num = num * 16 + int(c, 16)
digits = digits + 1
else:
digits = 2
escape = False
r = r + chr(num)
elif octa:
- if s[i] >= '0' and s[i] <= '7':
- num = num * 8 + int(s[i],8)
+ if c >= '0' and c <= '7':
+ num = num * 8 + int(c, 8)
digits = digits + 1
else:
digits = 3
escape = False
r = r + chr(num)
else:
- if s[i] in escapeSeqs:
- r = r + escapeSeqs[s[i]]
+ if c in escapeSeqs:
+ r = r + escapeSeqs[c]
escape = False
- elif s[i] >= '0' and s[i] <= '7':
+ elif c >= '0' and c <= '7':
octa = True
- num = int(s[i],8)
+ num = int(c, 8)
if num <= 3:
digits = 1
else:
digits = 2
- elif s[i] == 'x' or s[i] == 'X':
+ elif c == 'x' or c == 'X':
hexa = True
num = 0
digits = 0
else:
- r = r + s[i]
+ r = r + c
escape = False
- i = i + 1
return r
# Expand matches. The first match is always a DESC or DESC_BEGIN match.
#
# DESC, DESC_BEGIN format: \1 \2=<lang> \3 \4=gettext(" \5=<text> \6=") \7
# ENUM format: \1 \2=gettext(" \3=<text> \4=") \5
-def expandMatches(matches, translations, end=None):
+def expandMatches(matches, translations, outfile, end=None):
assert len(matches) > 0
nTranslations = len(translations)
i = 0
matches[0].expand (r'\5'))))
text = (matches[0].expand(r'\1' + lang + r'\3"' + text + r'"\7') + suffix)
- # In Python 2, stdout expects encoded byte strings, or else it will
- # encode them with the ascii 'codec'
- if sys.version_info.major == 2:
- text = text.encode('utf-8')
-
- print(text)
+ outfile.write(text + '\n')
# Expand any subsequent enum lines
for match in matches[1:]:
match.expand(r'\3'))))
text = match.expand(r'\1"' + text + r'"\5')
- # In Python 2, stdout expects encoded byte strings, or else it will
- # encode them with the ascii 'codec'
- if sys.version_info.major == 2:
- text = text.encode('utf-8')
-
- print(text)
+ outfile.write(text + '\n')
# Expand description end
if end:
- print(end, end='')
-
-# Compile a list of translation classes to all supported languages.
-# The first translation is always a NullTranslations.
-translations = [("en", gettext.NullTranslations())]
-for lang in args.languages:
- try:
- filename = os.path.join(args.localedir, '{}.gmo'.format(lang))
- with io.open(filename, 'rb') as f:
- trans = gettext.GNUTranslations(f)
- except (IOError, OSError):
- print("Warning: language '%s' not found." % lang, file=sys.stderr)
- continue
- translations.append((lang, trans))
+ outfile.write(end)
# Regular expressions:
reLibintl_h = re.compile(r'#\s*include\s*<libintl.h>')
reENUM = re.compile(r'(\s*DRI_CONF_ENUM\s*\([^,]+,\s*)(gettext\s*\(\s*")(.*)("\s*\))(\s*\)[ \t]*\\?)$')
reDESC_END = re.compile(r'\s*DRI_CONF_DESC_END')
-# Print a header
-print("/***********************************************************************\n" \
-" *** THIS FILE IS GENERATED AUTOMATICALLY. DON'T EDIT! ***\n" \
-" ***********************************************************************/")
-
-# Process the options template and generate options.h with all
-# translations.
-template = io.open(args.template, mode="rt", encoding='utf-8')
-descMatches = []
-for line in template:
- if len(descMatches) > 0:
- matchENUM = reENUM.match(line)
- matchDESC_END = reDESC_END.match(line)
- if matchENUM:
- descMatches.append(matchENUM)
- elif matchDESC_END:
- expandMatches(descMatches, translations, line)
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--template', required=True)
+ parser.add_argument('--output', required=True)
+ parser.add_argument('--localedir', required=True)
+ parser.add_argument('--languages', nargs='*', default=[])
+ args = parser.parse_args()
+
+ # Compile a list of translation classes to all supported languages.
+ # The first translation is always a NullTranslations.
+ translations = [("en", gettext.NullTranslations())]
+ for lang in args.languages:
+ try:
+ filename = os.path.join(args.localedir, '{}.gmo'.format(lang))
+ with io.open(filename, 'rb') as f:
+ trans = gettext.GNUTranslations(f)
+ except (IOError, OSError):
+ print("Warning: language '%s' not found." % lang, file=sys.stderr)
+ continue
+ translations.append((lang, trans))
+
+ with io.open(args.output, mode='wt', encoding='utf-8') as output:
+ output.write("/* This is file is generated automatically. Don't edit! */\n")
+
+ # Process the options template and generate options.h with all
+ # translations.
+ with io.open(args.template, mode="rt", encoding='utf-8') as template:
descMatches = []
- else:
- print("Warning: unexpected line inside description dropped:\n", line,
- file=sys.stderr)
- continue
- if reLibintl_h.search(line):
- # Ignore (comment out) #include <libintl.h>
- print("/* %s * commented out by gen_xmlpool.py */" % line)
- continue
- matchDESC = reDESC.match(line)
- matchDESC_BEGIN = reDESC_BEGIN.match(line)
- if matchDESC:
- assert len(descMatches) == 0
- expandMatches([matchDESC], translations)
- elif matchDESC_BEGIN:
- assert len(descMatches) == 0
- descMatches = [matchDESC_BEGIN]
- else:
- # In Python 2, stdout expects encoded byte strings, or else it will
- # encode them with the ascii 'codec'
- if sys.version_info.major == 2:
- line = line.encode('utf-8')
-
- print(line, end='')
-
-template.close()
-
-if len(descMatches) > 0:
- print("Warning: unterminated description at end of file.", file=sys.stderr)
- expandMatches(descMatches, translations)
+ for line in template:
+ if descMatches:
+ matchENUM = reENUM.match(line)
+ matchDESC_END = reDESC_END.match(line)
+ if matchENUM:
+ descMatches.append(matchENUM)
+ elif matchDESC_END:
+ expandMatches(descMatches, translations, output, line)
+ descMatches = []
+ else:
+ print("Warning: unexpected line inside description dropped:\n",
+ line, file=sys.stderr)
+ continue
+ if reLibintl_h.search(line):
+ # Ignore (comment out) #include <libintl.h>
+ output.write("/* %s * commented out by gen_xmlpool.py */\n" % line)
+ continue
+ matchDESC = reDESC.match(line)
+ matchDESC_BEGIN = reDESC_BEGIN.match(line)
+ if matchDESC:
+ assert not descMatches
+ expandMatches([matchDESC], translations, output)
+ elif matchDESC_BEGIN:
+ assert not descMatches
+ descMatches = [matchDESC_BEGIN]
+ else:
+
+ output.write(line)
+
+ if descMatches:
+ print("Warning: unterminated description at end of file.", file=sys.stderr)
+ expandMatches(descMatches, translations, output)
+
+
+if __name__ == '__main__':
+ main()