diff options
Diffstat (limited to 'ppapi/generators')
-rw-r--r-- | ppapi/generators/idl_lexer.py | 51 | ||||
-rw-r--r-- | ppapi/generators/idl_option.py | 109 | ||||
-rw-r--r-- | ppapi/generators/idl_outfile.py | 17 | ||||
-rw-r--r-- | ppapi/generators/idl_parser.py | 71 |
4 files changed, 161 insertions, 87 deletions
diff --git a/ppapi/generators/idl_lexer.py b/ppapi/generators/idl_lexer.py index 56594a2..744d69b 100644 --- a/ppapi/generators/idl_lexer.py +++ b/ppapi/generators/idl_lexer.py @@ -17,19 +17,10 @@ # PLY can be found at: # http://www.dabeaz.com/ply/ -import getopt import os.path import re import sys -LEXER_OPTIONS = { - 'output': False, - 'test_expect' : False, - 'test_same' : False, - 'verbose': False -} - - # # Try to load the ply module, if not, then assume it is in the third_party # directory, relative to ppapi @@ -42,7 +33,12 @@ except: sys.path.append(third_party) from ply import lex +from idl_option import GetOption, Option, ParseOptions + +Option('output', 'Generate output.') +Option('test_same', 'Test that the output matches.') +Option('test_expect', 'Test that the output matches.') # # IDL Lexer @@ -172,10 +168,8 @@ class IDLLexer(object): self.index = [0] self.lexobj.input(data) - def __init__(self, options = {}): + def __init__(self): self.lexobj = lex.lex(object=self, lextab=None, optimize=0) - for k in options: - LEXER_OPTIONS[k] = True @@ -221,12 +215,10 @@ def TextToTokens(source): # old set. # def TestSame(values): - global LEXER_OPTIONS - src1 = ' '.join(values) src2 = ' '.join(TextToTokens(src1)) - if LEXER_OPTIONS['output']: + if GetOption('output'): sys.stdout.write('Generating original.txt and tokenized.txt\n') open('original.txt', 'w').write(src1) open('tokenized.txt', 'w').write(src2) @@ -273,35 +265,15 @@ def TestExpect(tokens): def Main(args): - global LEXER_OPTIONS + filenames = ParseOptions(args) try: - long_opts = ['output', 'verbose', 'test_expect', 'test_same'] - usage = 'Usage: idl_lexer.py %s [<src.idl> ...]' % ' '.join( - ['--%s' % opt for opt in long_opts]) - - opts, filenames = getopt.getopt(args, '', long_opts) - except getopt.error, e: - sys.stderr.write('Illegal option: %s\n%s\n' % (str(e), usage)) - return 1 - - output = False - test_same = False - test_expect = False - verbose = False - - for opt, val in opts: - LEXER_OPTIONS[opt[2:]] = True - - try: - tokens = FilesToTokens(filenames, verbose) + tokens = FilesToTokens(filenames, GetOption('verbose')) values = [tok.value for tok in tokens] - if LEXER_OPTIONS['output']: sys.stdout.write(' <> '.join(values) + '\n') - if LEXER_OPTIONS['test_same']: + if GetOption('output'): sys.stdout.write(' <> '.join(values) + '\n') + if GetOption('test'): if TestSame(values): return -1 - - if LEXER_OPTIONS['test_expect']: if TestExpect(tokens): return -1 return 0 @@ -310,7 +282,6 @@ def Main(args): sys.stderr.write('%s\n' % str(le)) return -1 - if __name__ == '__main__': sys.exit(Main(sys.argv[1:])) diff --git a/ppapi/generators/idl_option.py b/ppapi/generators/idl_option.py new file mode 100644 index 0000000..0f7aa46 --- /dev/null +++ b/ppapi/generators/idl_option.py @@ -0,0 +1,109 @@ +#!/usr/bin/python +# +# Copyright (c) 2011 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 getopt +import sys + +from idl_log import ErrOut, InfoOut, WarnOut + +OptionMap = { } + + +def GetOption(name): + if name not in OptionMap: + raise RuntimeError('Could not find option "%s".' % name) + return OptionMap[name].Get() + +class Option(object): + def __init__(self, name, desc, default = None, callfunc = None, + testfunc = None, cookie = None): + + # Verify this option is not a duplicate + if name in OptionMap: + raise RuntimeError('Option "%s" already exists.' % name) + self.name = name + self.desc = desc + self.default = default + self.value = default + self.callfunc = callfunc + self.testfunc = testfunc + self.cookie = cookie + OptionMap[name] = self + + def Set(self, value): + if self.testfunc: + if not self.testfunc(self, value): return False + # If this is a boolean option, set it to true + if not self.default: + self.value = True + else: + self.value = value + if self.callfunc: + self.callfunc(self) + return True + + def Get(self): + return self.value + + +def DumpOption(option): + if len(option.name) > 1: + out = ' --%-15.15s\t%s' % (option.name, option.desc) + else: + out = ' -%-15.15s\t%s' % (option.name, option.desc) + if option.default: + out = ' %-15.15s\t%s\n\t\tDefault: %s\n' % (' ', out, option.default) + InfoOut.Log(out) + +def DumpHelp(option=None): + InfoOut.Log('Usage:') + for opt in sorted(OptionMap.keys()): + DumpOption(OptionMap[opt]) + + +# +# Default IDL options +# +# -h : Help, prints options +# --verbose : use verbose output +# --test : test this module +# +Option('h', 'Help', callfunc=DumpHelp) +Option('verbose', 'Verbose') +Option('test', 'Test the IDL scripts') + +def ParseOptions(args): + short_opts= "" + long_opts = [] + + # Build short and long option lists + for name in sorted(OptionMap.keys()): + option = OptionMap[name] + if len(name) > 1: + if option.default is None: + long_opts.append('%s' % name) + else: + long_opts.append('%s=' % name) + else: + if option.default is None: + short_opts += name + else: + short_opts += '%s:' % name + + try: + opts, filenames = getopt.getopt(args, short_opts, long_opts) + + for opt, val in opts: + if len(opt) == 2: opt = opt[1:] + if opt[0:2] == '--': opt = opt[2:] + OptionMap[opt].Set(val) + + except getopt.error, e: + ErrOut.Log('Illegal option: %s\n' % str(e)) + DumpHelp() + sys.exit(-1) + + return filenames diff --git a/ppapi/generators/idl_outfile.py b/ppapi/generators/idl_outfile.py index a9e4506..76262d7 100644 --- a/ppapi/generators/idl_outfile.py +++ b/ppapi/generators/idl_outfile.py @@ -22,9 +22,10 @@ from stat import * # the output files are used by a timestamp dependent build system # class IDLOutFile(object): - def __init__(self, filename, always_write = False): + def __init__(self, filename, always_write = False, create_dir = True): self.filename = filename self.always_write = always_write + self.create_dir = create_dir self.outlist = [] self.open = True @@ -36,15 +37,27 @@ class IDLOutFile(object): # Close the file def Close(self): + filename = os.path.realpath(self.filename) self.open = False outtext = ''.join(self.outlist) if not self.always_write: - intext = open(filename, 'r').read() + if os.path.isfile(filename): + intext = open(filename, 'r').read() + else: + intext = None + if intext == outtext: InfoOut.Log('Output %s unchanged.' % self.filename) return False try: + # If the directory does not exit, try to create it, if we fail, we + # still get the exception when the file is openned. + basepath, leafname = os.path.split(filename) + if basepath and not os.path.isdir(basepath) and self.create_dir: + InfoOut.Log('Creating directory: %s\n' % basepath) + os.makedirs(basepath) + outfile = open(filename, 'w') outfile.write(''.join(self.outlist)) InfoOut.Log('Output %s written.' % self.filename) diff --git a/ppapi/generators/idl_parser.py b/ppapi/generators/idl_parser.py index 5c33555..615d4dc 100644 --- a/ppapi/generators/idl_parser.py +++ b/ppapi/generators/idl_parser.py @@ -32,18 +32,15 @@ import sys from idl_log import ErrOut, InfoOut, WarnOut from idl_lexer import IDLLexer from idl_node import IDLAttribute, IDLAst, IDLNode +from idl_option import GetOption, Option, ParseOptions from ply import lex from ply import yacc -PARSER_OPTIONS = { - 'build_debug': False, - 'parse_debug': False, - 'token_debug': False, - 'test' : False, - 'output': False, - 'verbose': False -} +Option('build_debug', 'Debug tree building.') +Option('parse_debug', 'Debug parse reduction steps.') +Option('token_debug', 'Debug token generation.') +Option('dump_tree', 'Dump the tree.') # # ERROR_REMAP @@ -581,20 +578,15 @@ class IDLParser(IDLLexer): self.parse_errors += 1 - def __init__(self, options = {}): - global PARSER_OPTIONS - - IDLLexer.__init__(self, options) + def __init__(self): + IDLLexer.__init__(self) self.yaccobj = yacc.yacc(module=self, tabmodule=None, debug=False, optimize=0, write_tables=0) - for k in options: - PARSER_OPTIONS[k] = options[k] - - self.build_debug = PARSER_OPTIONS['build_debug'] - self.parse_debug = PARSER_OPTIONS['parse_debug'] - self.token_debug = PARSER_OPTIONS['token_debug'] - self.verbose = PARSER_OPTIONS['verbose'] + self.build_debug = GetOption('build_debug') + self.parse_debug = GetOption('parse_debug') + self.token_debug = GetOption('token_debug') + self.verbose = GetOption('verbose') self.parse_errors = 0 # @@ -787,11 +779,11 @@ def TestFile(parser, filename): return TestErrors(filename, result.out) -def TestErrorFiles(options): +def TestErrorFiles(): idldir = os.path.split(sys.argv[0])[0] idldir = os.path.join(idldir, 'test_parser', '*.idl') filenames = glob.glob(idldir) - parser = IDLParser(options) + parser = IDLParser() total_errs = 0 for filename in filenames: errs = TestFile(parser, filename) @@ -805,13 +797,13 @@ def TestErrorFiles(options): InfoOut.Log("Passed parsing test.") return total_errs -def TestNamespaceFiles(options): +def TestNamespaceFiles(): idldir = os.path.split(sys.argv[0])[0] idldir = os.path.join(idldir, 'test_namespace', '*.idl') filenames = glob.glob(idldir) InfoOut.SetConsole(False) - result = ParseFiles(filenames, options) + result = ParseFiles(filenames) InfoOut.SetConsole(True) if result.errs: @@ -821,8 +813,8 @@ def TestNamespaceFiles(options): return result.errs -def ParseFiles(filenames, options): - parser = IDLParser(options) +def ParseFiles(filenames): + parser = IDLParser() filenodes = [] errors = 0 @@ -849,34 +841,23 @@ def ParseFiles(filenames, options): def Main(args): - global PARSER_OPTIONS - - long_opts = PARSER_OPTIONS.keys() - usage = 'Usage: idl_parser.py %s [<src.idl> ...]' % ' '.join(long_opts) - try: - opts, filenames = getopt.getopt(args, '', long_opts) + filenames = ParseOptions(args) - except getopt.error, e: - ErrOut.Log('Illegal option: %s\n\t%s' % (str(e) % usage)) - return 1 - - for opt, val in opts: - PARSER_OPTIONS[opt[2:]] = True - - if PARSER_OPTIONS['test']: - errs = TestErrorFiles(PARSER_OPTIONS) - errs = TestNamespaceFiles(PARSER_OPTIONS) + # If testing... + if GetOption('test'): + errs = TestErrorFiles() + errs = TestNamespaceFiles() if errs: ErrOut.Log("Parser failed with %d errors." % errs) return -1 + return 0 - result = ParseFiles(filenames, PARSER_OPTIONS) - if PARSER_OPTIONS['output']: + # Otherwise, build the AST + result = ParseFiles(filenames) + if GetOption('dump_tree'): result.out.Dump(0) - if result.errs: ErrOut.Log('Found %d error(s).' % result.errors); - InfoOut.Log("%d files processed." % len(filenames)) return result.errs |