blob: d24e662ec97cd816a0552db0b351e2a1b567852d [file] [log] [blame]
#!/usr/bin/python
#
# Copyright (C) 2010 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Generates icudtXXl-default.dat from icudtXXl-all.dat and icu-data-default.txt.
#
# Usage:
# icu_dat_generator.py [-v] [-h]
#
# Sample usage:
# $ANDROID_BUILD_TOP/external/icu4c/stubdata$ ./icu_dat_generator.py --verbose
import getopt
import glob
import os
import os.path
import re
import shutil
import subprocess
import sys
def PrintHelpAndExit():
print "Usage:"
print " icu_dat_generator.py [-v|--verbose] [-h|--help]"
print "Example:"
print " $ANDROID_BUILD_TOP/external/icu4c/stubdata$ ./icu_dat_generator.py"
sys.exit(1)
def InvokeIcuTool(tool, working_dir, args):
command_list = [os.path.join(ICU_PREBUILT_DIR, tool)]
command_list.extend(args)
if VERBOSE:
command = "[%s] %s" % (working_dir, " ".join(command_list))
print command
ret = subprocess.call(command_list, cwd=working_dir)
if ret != 0:
sys.exit(command_list[0:])
def ExtractAllResourceFilesToTmpDir():
# copy icudtXXl-all.dat to icudtXXl.dat
src_dat = os.path.join(ICU4C_DIR, "stubdata", ICU_DATA + "-all.dat")
dst_dat = os.path.join(ICU4C_DIR, "stubdata", ICU_DATA + ".dat")
shutil.copyfile(src_dat, dst_dat)
InvokeIcuTool("icupkg", None, [dst_dat, "-x", "*", "-d", TMP_DAT_PATH])
def MakeDat(input_file, stubdata_dir):
print "------ Processing '%s'..." % (input_file)
if not os.path.isfile(input_file):
print "%s not a file!" % input_file
sys.exit(1)
GenResIndex(input_file)
CopyAndroidCnvFiles(stubdata_dir)
# Run "icupkg -tl -s icudtXXl -a icu-data-default.txt new icudtXXl.dat".
args = ["-tl", "-s", TMP_DAT_PATH, "-a", "add_list.txt", "new", ICU_DATA + ".dat"]
InvokeIcuTool("icupkg", TMP_DAT_PATH, args)
def ResFilesToLocales(res_files):
locales = []
for res_file in res_files:
# res_file is something like 'coll/en_US.res'.
if not '/' in res_file:
locales.append(res_file)
else:
locales.append(res_file.split('/')[1].replace('.res', ''))
return locales
def WriteIndex(path, locales):
empty_value = " {\"\"}\n" # key-value pair for all locale entries
f = open(path, "w")
f.write("res_index:table(nofallback) {\n")
f.write(" InstalledLocales {\n")
for locale in sorted(locales):
f.write(locale + empty_value)
f.write(" }\n")
f.write("}\n")
f.close()
def AddResFile(collection, path):
# There are two consumers of the the input .txt file: this script and
# icupkg. We only care about .res files, but icupkg needs files they depend
# on too, so it's not an error to have to ignore non-.res files here.
end = path.find(".res")
if end > 0:
collection.add(path[path.find("/")+1:end])
return
def AddAllResFiles(collection, dir_name, language):
pattern1 = '%s/data/%s/%s.txt' % (ICU4C_DIR, dir_name, language)
pattern2 = '%s/data/%s/%s_*.txt' % (ICU4C_DIR, dir_name, language)
for path in glob.glob(pattern1) + glob.glob(pattern2):
if 'TRADITIONAL' in path or 'PHONEBOOK' in path:
continue
parts = path.split('/')
if dir_name == 'locales':
path = parts[-1].replace('.txt', '')
else:
path = parts[-2] + '/' + parts[-1].replace('.txt', '.res')
collection.add(path)
def DumpFile(filename):
print ' ----------------- %s' % filename
os.system("cat %s" % filename)
print ' ----------------- END'
# Open input file (such as icu-data-default.txt).
# Go through the list and generate res_index.res for locales, brkitr,
# coll, et cetera.
def GenResIndex(input_file):
brkitrs = set()
colls = set()
currs = set()
langs = set()
locales = set()
regions = set()
zones = set()
languages = [
# Group 0.
'en',
# Group 1.
'ar',
'zh',
'nl',
'fr',
'de',
'it',
'ja',
'ko',
'pl',
'pt',
'ru',
'es',
'th',
'tr',
# Group 2.
'bg',
'ca',
'hr',
'cs',
'da',
'fil','tl',
'fi',
'el',
'iw','he',
'hi',
'hu',
'id','in',
'lv',
'lt',
'nb',
'ro',
'sr',
'sk',
'sl',
'sv',
'uk',
'vi',
'fa',
# Group 3.
'af',
'am',
'bn',
'et',
'is',
'ms',
'mr',
'sw',
'ta',
'zu',
# Group 4.
'eu',
'gl',
'gu',
'kn',
'ml',
'te',
'ur',
# Group 5.
'km',
'lo',
'ne',
'si',
'ka',
'hy',
'mn',
'cy',
# Others.
'az',
'be',
'rm',
]
for language in languages:
AddAllResFiles(brkitrs, 'brkitr', language)
AddAllResFiles(colls, 'coll', language)
AddAllResFiles(currs, 'curr', language)
AddAllResFiles(langs, 'lang', language)
AddAllResFiles(regions, 'region', language)
AddAllResFiles(zones, 'zone', language)
AddAllResFiles(locales, 'locales', language)
# We need to merge the human-edited icu-data-default.txt with the
# machine-generated list of files needed to support the various languages.
new_add_list = []
for line in open(input_file, "r"):
new_add_list.append(line)
if "root." in line or "res_index" in line or "_.res" in line:
continue
if "brkitr/" in line:
AddResFile(brkitrs, line)
elif "coll/" in line:
AddResFile(colls, line)
elif "curr/" in line:
AddResFile(currs, line)
elif "lang/" in line:
AddResFile(langs, line)
elif "region/" in line:
AddResFile(regions, line)
elif "zone/" in line:
AddResFile(zones, line)
elif ".res" in line:
# TODO: these should all now be misc resources!
# We need to determine the resource is locale resource or misc resource.
# To determine the locale resource, we assume max script length is 3.
end = line.find(".res")
if end <= 3 or (line.find("_") <= 3 and line.find("_") > 0):
locales.add(line[:end])
kind_to_res_files = {
"brkitr": brkitrs,
"coll": colls,
"curr": currs,
"lang": langs,
"locales": locales,
"region": regions,
"zone": zones
}
# Merge the machine-generated list into the human-generated list.
for kind, res_files in kind_to_res_files.items():
for res_file in sorted(res_files):
if '.' not in res_file:
res_file = res_file + '.res'
new_add_list.append(res_file)
if VERBOSE:
for kind, res_files in kind_to_res_files.items():
print "%s=%s" % (kind, sorted(res_files))
# Write the genrb input files.
# First add_list.txt, the argument to icupkg -a...
f = open(os.path.join(TMP_DAT_PATH, "add_list.txt"), "w")
for line in new_add_list:
if line.startswith('#'):
continue
f.write("%s\n" % line)
f.close()
# Second res_index.txt, used below by genrb.
res_index = "res_index.txt"
WriteIndex(os.path.join(TMP_DAT_PATH, res_index), locales)
for kind, res_files in kind_to_res_files.items():
if kind == "locales":
continue
res_index_filename = os.path.join(TMP_DAT_PATH, kind, res_index)
WriteIndex(res_index_filename, ResFilesToLocales(res_files))
if VERY_VERBOSE:
DumpFile(res_index_filename)
# Useful if you need to see the temporary input files we generated.
if VERY_VERBOSE:
DumpFile('%s/add_list.txt' % TMP_DAT_PATH)
DumpFile('%s/res_index.txt' % TMP_DAT_PATH)
# Call genrb to generate new res_index.res.
InvokeIcuTool("genrb", TMP_DAT_PATH, [res_index])
for kind, res_files in kind_to_res_files.items():
if kind == "locales":
continue
InvokeIcuTool("genrb", os.path.join(TMP_DAT_PATH, kind), [res_index])
def CopyAndroidCnvFiles(stubdata_dir):
android_specific_cnv = ["gsm-03.38-2000.cnv",
"iso-8859_16-2001.cnv",
"docomo-shift_jis-2012.cnv",
"kddi-jisx-208-2007.cnv",
"kddi-shift_jis-2012.cnv",
"softbank-jisx-208-2007.cnv",
"softbank-shift_jis-2012.cnv"]
for cnv_file in android_specific_cnv:
src_path = os.path.join(stubdata_dir, "cnv", cnv_file)
dst_path = os.path.join(TMP_DAT_PATH, cnv_file)
shutil.copyfile(src_path, dst_path)
if VERBOSE:
print "copy " + src_path + " " + dst_path
def main():
global ANDROID_BUILD_TOP # $ANDROID_BUILD_TOP
global ICU4C_DIR # $ANDROID_BUILD_TOP/external/icu4c
global ICU_PREBUILT_DIR # Directory containing pre-built ICU tools.
global ICU_DATA # e.g. "icudt50l"
global TMP_DAT_PATH # Temporary directory to store all resource files and
# intermediate dat files.
global VERBOSE, VERY_VERBOSE
VERBOSE = VERY_VERBOSE = False
show_help = False
try:
opts, args = getopt.getopt(sys.argv[1:], "hv", ["help", "verbose", "very-verbose"])
except getopt.error:
PrintHelpAndExit()
for opt, _ in opts:
if opt in ("-h", "--help"):
show_help = True
elif opt in ("-v", "--verbose"):
VERBOSE = True
elif opt in ("--very-verbose"):
VERY_VERBOSE = VERBOSE = True
if args:
show_help = True
if show_help:
PrintHelpAndExit()
ANDROID_BUILD_TOP = os.environ.get("ANDROID_BUILD_TOP")
if not ANDROID_BUILD_TOP:
print "$ANDROID_BUILD_TOP not set! Run 'env_setup.sh'."
sys.exit(1)
ICU4C_DIR = os.path.join(ANDROID_BUILD_TOP, "external", "icu4c")
stubdata_dir = os.path.join(ICU4C_DIR, "stubdata")
# Work out the ICU version from the source .dat filename, so we can find the
# appropriate pre-built ICU tools.
source_dat = os.path.basename(glob.glob(os.path.join(stubdata_dir, "icudt*.dat"))[0])
icu_version = re.sub(r"([^0-9])", "", source_dat)
ICU_PREBUILT_DIR = os.path.join(os.environ.get("ANDROID_BUILD_TOP"),
"prebuilts", "misc", "linux-x86_64", "icu-%s%s" % (icu_version[0], icu_version[1]))
if not os.path.exists(ICU_PREBUILT_DIR):
print "%s does not exist!" % ICU_PREBUILT_DIR
ICU_DATA = "icudt" + icu_version + "l"
# Check that icudtXXl-all.dat exists (since we build the other .dat files from that).
full_data_filename = os.path.join(stubdata_dir, ICU_DATA + "-all.dat")
if not os.path.isfile(full_data_filename):
print "%s not present." % full_data_filename
sys.exit(1)
# Create a temporary working directory.
TMP_DAT_PATH = os.path.join(ICU4C_DIR, "tmp")
if os.path.exists(TMP_DAT_PATH):
shutil.rmtree(TMP_DAT_PATH)
os.mkdir(TMP_DAT_PATH)
# Extract resource files from icudtXXl-all.dat to TMP_DAT_PATH.
ExtractAllResourceFilesToTmpDir()
input_file = os.path.join(stubdata_dir, "icu-data-default.txt")
output_file = os.path.join(stubdata_dir, ICU_DATA + "-default.dat")
MakeDat(input_file, stubdata_dir)
shutil.copyfile(os.path.join(TMP_DAT_PATH, ICU_DATA + ".dat"), output_file)
print "Generated ICU data: %s" % output_file
# Cleanup temporary working directory and icudtXXl.dat
shutil.rmtree(TMP_DAT_PATH)
os.remove(os.path.join(stubdata_dir, ICU_DATA + ".dat"))
if __name__ == "__main__":
main()