#! /usr/bin/python import sys import xml.dom.minidom def check_static_char_array_length(name, array): # some compilers like VC6 doesn't allow static arrays more than 64K bytes size. size = reduce(lambda x, y: x+len(escapedString(y)), array, 0) if size > 65535: print "\n\n\n#error Array %s is too long! " % name sys.stderr.write("\n\n\nERROR: the content of the array '%s' is too long: %d > 65535 " % (name, size)) sys.exit(1) def wrap_list(lst): def split(lst, size): for i in range(len(lst)/size+1): yield lst[i*size:(i+1)*size] return ",\n".join(map(lambda x: ", ".join(x), split(lst, 20))) def firstChildElt(parent, name): child = parent.firstChild while child: if child.nodeType == parent.ELEMENT_NODE \ and (not name or child.nodeName == name): return child child = child.nextSibling return False def nextSiblingElt(sibling, name): sib = sibling.nextSibling while sib: if sib.nodeType == sibling.ELEMENT_NODE \ and (not name or sib.nodeName == name): return sib sib = sib.nextSibling return False def eltText(elt): result = "" child = elt.firstChild while child: if child.nodeType == elt.TEXT_NODE: if result: result += " " result += child.nodeValue child = child.nextSibling return result def loadLanguageMap(doc): result = {} language_list_elt = firstChildElt(doc.documentElement, "languageList") language_elt = firstChildElt(language_list_elt, "language") while language_elt: language_id = int(eltText(firstChildElt(language_elt, "id"))) language_name = eltText(firstChildElt(language_elt, "name")) language_code = eltText(firstChildElt(language_elt, "code")) result[language_id] = (language_name, language_code) language_elt = nextSiblingElt(language_elt, "language") return result def loadCountryMap(doc): result = {} country_list_elt = firstChildElt(doc.documentElement, "countryList") country_elt = firstChildElt(country_list_elt, "country") while country_elt: country_id = int(eltText(firstChildElt(country_elt, "id"))) country_name = eltText(firstChildElt(country_elt, "name")) country_code = eltText(firstChildElt(country_elt, "code")) result[country_id] = (country_name, country_code) country_elt = nextSiblingElt(country_elt, "country") return result def loadDefaultMap(doc): result = {} list_elt = firstChildElt(doc.documentElement, "defaultCountryList") elt = firstChildElt(list_elt, "defaultCountry") while elt: country = eltText(firstChildElt(elt, "country")); language = eltText(firstChildElt(elt, "language")); result[language] = country; elt = nextSiblingElt(elt, "defaultCountry"); return result def fixedCountryName(name, dupes): if name in dupes: return name + "Country" return name def fixedLanguageName(name, dupes): if name in dupes: return name + "Language" return name def findDupes(country_map, language_map): country_set = set([ v[0] for a, v in country_map.iteritems() ]) language_set = set([ v[0] for a, v in language_map.iteritems() ]) return country_set & language_set def languageNameToId(name, language_map): for key in language_map.keys(): if language_map[key][0] == name: return key return -1 def countryNameToId(name, country_map): for key in country_map.keys(): if country_map[key][0] == name: return key return -1 def convertFormat(format): result = "" i = 0 while i < len(format): if format[i] == "'": result += "'" i += 1 while i < len(format) and format[i] != "'": result += format[i] i += 1 if i < len(format): result += "'" i += 1 else: s = format[i:] if s.startswith("EEEE"): result += "dddd" i += 4 elif s.startswith("EEE"): result += "ddd" i += 3 elif s.startswith("a"): result += "AP" i += 1 elif s.startswith("z"): result += "t" i += 1 elif s.startswith("v"): i += 1 else: result += format[i] i += 1 return result class Locale: def __init__(self, elt): self.language = eltText(firstChildElt(elt, "language")) self.country = eltText(firstChildElt(elt, "country")) self.decimal = int(eltText(firstChildElt(elt, "decimal"))) self.group = int(eltText(firstChildElt(elt, "group"))) self.listDelim = int(eltText(firstChildElt(elt, "list"))) self.percent = int(eltText(firstChildElt(elt, "percent"))) self.zero = int(eltText(firstChildElt(elt, "zero"))) self.minus = int(eltText(firstChildElt(elt, "minus"))) self.plus = int(eltText(firstChildElt(elt, "plus"))) self.exp = int(eltText(firstChildElt(elt, "exp"))) self.am = eltText(firstChildElt(elt, "am")) self.pm = eltText(firstChildElt(elt, "pm")) self.longDateFormat = convertFormat(eltText(firstChildElt(elt, "longDateFormat"))) self.shortDateFormat = convertFormat(eltText(firstChildElt(elt, "shortDateFormat"))) self.longTimeFormat = convertFormat(eltText(firstChildElt(elt, "longTimeFormat"))) self.shortTimeFormat = convertFormat(eltText(firstChildElt(elt, "shortTimeFormat"))) self.standaloneLongMonths = eltText(firstChildElt(elt, "standaloneLongMonths")) self.standaloneShortMonths = eltText(firstChildElt(elt, "standaloneShortMonths")) self.standaloneNarrowMonths = eltText(firstChildElt(elt, "standaloneNarrowMonths")) self.longMonths = eltText(firstChildElt(elt, "longMonths")) self.shortMonths = eltText(firstChildElt(elt, "shortMonths")) self.narrowMonths = eltText(firstChildElt(elt, "narrowMonths")) self.standaloneLongDays = eltText(firstChildElt(elt, "standaloneLongDays")) self.standaloneShortDays = eltText(firstChildElt(elt, "standaloneShortDays")) self.standaloneNarrowDays = eltText(firstChildElt(elt, "standaloneNarrowDays")) self.longDays = eltText(firstChildElt(elt, "longDays")) self.shortDays = eltText(firstChildElt(elt, "shortDays")) self.narrowDays = eltText(firstChildElt(elt, "narrowDays")) def loadLocaleMap(doc, language_map, country_map): result = {} locale_list_elt = firstChildElt(doc.documentElement, "localeList") locale_elt = firstChildElt(locale_list_elt, "locale") while locale_elt: locale = Locale(locale_elt) language_id = languageNameToId(locale.language, language_map) country_id = countryNameToId(locale.country, country_map) result[(language_id, country_id)] = locale locale_elt = nextSiblingElt(locale_elt, "locale") return result def compareLocaleKeys(key1, key2): if key1 == key2: return 0 if key1[0] == key2[0]: l1 = compareLocaleKeys.locale_map[key1] l2 = compareLocaleKeys.locale_map[key2] if l1.language in compareLocaleKeys.default_map: default = compareLocaleKeys.default_map[l1.language] if l1.country == default: return -1 if l2.country == default: return 1 else: return key1[0] - key2[0] return key1[1] - key2[1] def languageCount(language_id, locale_map): result = 0 for key in locale_map.keys(): if key[0] == language_id: result += 1 return result class StringDataToken: def __init__(self, index, length): self.index = index self.length = length def __str__(self): return " %d,%d " % (self.index, self.length) class StringData: def __init__(self): self.data = [] self.hash = {} def append(self, s): if s in self.hash: return self.hash[s] lst = map(lambda x: hex(ord(x)), s) index = len(self.data) if index >= 65535: print "\n\n\n#error Data index is too big!" sys.stderr.write ("\n\n\nERROR: index exceeds the uint16 range! index = %d\n" % index) sys.exit(1) size = len(lst) if size >= 65535: print "\n\n\n#error Data is too big!" sys.stderr.write ("\n\n\nERROR: data size exceeds the uint16 range! size = %d\n" % size) sys.exit(1) token = StringDataToken(index, size) self.hash[s] = token self.data += lst return token def escapedString(s): result = "" i = 0 while i < len(s): if s[i] == '"': result += '\\"' i += 1 else: result += s[i] i += 1 s = result line = "" need_escape = False result = "" for c in s: if ord(c) < 128 and (not need_escape or ord(c.lower()) < ord('a') or ord(c.lower()) > ord('f')): line += c need_escape = False else: line += "\\x%02x" % (ord(c)) need_escape = True if len(line) > 80: result = result + "\n" + "\"" + line + "\"" line = "" line += "\\0" result = result + "\n" + "\"" + line + "\"" if result[0] == "\n": result = result[1:] return result def printEscapedString(s): print escapedString(s); def main(): doc = xml.dom.minidom.parse("locale.xml") language_map = loadLanguageMap(doc) country_map = loadCountryMap(doc) default_map = loadDefaultMap(doc) locale_map = loadLocaleMap(doc, language_map, country_map) dupes = findDupes(language_map, country_map) # Language enum print "enum Language {" language = "" for key in language_map.keys(): language = fixedLanguageName(language_map[key][0], dupes) print " " + language + " = " + str(key) + "," print " LastLanguage = " + language print "};" print # Country enum print "enum Country {" country = "" for key in country_map.keys(): country = fixedCountryName(country_map[key][0], dupes) print " " + country + " = " + str(key) + "," print " LastCountry = " + country print "};" print # Locale index print "static const uint locale_index[] = {" print " 0, // unused" index = 0 for key in language_map.keys(): i = 0 count = languageCount(key, locale_map) if count > 0: i = index index += count print "%6d, // %s" % (i, language_map[key][0]) print " 0 // trailing 0" print "};" print date_format_data = StringData() time_format_data = StringData() months_data = StringData() standalone_months_data = StringData() days_data = StringData() am_data = StringData() pm_data = StringData() # Locale data print "static const QLocalePrivate locale_data[] = {" print "// lang terr dec group list prcnt zero minus plus exp sDtFmt lDtFmt sTmFmt lTmFmt ssMonth slMonth sMonth lMonth sDays lDays am,len pm,len" locale_keys = locale_map.keys() compareLocaleKeys.default_map = default_map compareLocaleKeys.locale_map = locale_map locale_keys.sort(compareLocaleKeys) for key in locale_keys: l = locale_map[key] print " { %6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s }, // %s/%s" \ % (key[0], key[1], l.decimal, l.group, l.listDelim, l.percent, l.zero, l.minus, l.plus, l.exp, date_format_data.append(l.shortDateFormat), date_format_data.append(l.longDateFormat), time_format_data.append(l.shortTimeFormat), time_format_data.append(l.longTimeFormat), standalone_months_data.append(l.standaloneShortMonths), standalone_months_data.append(l.standaloneLongMonths), standalone_months_data.append(l.standaloneNarrowMonths), months_data.append(l.shortMonths), months_data.append(l.longMonths), months_data.append(l.narrowMonths), days_data.append(l.standaloneShortDays), days_data.append(l.standaloneLongDays), days_data.append(l.standaloneNarrowDays), days_data.append(l.shortDays), days_data.append(l.longDays), days_data.append(l.narrowDays), am_data.append(l.am), pm_data.append(l.pm), l.language, l.country) print " { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 } // trailing 0s" print "};" print # Date format data #check_static_char_array_length("date_format", date_format_data.data) print "static const ushort date_format_data[] = {" print wrap_list(date_format_data.data) print "};" print # Time format data #check_static_char_array_length("time_format", time_format_data.data) print "static const ushort time_format_data[] = {" print wrap_list(time_format_data.data) print "};" print # Months data #check_static_char_array_length("months", months_data.data) print "static const ushort months_data[] = {" print wrap_list(months_data.data) print "};" print # Standalone months data #check_static_char_array_length("standalone_months", standalone_months_data.data) print "static const ushort standalone_months_data[] = {" print wrap_list(standalone_months_data.data) print "};" print # Days data #check_static_char_array_length("days", days_data.data) print "static const ushort days_data[] = {" print wrap_list(days_data.data) print "};" print # AM data #check_static_char_array_length("am", am_data.data) print "static const ushort am_data[] = {" print wrap_list(am_data.data) print "};" print # PM data #check_static_char_array_length("pm", am_data.data) print "static const ushort pm_data[] = {" print wrap_list(pm_data.data) print "};" print # Language name list print "static const char language_name_list[] =" print "\"Default\\0\"" for key in language_map.keys(): print "\"" + language_map[key][0] + "\\0\"" print ";" print # Language name index print "static const uint language_name_index[] = {" print " 0, // Unused" index = 8 for key in language_map.keys(): language = language_map[key][0] print "%6d, // %s" % (index, language) index += len(language) + 1 print "};" print # Country name list print "static const char country_name_list[] =" print "\"Default\\0\"" for key in country_map.keys(): if key == 0: continue print "\"" + country_map[key][0] + "\\0\"" print ";" print # Country name index print "static const uint country_name_index[] = {" print " 0, // AnyCountry" index = 8 for key in country_map.keys(): if key == 0: continue country = country_map[key][0] print "%6d, // %s" % (index, country) index += len(country) + 1 print "};" print # Language code list print "static const unsigned char language_code_list[] =" print "\" \\0\" // Unused" for key in language_map.keys(): code = language_map[key][1] if len(code) == 2: code += r"\0" print "\"%2s\" // %s" % (code, language_map[key][0]) print ";" print # Country code list print "static const unsigned char country_code_list[] =" for key in country_map.keys(): print "\"%2s\" // %s" % (country_map[key][1], country_map[key][0]) print ";" if __name__ == "__main__": main()