#!/usr/bin/env python3 # -*- coding: utf-8 -*- # # SPDX-FileCopyrightText: 2014 Denis Steckelmacher # # SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL from jsgenerator import * def license(): # Print the license of the generated file (the same as the one of this file) print(""" /* * ==== FILE AUTOGENERATED FROM .idl FILES UNDER THE FOLLOWING LICENSE ==== * * Copyright (C) 2008 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ """) def get_type(decl): typename = ' '.join(decl[0:-1]) if typename == 'void': typename = '' elif typename == 'any': typename = '_mixed' elif typename == 'boolean' or typename == 'bool': typename = 'true' elif typename == 'DOMString': typename = "''" elif typename == 'DOMObject': typename = 'new Object()' elif typename == 'DOMTimeStamp': typename = 'new Date()' elif 'unsigned' in typename or ' short' in typename or ' int' in typename or ' long' in typename or typename in ['short', 'int', 'long']: typename = '1' elif typename == 'float' or typename == 'double': typename = '1.0' elif typename == 'Array': typename = '[]' elif 'Callback' in typename or 'Handler' in typename: typename = 'function(){}' elif 'Constructor' in typename: typename = typename.replace('Constructor', '') else: typename = 'new %s()' % typename return typename def get_name(decl): return decl[-1] member_decl = [] param_decl = [] params = [] skip_end_of_line = False in_module = False in_interface = False in_inherit = False in_param = False cl = None def parse(token): global member_decl, param_decl, params, skip_end_of_line, in_module, in_interface, in_inherit, in_param, cl if token in ['in', 'readonly', 'optional', 'attribute', 'getter', 'setter', '{', '}']: pass elif token == 'raises': skip_end_of_line = True elif token == 'module': in_module = True elif token == 'interface': in_module = False in_interface = True elif in_module: # Skip the module declaration pass elif in_interface: # Interface name cl = Class(token) in_interface = False if token == 'DOMWindow': # Export window, the only thing that should be exposed to the outside world print('module.exports = DOMWindow;') elif token == ';': # End the current declaration if len(member_decl) == 0: # When the end of a class is reached, an empty declaration is produced cl.print() return if in_param: # Declare a method cl.member(F(get_type(member_decl), get_name(member_decl), \ *[(get_name(p), get_type(p)) for p in params] )) else: # Declare a member variable if get_type(member_decl) is not None and get_name(member_decl)[0].isalpha(): cl.member(Var(get_type(member_decl), get_name(member_decl))) member_decl.clear() params.clear() skip_end_of_line = False in_param = False elif skip_end_of_line: # Skip everything until the colon pass elif token == ':': in_inherit = True elif in_inherit: cl.prototype(token) in_inherit = False elif token == '(': # Begin the parameter list in_param = True elif token == ')' or token == ',': # End of a parameter if len(param_decl) != 0: params.append(param_decl[:]) param_decl.clear() pass elif in_param: # Add a token to the parameter declaration param_decl.append(token) else: # Add a token to the member declaration member_decl.append(token) def tokenize(data): token = '' prev_c = '' c = '' next_c = '' in_comment = 'none' bracket_depth = 0 for i in range(len(data) + 1): prev_c = c c = next_c if i < len(data): next_c = data[i] # Handle single-line and multi-line comments if in_comment == 'singleline': if c == '\n': in_comment = 'none' continue if in_comment == 'multiline': if prev_c == '*' and c == '/': in_comment = 'none' continue if c == '/' and next_c == '*': in_comment = 'multiline' continue if c == '/' and next_c == '/': in_comment = 'singleline' continue if c == '#': # Skip preprocessor macros: consider them as comments in_comment = 'singleline' continue # Skip hints between brackets if c == '[': bracket_depth += 1 continue elif c == ']': bracket_depth -= 1 continue if bracket_depth > 0: continue # Spaces are used to separate tokens if not c.isalnum() or not token.isalnum(): if token != '': parse(token) token = '' if c.isspace(): continue token += c def main(): license() for fl in sys.argv[1:]: f = open(fl, 'r') tokenize(f.read()) f.close() if __name__ == '__main__': if len(sys.argv) < 2: print('Usage: idltojs.py ') else: main()