| #!/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') |