File indexing completed on 2024-05-19 15:46:48
0001 #!/usr/bin/env python3 0002 # -*- coding: utf-8 -*- 0003 # 0004 # SPDX-FileCopyrightText: 2014 Denis Steckelmacher <steckdenis@yahoo.fr> 0005 # 0006 # SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0007 0008 from jsgenerator import * 0009 0010 def license(): 0011 # Print the license of the generated file (the same as the one of this file) 0012 print(""" 0013 /* 0014 * ==== FILE AUTOGENERATED FROM .idl FILES UNDER THE FOLLOWING LICENSE ==== 0015 * 0016 * Copyright (C) 2008 Apple Inc. All Rights Reserved. 0017 * 0018 * Redistribution and use in source and binary forms, with or without 0019 * modification, are permitted provided that the following conditions 0020 * are met: 0021 * 1. Redistributions of source code must retain the above copyright 0022 * notice, this list of conditions and the following disclaimer. 0023 * 2. Redistributions in binary form must reproduce the above copyright 0024 * notice, this list of conditions and the following disclaimer in the 0025 * documentation and/or other materials provided with the distribution. 0026 * 0027 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 0028 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 0029 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 0030 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 0031 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 0032 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 0033 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 0034 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 0035 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 0036 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 0037 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 0038 */ 0039 """) 0040 0041 def get_type(decl): 0042 typename = ' '.join(decl[0:-1]) 0043 0044 if typename == 'void': 0045 typename = '' 0046 elif typename == 'any': 0047 typename = '_mixed' 0048 elif typename == 'boolean' or typename == 'bool': 0049 typename = 'true' 0050 elif typename == 'DOMString': 0051 typename = "''" 0052 elif typename == 'DOMObject': 0053 typename = 'new Object()' 0054 elif typename == 'DOMTimeStamp': 0055 typename = 'new Date()' 0056 elif 'unsigned' in typename or ' short' in typename or ' int' in typename or ' long' in typename or typename in ['short', 'int', 'long']: 0057 typename = '1' 0058 elif typename == 'float' or typename == 'double': 0059 typename = '1.0' 0060 elif typename == 'Array': 0061 typename = '[]' 0062 elif 'Callback' in typename or 'Handler' in typename: 0063 typename = 'function(){}' 0064 elif 'Constructor' in typename: 0065 typename = typename.replace('Constructor', '') 0066 else: 0067 typename = 'new %s()' % typename 0068 0069 return typename 0070 0071 def get_name(decl): 0072 return decl[-1] 0073 0074 member_decl = [] 0075 param_decl = [] 0076 params = [] 0077 skip_end_of_line = False 0078 in_module = False 0079 in_interface = False 0080 in_inherit = False 0081 in_param = False 0082 cl = None 0083 0084 def parse(token): 0085 global member_decl, param_decl, params, skip_end_of_line, in_module, in_interface, in_inherit, in_param, cl 0086 0087 if token in ['in', 'readonly', 'optional', 'attribute', 'getter', 'setter', '{', '}']: 0088 pass 0089 elif token == 'raises': 0090 skip_end_of_line = True 0091 elif token == 'module': 0092 in_module = True 0093 elif token == 'interface': 0094 in_module = False 0095 in_interface = True 0096 elif in_module: 0097 # Skip the module declaration 0098 pass 0099 elif in_interface: 0100 # Interface name 0101 cl = Class(token) 0102 in_interface = False 0103 0104 if token == 'DOMWindow': 0105 # Export window, the only thing that should be exposed to the outside world 0106 print('module.exports = DOMWindow;') 0107 0108 elif token == ';': 0109 # End the current declaration 0110 if len(member_decl) == 0: 0111 # When the end of a class is reached, an empty declaration is produced 0112 cl.print() 0113 return 0114 0115 if in_param: 0116 # Declare a method 0117 cl.member(F(get_type(member_decl), get_name(member_decl), \ 0118 *[(get_name(p), get_type(p)) for p in params] 0119 )) 0120 else: 0121 # Declare a member variable 0122 if get_type(member_decl) is not None and get_name(member_decl)[0].isalpha(): 0123 cl.member(Var(get_type(member_decl), get_name(member_decl))) 0124 0125 member_decl.clear() 0126 params.clear() 0127 skip_end_of_line = False 0128 in_param = False 0129 elif skip_end_of_line: 0130 # Skip everything until the colon 0131 pass 0132 elif token == ':': 0133 in_inherit = True 0134 elif in_inherit: 0135 cl.prototype(token) 0136 in_inherit = False 0137 elif token == '(': 0138 # Begin the parameter list 0139 in_param = True 0140 elif token == ')' or token == ',': 0141 # End of a parameter 0142 if len(param_decl) != 0: 0143 params.append(param_decl[:]) 0144 param_decl.clear() 0145 0146 pass 0147 elif in_param: 0148 # Add a token to the parameter declaration 0149 param_decl.append(token) 0150 else: 0151 # Add a token to the member declaration 0152 member_decl.append(token) 0153 0154 def tokenize(data): 0155 token = '' 0156 prev_c = '' 0157 c = '' 0158 next_c = '' 0159 in_comment = 'none' 0160 bracket_depth = 0 0161 0162 for i in range(len(data) + 1): 0163 prev_c = c 0164 c = next_c 0165 0166 if i < len(data): 0167 next_c = data[i] 0168 0169 # Handle single-line and multi-line comments 0170 if in_comment == 'singleline': 0171 if c == '\n': 0172 in_comment = 'none' 0173 continue 0174 0175 if in_comment == 'multiline': 0176 if prev_c == '*' and c == '/': 0177 in_comment = 'none' 0178 continue 0179 0180 if c == '/' and next_c == '*': 0181 in_comment = 'multiline' 0182 continue 0183 0184 if c == '/' and next_c == '/': 0185 in_comment = 'singleline' 0186 continue 0187 0188 if c == '#': 0189 # Skip preprocessor macros: consider them as comments 0190 in_comment = 'singleline' 0191 continue 0192 0193 # Skip hints between brackets 0194 if c == '[': 0195 bracket_depth += 1 0196 continue 0197 elif c == ']': 0198 bracket_depth -= 1 0199 continue 0200 0201 if bracket_depth > 0: 0202 continue 0203 0204 # Spaces are used to separate tokens 0205 if not c.isalnum() or not token.isalnum(): 0206 if token != '': 0207 parse(token) 0208 token = '' 0209 0210 if c.isspace(): 0211 continue 0212 0213 token += c 0214 0215 def main(): 0216 license() 0217 0218 for fl in sys.argv[1:]: 0219 f = open(fl, 'r') 0220 tokenize(f.read()) 0221 f.close() 0222 0223 if __name__ == '__main__': 0224 if len(sys.argv) < 2: 0225 print('Usage: idltojs.py <idl...>') 0226 else: 0227 main()