summaryrefslogtreecommitdiffstats
path: root/ppapi/generators
diff options
context:
space:
mode:
Diffstat (limited to 'ppapi/generators')
-rw-r--r--ppapi/generators/idl_lexer.py51
-rw-r--r--ppapi/generators/idl_option.py109
-rw-r--r--ppapi/generators/idl_outfile.py17
-rw-r--r--ppapi/generators/idl_parser.py71
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