| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env python | |
| 2 # Copyright (c) 2013 Google Inc. All rights reserved. | |
| 3 # | |
| 4 # Redistribution and use in source and binary forms, with or without | |
| 5 # modification, are permitted provided that the following conditions are | |
| 6 # met: | |
| 7 # | |
| 8 # * Redistributions of source code must retain the above copyright | |
| 9 # notice, this list of conditions and the following disclaimer. | |
| 10 # * Redistributions in binary form must reproduce the above | |
| 11 # copyright notice, this list of conditions and the following disclaimer | |
| 12 # in the documentation and/or other materials provided with the | |
| 13 # distribution. | |
| 14 # * Neither the name of Google Inc. nor the names of its | |
| 15 # contributors may be used to endorse or promote products derived from | |
| 16 # this software without specific prior written permission. | |
| 17 # | |
| 18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 29 | |
| 30 import re | |
| 31 import sys | |
| 32 import json | |
| 33 | |
| 34 | |
| 35 def parse_idl_file(idlFileName): | |
| 36 idlFile = open(idlFileName, "r") | |
| 37 source = idlFile.read() | |
| 38 idlFile.close() | |
| 39 | |
| 40 source = re.sub(r"//.*\n", "", source) # Remove line comments | |
| 41 source = re.sub(r"\s+", " ", source) # Line breaks to spaces, collapse
spaces | |
| 42 source = re.sub(r"/\*.*?\*/", "", source) # Remove block comments | |
| 43 source = re.sub(r"\[.*?\]", "", source) # Remove method parameters and ar
ray type suffixes | |
| 44 source = re.sub(r"\?", "", source) # Remove optional type suffixes | |
| 45 | |
| 46 parsed_webgl_calls = [] | |
| 47 | |
| 48 # Search for method signatures | |
| 49 for line in source.split(";"): | |
| 50 match = re.match(r"^\s*(\w[\w\s]*)\s+(\w+)\s*\(([^()]*)\)", line) | |
| 51 if not match: | |
| 52 continue | |
| 53 | |
| 54 return_type = match.group(1).strip() | |
| 55 function_name = match.group(2) | |
| 56 arguments_string = match.group(3) | |
| 57 | |
| 58 # Search for argument signatures | |
| 59 argument_types = [] | |
| 60 for argument in arguments_string.split(","): | |
| 61 match = re.match(r"^\s*(\w[\w\s]*)\s+(\w+)\s*$", argument) | |
| 62 if not match: | |
| 63 continue | |
| 64 argument_types.append(match.group(1).strip()) | |
| 65 | |
| 66 # Special case for texParameterf/texParameteri and getTexParameter: trea
t the parameter as GLenum regardless of the IDL specification: | |
| 67 # void texParameterf(GLenum target, GLenum pname, GLfloat param) | |
| 68 # void texParameteri(GLenum target, GLenum pname, GLint param) | |
| 69 # any getTexParameter(GLenum target, GLenum pname) | |
| 70 if function_name == "texParameterf" or function_name == "texParameteri": | |
| 71 argument_types[2] = "GLenum" | |
| 72 if function_name == "getTexParameter": | |
| 73 return_type = "GLenum" | |
| 74 | |
| 75 parsed_webgl_calls.append({"function_name": function_name, "return_type"
: return_type, "argument_types": argument_types}) | |
| 76 | |
| 77 return parsed_webgl_calls | |
| 78 | |
| 79 | |
| 80 def generate_json_lines(parsed_webgl_calls): | |
| 81 enum_types = ["GLenum", "GLbitfield"] | |
| 82 hints = { | |
| 83 "blendFunc": ["ZERO", "ONE"], | |
| 84 "blendFuncSeparate": ["ZERO", "ONE"], | |
| 85 "stencilOp": ["ZERO", "ONE"], | |
| 86 "stencilOpSeparate": ["ZERO", "ONE"], | |
| 87 "drawArrays": ["POINTS", "LINES"], | |
| 88 "drawElements": ["POINTS", "LINES"], | |
| 89 "getError": ["NO_ERROR"], | |
| 90 } | |
| 91 | |
| 92 json_lines = [] | |
| 93 for call in parsed_webgl_calls: | |
| 94 function_name = call["function_name"] | |
| 95 return_type = call["return_type"] | |
| 96 argument_types = call["argument_types"] | |
| 97 | |
| 98 if not (return_type in enum_types or set(enum_types).intersection(argume
nt_types)): | |
| 99 continue | |
| 100 | |
| 101 # Using "aname" instead of "name" to make it the first parameter after s
orting (for readability sake). | |
| 102 result = {"aname": function_name} | |
| 103 if return_type in enum_types: | |
| 104 result["returnType"] = return_type[2:] | |
| 105 | |
| 106 for enum_type in enum_types: | |
| 107 if not enum_type in argument_types: | |
| 108 continue | |
| 109 result[enum_type[2:]] = [i for i in range(len(argument_types)) if ar
gument_types[i] == enum_type] | |
| 110 | |
| 111 if function_name in hints: | |
| 112 result["hints"] = hints[function_name] | |
| 113 | |
| 114 result_json = json.dumps(result, sort_keys=True) | |
| 115 if result_json in json_lines: | |
| 116 continue | |
| 117 json_lines.append(result_json) | |
| 118 | |
| 119 return json_lines | |
| 120 | |
| 121 | |
| 122 def check_injected_script_js_file(jsFileName, json_lines): | |
| 123 jsFile = open(jsFileName, "r") | |
| 124 source = jsFile.read() | |
| 125 jsFile.close() | |
| 126 | |
| 127 missing_lines = [] | |
| 128 for line in json_lines: | |
| 129 if not line in source: | |
| 130 missing_lines.append(line) | |
| 131 | |
| 132 if len(missing_lines): | |
| 133 print "ERROR: Injected script file is missing %d line(s) of generated co
de: " % len(missing_lines) | |
| 134 for line in missing_lines: | |
| 135 print " %s" % line | |
| 136 else: | |
| 137 print "OK" | |
| 138 | |
| 139 | |
| 140 def main(argv): | |
| 141 if len(argv) < 2: | |
| 142 print('Usage: %s path/to/WebGLRenderingContext.idl [path/to/InjectedScri
ptCanvasModuleSource.js]' % argv[0]) | |
| 143 return 1 | |
| 144 | |
| 145 parsed_webgl_calls = parse_idl_file(argv[1]) | |
| 146 json_lines = generate_json_lines(parsed_webgl_calls) | |
| 147 | |
| 148 if len(json_lines) < 50: | |
| 149 print "WARNING: too few WebGL methods parsed: %d! Something wrong with t
he IDL file parsing?" % len(json_lines) | |
| 150 | |
| 151 if len(argv) > 2: | |
| 152 check_injected_script_js_file(argv[2], json_lines) | |
| 153 | |
| 154 if __name__ == '__main__': | |
| 155 sys.exit(main(sys.argv)) | |
| OLD | NEW |