blob: 6b2b300ce1c45da525c8b06313b79f7327d06de2 [file] [log] [blame]
#!/usr/bin/env python
# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import re
import sys
import json
import optparse
# Matches the include statement in the braille table files.
INCLUDE_RE = re.compile(r"^\s*include\s+([^#\s]+)")
# Exclude these files from table validation.
IGNORE_TABLES = set()
IGNORE_TABLES.add('boxes.ctb')
IGNORE_TABLES.add('unicode-braille.utb')
IGNORE_TABLES.add('IPA.utb')
IGNORE_TABLES.add('spaces.ctb')
IGNORE_TABLES.add('ethio-g1.ctb')
IGNORE_TABLES.add('or-in-g1.utb')
def Error(msg):
print >> sys.stderr, 'liblouis_list_tables: %s' % msg
sys.exit(1)
def ToNativePath(pathname):
return os.path.sep.join(pathname.split('/'))
def LoadTablesFile(filename):
with open(ToNativePath(filename), 'r') as fh:
try:
return json.load(fh)
except ValueError, e:
raise ValueError('Error parsing braille table file %s: %s' %
(filename, e.message))
def FindFile(filename, directories):
for d in directories:
fullname = '/'.join([d, filename])
if os.path.isfile(ToNativePath(fullname)):
return fullname
Error('File not found: %s' % filename)
def FindAllTableFiles(directory):
ret = set()
for filename in os.listdir(directory):
if filename.endswith(".ctb") or filename.endswith(".utb"):
ret.add(filename)
return ret
def GetIncludeFiles(filename):
result = []
with open(ToNativePath(filename), 'r') as fh:
for line in fh.xreadlines():
match = INCLUDE_RE.match(line)
if match:
result.append(match.group(1))
return result
def ProcessFile(output_set, filename, directories, indent=0):
fullname = FindFile(filename, directories)
if fullname in output_set:
return
output_set.add(indent*" " + fullname)
for include_file in GetIncludeFiles(fullname):
ProcessFile(output_set, include_file, directories, indent=2)
def GetTableFiles(tables_file, directories, extra_files):
tables = LoadTablesFile(tables_file)
output_set = set()
for table in tables:
for name in table['fileNames'].split(','):
ProcessFile(output_set, name, directories)
for name in extra_files:
ProcessFile(output_set, name, directories)
return output_set
def CheckTables(tables_file):
tables = LoadTablesFile(tables_file)
actual_set = set();
for table in tables:
for name in table['fileNames'].split(','):
actual_set.add(name)
expected_set = FindAllTableFiles("src/tables")
output = []
for table in actual_set:
if table not in expected_set and table not in IGNORE_TABLES:
output.append("Error: obsolete table not in liblouis " + table)
new_tables = []
for table in expected_set:
if table not in actual_set and table not in IGNORE_TABLES:
output.append("Error: table not found in tables file " + table)
new_tables.append(table)
return (output, new_tables)
def DoMain(argv):
"Entry point for gyp's pymod_do_main command."
parser = optparse.OptionParser()
# Give a clearer error message when this is used as a module.
parser.prog = 'liblouis_list_tables'
parser.set_usage('usage: %prog [options] listfile')
parser.add_option('-D', '--directory', dest='directories',
action='append', help='Where to search for table files')
parser.add_option('-e', '--extra_file', dest='extra_files', action='append',
default=[], help='Extra liblouis table file to process')
(options, args) = parser.parse_args(argv)
if len(args) != 1:
parser.error('Expecting exactly one argument')
if not options.directories:
parser.error('At least one --directory option must be specified')
files = GetTableFiles(args[0], options.directories, options.extra_files)
return '\n'.join(files)
def main(argv):
print DoMain(argv[1:])
if __name__ == '__main__':
try:
sys.exit(main(sys.argv))
except KeyboardInterrupt:
Error('interrupted')