Blame bindings/bindings.py

Packit Service 88ab54
#
Packit Service 88ab54
# Lasso - A free implementation of the Liberty Alliance specifications.
Packit Service 88ab54
#
Packit Service 88ab54
# Copyright (C) 2004-2007 Entr'ouvert
Packit Service 88ab54
# http://lasso.entrouvert.org
Packit Service 88ab54
#
Packit Service 88ab54
# Authors: See AUTHORS file in top-level directory.
Packit Service 88ab54
#
Packit Service 88ab54
# This program is free software; you can redistribute it and/or modify
Packit Service 88ab54
# it under the terms of the GNU General Public License as published by
Packit Service 88ab54
# the Free Software Foundation; either version 2 of the License, or
Packit Service 88ab54
# (at your option) any later version.
Packit Service 88ab54
#
Packit Service 88ab54
# This program is distributed in the hope that it will be useful,
Packit Service 88ab54
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 88ab54
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 88ab54
# GNU General Public License for more details.
Packit Service 88ab54
#
Packit Service 88ab54
# You should have received a copy of the GNU General Public License
Packit Service 88ab54
# along with this program; if not, see <http://www.gnu.org/licenses/>.
Packit Service 88ab54
Packit Service 88ab54
Packit Service 88ab54
import os
Packit Service 88ab54
import re
Packit Service 88ab54
from six import print_
Packit Service 88ab54
import sys
Packit Service 88ab54
from utils import *
Packit Service 88ab54
Packit Service 88ab54
from optparse import OptionParser
Packit Service 88ab54
Packit Service 88ab54
try:
Packit Service 88ab54
    from lxml import etree as ET
Packit Service 88ab54
except ImportError:
Packit Service 88ab54
    try:
Packit Service 88ab54
        import cElementTree as ET
Packit Service 88ab54
    except ImportError:
Packit Service 88ab54
        try:
Packit Service 88ab54
            import elementtree.ElementTree as ET
Packit Service 88ab54
        except ImportError:
Packit Service 88ab54
            import xml.etree.ElementTree as ET
Packit Service 88ab54
Packit Service 88ab54
sys.path.append(os.path.dirname(__file__))
Packit Service 88ab54
Packit Service 88ab54
# monkey patch os.path to include relpath if python version is < 2.6
Packit Service 88ab54
if not hasattr(os.path, "relpath"):
Packit Service 88ab54
    def relpath(longPath, basePath):
Packit Service 88ab54
        if not longPath.startswith(basePath):
Packit Service 88ab54
            raise RuntimeError("Unexpected arguments")
Packit Service 88ab54
        if longPath == basePath:
Packit Service 88ab54
            return "."
Packit Service 88ab54
        i = len(basePath)
Packit Service 88ab54
        if not basePath.endswith(os.path.sep):
Packit Service 88ab54
            i += len(os.path.sep)
Packit Service 88ab54
        return longPath[i:]
Packit Service 88ab54
Packit Service 88ab54
    os.path.relpath = relpath
Packit Service 88ab54
Packit Service 88ab54
Packit Service 88ab54
Packit Service 88ab54
class BindingData:
Packit Service 88ab54
    src_dir = os.path.dirname(__file__)
Packit Service 88ab54
Packit Service 88ab54
    def __init__(self, options = None):
Packit Service 88ab54
        self.headers = []
Packit Service 88ab54
        # [(char,string)]
Packit Service 88ab54
        # where char is:
Packit Service 88ab54
        # - i: integer
Packit Service 88ab54
        # - s: string
Packit Service 88ab54
        self.constants = []
Packit Service 88ab54
        self.structs = []
Packit Service 88ab54
        self.struct_dict = {}
Packit Service 88ab54
        self.functions = []
Packit Service 88ab54
        self.enums = []
Packit Service 88ab54
        self.options = options
Packit Service 88ab54
        self.overrides = ET.parse(os.path.join(self.src_dir, 'overrides.xml'))
Packit Service 88ab54
        self.functions_toskip = dict()
Packit Service 88ab54
        self.structs_toskip = dict()
Packit Service 88ab54
Packit Service 88ab54
        for func in self.overrides.findall('func'):
Packit Service 88ab54
            if func.attrib.get('skip') == 'true':
Packit Service 88ab54
                self.functions_toskip[func.attrib.get('name')] = 1
Packit Service 88ab54
        for struct in self.overrides.findall('struct'):
Packit Service 88ab54
            if struct.attrib.get('skip') == 'true':
Packit Service 88ab54
                self.structs_toskip[struct.attrib.get('name')] = 1
Packit Service 88ab54
Packit Service 88ab54
    def match_tag_language(self,tag):
Packit Service 88ab54
        if self.options and self.options.language:
Packit Service 88ab54
            languages = tag.attrib.get('language')
Packit Service 88ab54
            if languages:
Packit Service 88ab54
                lang_list = languages.split(' ')
Packit Service 88ab54
                if self.options.language in lang_list:
Packit Service 88ab54
                    return True
Packit Service 88ab54
                else:
Packit Service 88ab54
                    return False
Packit Service 88ab54
            else:
Packit Service 88ab54
                return True
Packit Service 88ab54
        else:
Packit Service 88ab54
            return True
Packit Service 88ab54
Packit Service 88ab54
    def display_structs(self):
Packit Service 88ab54
        for struct in self.structs:
Packit Service 88ab54
            struct.display()
Packit Service 88ab54
Packit Service 88ab54
    def display_funcs(self):
Packit Service 88ab54
        for func in self.functions:
Packit Service 88ab54
            print(func.return_type, func.name)
Packit Service 88ab54
            for a in func.args:
Packit Service 88ab54
                print('  ', a)
Packit Service 88ab54
Packit Service 88ab54
    def order_class_hierarchy(self):
Packit Service 88ab54
        new_order = []
Packit Service 88ab54
        while self.structs:
Packit Service 88ab54
            for c in self.structs:
Packit Service 88ab54
                if c.parent == 'GObject' or c.parent in [x.name for x in new_order]:
Packit Service 88ab54
                    self.structs.remove(c)
Packit Service 88ab54
                    new_order.append(c)
Packit Service 88ab54
                    break
Packit Service 88ab54
        self.structs = new_order
Packit Service 88ab54
Packit Service 88ab54
    def create_struct_dict(self):
Packit Service 88ab54
        for c in self.structs:
Packit Service 88ab54
            self.struct_dict[c.name] = c
Packit Service 88ab54
Packit Service 88ab54
    def attach_methods(self):
Packit Service 88ab54
        self.create_struct_dict()
Packit Service 88ab54
        for f in self.functions[:]:
Packit Service 88ab54
            if len(f.args) == 0:
Packit Service 88ab54
                continue
Packit Service 88ab54
            if f.name.endswith('_new') or '_new_' in f.name:
Packit Service 88ab54
                # constructor for another class
Packit Service 88ab54
                continue
Packit Service 88ab54
            arg_type = f.args[0][0]
Packit Service 88ab54
            if arg_type[-1] == '*':
Packit Service 88ab54
                arg_type = arg_type[:-1]
Packit Service 88ab54
            arg_type = arg_type.replace('const ','')
Packit Service 88ab54
            c = self.struct_dict.get(arg_type)
Packit Service 88ab54
            if not c:
Packit Service 88ab54
                continue
Packit Service 88ab54
            c.methods.append(f)
Packit Service 88ab54
            if f.docstring and f.docstring.parameters:
Packit Service 88ab54
                # remove first parameter, which is self/this/etc.
Packit Service 88ab54
                f.docstring.parameters = f.docstring.parameters[1:]
Packit Service 88ab54
Packit Service 88ab54
            self.functions.remove(f)
Packit Service 88ab54
Packit Service 88ab54
    def look_for_docstrings(self, srcdir, exception_doc):
Packit Service 88ab54
        def getfunc(name):
Packit Service 88ab54
            funcs = [f for f in self.functions if f.name == name]
Packit Service 88ab54
            if not funcs:
Packit Service 88ab54
                return None
Packit Service 88ab54
            else:
Packit Service 88ab54
                return funcs[0]
Packit Service 88ab54
        regex = re.compile(r'\/\*\*\s(.*?)\*\/', re.DOTALL)
Packit Service 88ab54
        for base, dirnames, filenames in os.walk(srcdir):
Packit Service 88ab54
            bname = os.path.basename(base)
Packit Service 88ab54
            if bname == '.svn':
Packit Service 88ab54
                # ignore svn directories
Packit Service 88ab54
                continue
Packit Service 88ab54
            if not 'Makefile.am' in filenames:
Packit Service 88ab54
                # not a source dir
Packit Service 88ab54
                continue
Packit Service 88ab54
            makefile_am = open(os.path.join(base, 'Makefile.am')).read()
Packit Service 88ab54
            filenames = [x for x in filenames if x.endswith('.c') if x in makefile_am]
Packit Service 88ab54
            for filename in filenames:
Packit Service 88ab54
                s = open(os.path.join(base, filename)).read()
Packit Service 88ab54
                docstrings = regex.findall(s)
Packit Service 88ab54
                for d in docstrings:
Packit Service 88ab54
                    docstring = '\n'.join([x[3:] for x in d.splitlines()])
Packit Service 88ab54
                    function_name = docstring.splitlines(1)[0].strip().strip(':')
Packit Service 88ab54
                    func = getfunc(function_name)
Packit Service 88ab54
                    if not func:
Packit Service 88ab54
                        continue
Packit Service 88ab54
                    func.docstring = DocString(func, docstring, self)
Packit Service 88ab54
        if exception_doc:
Packit Service 88ab54
            lines = os.popen('perl ../utility-scripts/error-analyzer.pl %s' % srcdir, 'r').readlines()
Packit Service 88ab54
            for line in lines:
Packit Service 88ab54
                elts = re.split(r' +',line.strip())
Packit Service 88ab54
                func = getfunc(elts[0])
Packit Service 88ab54
                if func:
Packit Service 88ab54
                    func.errors = elts[1:]
Packit Service 88ab54
Packit Service 88ab54
Packit Service 88ab54
class Struct:
Packit Service 88ab54
    def __init__(self, name):
Packit Service 88ab54
        self.name = name[1:] # skip leading _
Packit Service 88ab54
        self.parent = None
Packit Service 88ab54
        self.members = []
Packit Service 88ab54
        self.methods = []
Packit Service 88ab54
Packit Service 88ab54
    def __repr__(self):
Packit Service 88ab54
        return '<Struct name:%s, childof:%s>' % (self.name, self.parent)
Packit Service 88ab54
Packit Service 88ab54
    def display(self):
Packit Service 88ab54
        print(self.__repr__())
Packit Service 88ab54
        for m in self.members:
Packit Service 88ab54
            print('  ', m)
Packit Service 88ab54
        for m in self.methods:
Packit Service 88ab54
            print('  ', m)
Packit Service 88ab54
Packit Service 88ab54
    def getMember(self, name):
Packit Service 88ab54
        l = [m for m in self.members if arg_name(m) == name]
Packit Service 88ab54
        if l:
Packit Service 88ab54
            return l[0]
Packit Service 88ab54
        else:
Packit Service 88ab54
            return None
Packit Service 88ab54
Packit Service 88ab54
    def getMethod(self, name):
Packit Service 88ab54
        l = [m for m in self.methods if m.name == name]
Packit Service 88ab54
        if l:
Packit Service 88ab54
            return l[0]
Packit Service 88ab54
        else:
Packit Service 88ab54
            return None
Packit Service 88ab54
Packit Service 88ab54
toskip = None
Packit Service 88ab54
Packit Service 88ab54
Packit Service 88ab54
class Function:
Packit Service 88ab54
    return_type = None
Packit Service 88ab54
    return_type_qualifier = None
Packit Service 88ab54
    return_arg = None
Packit Service 88ab54
    name = None
Packit Service 88ab54
    rename = None
Packit Service 88ab54
    args = None
Packit Service 88ab54
    docstring = None
Packit Service 88ab54
    return_owner = True
Packit Service 88ab54
    skip = False
Packit Service 88ab54
    errors = None
Packit Service 88ab54
Packit Service 88ab54
    def __repr__(self):
Packit Service 88ab54
        return '<Function return_type:%s name:%s args:%r>' % (
Packit Service 88ab54
                self.return_arg, self.name, self.args)
Packit Service 88ab54
Packit Service 88ab54
    def apply_overrides(self):
Packit Service 88ab54
        for func in binding.overrides.findall('func'):
Packit Service 88ab54
            if not binding.match_tag_language(func):
Packit Service 88ab54
                continue
Packit Service 88ab54
            if func.attrib.get('name') != self.name:
Packit Service 88ab54
                continue
Packit Service 88ab54
            for param in func.findall('param'):
Packit Service 88ab54
                try:
Packit Service 88ab54
                    arg = [x for x in self.args if x[1] == param.attrib.get('name')][0]
Packit Service 88ab54
                except IndexError:
Packit Service 88ab54
                    print_('W: no such param (%s) in function (%s)' % (
Packit Service 88ab54
                            param.attrib.get('name'), self.name), file=sys.stderr)
Packit Service 88ab54
                    continue
Packit Service 88ab54
                if param.attrib.get('optional') == 'true':
Packit Service 88ab54
                    arg[2]['optional'] = True
Packit Service 88ab54
                if param.attrib.get('default'):
Packit Service 88ab54
                    arg[2]['default'] = param.attrib.get('default')
Packit Service 88ab54
                if param.attrib.get('type'):
Packit Service 88ab54
                    arg[0] = param.attrib.get('type')
Packit Service 88ab54
                if param.attrib.get('elem_type'):
Packit Service 88ab54
                    arg[2]['element-type'] = param.attrib.get('elem_type')
Packit Service 88ab54
            if func.attrib.get('rename'):
Packit Service 88ab54
                self.rename = func.attrib.get('rename')
Packit Service 88ab54
            if func.attrib.get('return_owner'):
Packit Service 88ab54
                self.return_owner = (func.attrib.get('return_owner') != 'false')
Packit Service 88ab54
            if func.attrib.get('return_type'):
Packit Service 88ab54
                self.return_type = func.attrib.get('return_type')
Packit Service 88ab54
            if func.attrib.get('skip'):
Packit Service 88ab54
                skip = func.attrib.get('skip')
Packit Service 88ab54
                if skip == 'true':
Packit Service 88ab54
                    self.skip = True
Packit Service 88ab54
                elif skip == 'unless-id-wsf' and not binding.options.idwsf:
Packit Service 88ab54
                    self.skip = True
Packit Service 88ab54
                elif binding.options.language in skip.split(','):
Packit Service 88ab54
                    self.skip = True
Packit Service 88ab54
            if func.attrib.get('return_type_qualifier'):
Packit Service 88ab54
                self.return_type_qualifier = func.attrib.get('return_type_qualifier')
Packit Service 88ab54
        for param in binding.overrides.findall('arg'):
Packit Service 88ab54
            if not binding.match_tag_language(param):
Packit Service 88ab54
                continue
Packit Service 88ab54
            arg_name = param.attrib.get('name')
Packit Service 88ab54
            arg_sub = param.attrib.get('rename')
Packit Service 88ab54
            if arg_name and arg_sub:
Packit Service 88ab54
                args = [ x for x in self.args if x[1] == arg_name]
Packit Service 88ab54
                for arg in args:
Packit Service 88ab54
                    arg[2]['original-name'] = arg[1]
Packit Service 88ab54
                    arg[1] = arg_sub
Packit Service 88ab54
Packit Service 88ab54
Packit Service 88ab54
class DocString:
Packit Service 88ab54
    orig_docstring = None
Packit Service 88ab54
    parameters = None
Packit Service 88ab54
    return_value = None
Packit Service 88ab54
    description = None
Packit Service 88ab54
Packit Service 88ab54
    def __init__(self, function, docstring, binding_data):
Packit Service 88ab54
        self.binding_data = binding_data
Packit Service 88ab54
        self.orig_docstring = docstring
Packit Service 88ab54
        self.parameters = []
Packit Service 88ab54
        self.params = {}
Packit Service 88ab54
        lines = docstring.splitlines()
Packit Service 88ab54
        # ignore the first line, it has the symbol name
Packit Service 88ab54
        lines = lines[1:]
Packit Service 88ab54
Packit Service 88ab54
        # look for parameters
Packit Service 88ab54
        while lines[0].strip():
Packit Service 88ab54
            if not self.parameters and not lines[0].startswith('@'):
Packit Service 88ab54
                # function without parameters
Packit Service 88ab54
                break
Packit Service 88ab54
            if not self.parameters:
Packit Service 88ab54
                self.parameters = []
Packit Service 88ab54
Packit Service 88ab54
            if lines[0][0] == '@':
Packit Service 88ab54
Packit Service 88ab54
                splits = lines[0][1:].split(':', 2)
Packit Service 88ab54
                param_name = splits[0]
Packit Service 88ab54
                if len(splits) > 2:
Packit Service 88ab54
                    param_options = splits[1]
Packit Service 88ab54
                    param_desc = splits[2]
Packit Service 88ab54
                    self.parameters.append([param_name, param_desc, param_options])
Packit Service 88ab54
                    self.params[param_name] = { 'desc': param_desc, 'options': param_options }
Packit Service 88ab54
                    for a in function.args:
Packit Service 88ab54
                        if a[1] == param_name or a[2].get('original-name') == param_name:
Packit Service 88ab54
                            arg = a
Packit Service 88ab54
                            break
Packit Service 88ab54
                    else:
Packit Service 88ab54
                        raise Exception('should not happen ' + param_name + ' ' + lines[0] + repr(function))
Packit Service 88ab54
                    self.annotation2arg(arg, param_options)
Packit Service 88ab54
                else:
Packit Service 88ab54
                    param_desc = splits[1]
Packit Service 88ab54
                    self.parameters.append([param_name, param_desc])
Packit Service 88ab54
                    self.params[param_name] = { 'desc': param_desc }
Packit Service 88ab54
            else:
Packit Service 88ab54
                # continuation of previous description
Packit Service 88ab54
                self.parameters[-1][1] = self.parameters[-1][1] + ' ' + lines[0].strip()
Packit Service 88ab54
Packit Service 88ab54
            lines = lines[1:]
Packit Service 88ab54
Packit Service 88ab54
        # blank line then description, till the end or the return value
Packit Service 88ab54
        lines = lines[1:]
Packit Service 88ab54
        self.description = ''
Packit Service 88ab54
        while not lines[0].startswith('Return value'):
Packit Service 88ab54
            self.description += lines[0] + '\n'
Packit Service 88ab54
            if len(lines) == 1:
Packit Service 88ab54
                self.description = self.description.strip()
Packit Service 88ab54
                return
Packit Service 88ab54
            lines = lines[1:]
Packit Service 88ab54
        self.description = self.description.strip()
Packit Service 88ab54
Packit Service 88ab54
        # return value
Packit Service 88ab54
        if lines[0].startswith('Return value') or lines[0].startswith('Returns'):
Packit Service 88ab54
            lines[0] = lines[0].split(':', 1)[1]
Packit Service 88ab54
            accu = ''
Packit Service 88ab54
            while lines[0].strip():
Packit Service 88ab54
                accu = accu + ' ' + lines[0].strip()
Packit Service 88ab54
                if len(lines) == 1:
Packit Service 88ab54
                    break
Packit Service 88ab54
                lines = lines[1:]
Packit Service 88ab54
            # find GObject-introspection annotations
Packit Service 88ab54
            if re.match(r'\s*\(', accu):
Packit Service 88ab54
                annotation, accu = accu.split(':', 1)
Packit Service 88ab54
                self.annotation2arg(function.return_arg, annotation)
Packit Service 88ab54
            self.return_value = accu.strip() # remove leading space
Packit Service 88ab54
    def annotation2arg(self, arg, annotation):
Packit Service 88ab54
        '''Convert GObject-introspection annotations to arg options'''
Packit Service 88ab54
Packit Service 88ab54
        if 'allow-none' in annotation:
Packit Service 88ab54
            arg[2]['optional'] = True
Packit Service 88ab54
        if re.search(r'\(\s*out\s*\)', annotation):
Packit Service 88ab54
            arg[2]['out'] = True
Packit Service 88ab54
        if re.search(r'\(\s*in\s*\)', annotation):
Packit Service 88ab54
            arg[2]['in'] = True
Packit Service 88ab54
        m = re.search(r'\(\s*default\s*([^ )]*)\s*\)', annotation)
Packit Service 88ab54
        if m:
Packit Service 88ab54
            prefix = ''
Packit Service 88ab54
            if is_boolean(arg):
Packit Service 88ab54
                prefix = 'b:'
Packit Service 88ab54
            elif is_int(arg, self.binding_data):
Packit Service 88ab54
                prefix = 'c:'
Packit Service 88ab54
            else:
Packit Service 88ab54
                raise Exception('should not happen: could not found type for default: ' + annotation)
Packit Service 88ab54
            arg[2]['default'] = prefix + m.group(1)
Packit Service 88ab54
            arg[2]['optional'] = True
Packit Service 88ab54
        m = re.search(r'\(\s*element-type\s+([\w*]+)(?:\s+([\w*]+))?', annotation)
Packit Service 88ab54
        if m:
Packit Service 88ab54
            if len(m.groups()) > 2:
Packit Service 88ab54
                arg[2]['key-type'] = \
Packit Service 88ab54
                        convert_type_from_gobject_annotation(m.group(1))
Packit Service 88ab54
                arg[2]['value-type'] = \
Packit Service 88ab54
                        convert_type_from_gobject_annotation(m.group(2))
Packit Service 88ab54
            else:
Packit Service 88ab54
                arg[2]['element-type'] = \
Packit Service 88ab54
                        convert_type_from_gobject_annotation(m.group(1))
Packit Service 88ab54
        m = re.search(r'\(\s*transfer\s+(\w+)', annotation)
Packit Service 88ab54
        if m:
Packit Service 88ab54
            arg[2]['transfer'] = m.group(1)
Packit Service 88ab54
Packit Service 88ab54
def normalise_var(type, name):
Packit Service 88ab54
    if name[0] == '*':
Packit Service 88ab54
        type += '*'
Packit Service 88ab54
        name = name[1:]
Packit Service 88ab54
    return type, name
Packit Service 88ab54
Packit Service 88ab54
exclude_private = True
Packit Service 88ab54
Packit Service 88ab54
def parse_header(header_file):
Packit Service 88ab54
    global binding
Packit Service 88ab54
Packit Service 88ab54
    struct_names = {}
Packit Service 88ab54
    in_comment = False
Packit Service 88ab54
    in_enum = False
Packit Service 88ab54
    in_struct = None
Packit Service 88ab54
    in_struct_private = False
Packit Service 88ab54
    in_ifdef_zero = False
Packit Service 88ab54
Packit Service 88ab54
    lines = open(header_file).readlines()
Packit Service 88ab54
    i = 0
Packit Service 88ab54
    while i < len(lines):
Packit Service 88ab54
        line = lines[i]
Packit Service 88ab54
        while line.endswith('\\\n'):
Packit Service 88ab54
            i += 1
Packit Service 88ab54
            line = line[:-2] + ' ' + lines[i].lstrip()
Packit Service 88ab54
Packit Service 88ab54
        if in_comment:
Packit Service 88ab54
            if '*/' in line:
Packit Service 88ab54
                in_comment = False
Packit Service 88ab54
        elif '/*' in line and not '*/' in line:
Packit Service 88ab54
            in_comment = True
Packit Service 88ab54
        elif in_ifdef_zero:
Packit Service 88ab54
            # minimal support for code sections commented with #if 0
Packit Service 88ab54
            if line.startswith('#endif'):
Packit Service 88ab54
                in_ifdef_zero = False
Packit Service 88ab54
        elif line.startswith('#if 0'):
Packit Service 88ab54
            in_ifdef_zero = True
Packit Service 88ab54
        elif in_enum:
Packit Service 88ab54
            if line.startswith('}'):
Packit Service 88ab54
                in_enum = False
Packit Service 88ab54
                enum_name = line[2:].strip().strip(';')
Packit Service 88ab54
                binding.enums.append(enum_name)
Packit Service 88ab54
            else:
Packit Service 88ab54
                m = re.match('\s*([a-zA-Z0-9_]+)', line)
Packit Service 88ab54
                if m:
Packit Service 88ab54
                    binding.constants.append(('i', m.group(1)))
Packit Service 88ab54
        elif line.startswith('#define'):
Packit Service 88ab54
            m = re.match(r'#define\s+([a-zA-Z0-9_]+)\s+([-\w"]+)', line)
Packit Service 88ab54
            if m:
Packit Service 88ab54
                constant_name = m.group(1)
Packit Service 88ab54
                if constant_name[0] != '_':
Packit Service 88ab54
                    # ignore private constants
Packit Service 88ab54
                    if '"' in line:
Packit Service 88ab54
                        constant_type = 's'
Packit Service 88ab54
                    elif m.group(2).startswith('LASSO_'):
Packit Service 88ab54
                        l = [ c for c in binding.constants if m.group(2) == c[1] ]
Packit Service 88ab54
                        if l:
Packit Service 88ab54
                            contant_type = l[0][0]
Packit Service 88ab54
                        else:
Packit Service 88ab54
                            raise Exception()
Packit Service 88ab54
                    else:
Packit Service 88ab54
                        constant_type = 'i'
Packit Service 88ab54
                    constant = (constant_type, constant_name)
Packit Service 88ab54
                    binding.constants.append(constant)
Packit Service 88ab54
        elif line.startswith('typedef enum {'):
Packit Service 88ab54
            in_enum = True
Packit Service 88ab54
        elif line.startswith('typedef struct'):
Packit Service 88ab54
            m = re.match('typedef struct ([a-zA-Z0-9_]+)', line)
Packit Service 88ab54
            if m:
Packit Service 88ab54
                struct_name = m.group(1)
Packit Service 88ab54
                if not (struct_name.endswith('Class') or struct_name.endswith('Private')):
Packit Service 88ab54
                    struct_names[struct_name] = True
Packit Service 88ab54
        elif line.startswith('struct _'):
Packit Service 88ab54
            m = re.match('struct ([a-zA-Z0-9_]+)', line)
Packit Service 88ab54
            struct_name = m.group(1)
Packit Service 88ab54
            if struct_name in struct_names:
Packit Service 88ab54
                in_struct = Struct(struct_name)
Packit Service 88ab54
                in_struct_private = False
Packit Service 88ab54
        elif in_struct:
Packit Service 88ab54
            if line.startswith('}'):
Packit Service 88ab54
                if not in_struct.name in binding.structs_toskip:
Packit Service 88ab54
                    binding.structs.append(in_struct)
Packit Service 88ab54
                else:
Packit Service 88ab54
                    print_('W: skipping structure %s due to overrides.xml' % in_struct.name, file=sys.stderr)
Packit Service 88ab54
                in_struct = None
Packit Service 88ab54
            elif '/*< public >*/' in line:
Packit Service 88ab54
                in_struct_private = False
Packit Service 88ab54
            elif '/*< private >*/' in line:
Packit Service 88ab54
                in_struct_private = True
Packit Service 88ab54
            elif in_struct_private and exclude_private:
Packit Service 88ab54
                pass
Packit Service 88ab54
            elif 'DEPRECATED' in line and exclude_private:
Packit Service 88ab54
                pass
Packit Service 88ab54
            else:
Packit Service 88ab54
                # TODO: Add parsing of OFTYPE
Packit Service 88ab54
                # Transform struct to typedef
Packit Service 88ab54
                # example: "struct _LassoAssertion" -> "LassoAssertion"
Packit Service 88ab54
                line = re.sub('\s+struct _', ' ', line)
Packit Service 88ab54
                member_match = re.match('\s+(\w+)\s+(\*?\w+)', line)
Packit Service 88ab54
                if member_match:
Packit Service 88ab54
                    member_type, member_name = normalise_var(member_match.group(1), member_match.group(2))
Packit Service 88ab54
                    field = (member_type, member_name, {})
Packit Service 88ab54
                    if member_type == 'void*':
Packit Service 88ab54
                        print_('W: skipping field %s.%s' % (in_struct.name, member_name), file=sys.stderr)
Packit Service 88ab54
                    else:
Packit Service 88ab54
                        if is_glist(field) or is_hashtable(field):
Packit Service 88ab54
                            found = re.search(r' of ([^*]*)', line)
Packit Service 88ab54
                            if found:
Packit Service 88ab54
                                field[2]['element-type'] = clean_type(found.group(1))
Packit Service 88ab54
                        if member_name == 'parent':
Packit Service 88ab54
                            in_struct.parent = member_type
Packit Service 88ab54
                        else:
Packit Service 88ab54
                            in_struct.members.append(field)
Packit Service 88ab54
        elif line.startswith('LASSO_EXPORT '):
Packit Service 88ab54
            while not line.strip().endswith(';'):
Packit Service 88ab54
                i += 1
Packit Service 88ab54
                line = line[:-1] + ' ' + lines[i].lstrip()
Packit Service 88ab54
Packit Service 88ab54
            # parse the type, then the name, then argument list
Packit Service 88ab54
            m = re.match(r'LASSO_EXPORT\s+([^(]*(?:\s|\*))(\w+)\s*\(\s*(.*?)\s*\)\s*;', line)
Packit Service 88ab54
            if m and (not exclude_private or not m.group(2).endswith('_get_type')):
Packit Service 88ab54
                return_type, function_name, args = m.groups()
Packit Service 88ab54
                return_type = return_type.strip()
Packit Service 88ab54
                f = Function()
Packit Service 88ab54
                if function_name[0] == '*':
Packit Service 88ab54
                    return_type += '*'
Packit Service 88ab54
                    function_name = function_name[1:]
Packit Service 88ab54
                if binding.functions_toskip.get(function_name) != 1:
Packit Service 88ab54
                    if re.search(r'\<const\>', return_type):
Packit Service 88ab54
                        f.return_owner = False
Packit Service 88ab54
                    # clean the type
Packit Service 88ab54
                    return_type = clean_type(return_type)
Packit Service 88ab54
                    if return_type != 'void':
Packit Service 88ab54
                        f.return_type = return_type
Packit Service 88ab54
                        f.return_arg = (return_type, None, {})
Packit Service 88ab54
                    if function_name.endswith('_destroy') and exclude_private:
Packit Service 88ab54
                        # skip the _destroy functions, they are just wrapper over
Packit Service 88ab54
                        # g_object_unref
Packit Service 88ab54
                        pass
Packit Service 88ab54
                    else:
Packit Service 88ab54
                        f.name = function_name
Packit Service 88ab54
                        f.args = []
Packit Service 88ab54
                        for arg in [x.strip() for x in args.split(',')]:
Packit Service 88ab54
                            arg = clean_type(arg)
Packit Service 88ab54
                            if arg == 'void' or arg == '':
Packit Service 88ab54
                                continue
Packit Service 88ab54
                            m = re.match(r'(.*(?:\s|\*))(\w+)', arg)
Packit Service 88ab54
                            if m:
Packit Service 88ab54
                                type, name = m.groups()
Packit Service 88ab54
                                type = clean_type(type)
Packit Service 88ab54
                                f.args.append(list((type, name, {})))
Packit Service 88ab54
                            else:
Packit Service 88ab54
                                print_('failed to process:', arg, 'in line:', line, file=sys.stderr)
Packit Service 88ab54
                                f.skip = True
Packit Service 88ab54
                        f.apply_overrides()
Packit Service 88ab54
                        if not f.skip:
Packit Service 88ab54
                            binding.functions.append(f)
Packit Service 88ab54
                        else:
Packit Service 88ab54
                            print_('W: skipping function', f, file=sys.stderr)
Packit Service 88ab54
Packit Service 88ab54
        i += 1
Packit Service 88ab54
Packit Service 88ab54
Packit Service 88ab54
def parse_headers(srcdir):
Packit Service 88ab54
    wsf_prefixes = ['disco_', 'dst_', 'is_', 'profile_service_', 'discovery_',
Packit Service 88ab54
            'wsf_', 'interaction_', 'utility_', 'sa_', 'authentication_',
Packit Service 88ab54
            'wsse_', 'sec_', 'idwsf2_', 'wsf2_', 'wsa_', 'wsu', 'soap_binding']
Packit Service 88ab54
Packit Service 88ab54
    srcdir = os.path.abspath(srcdir)
Packit Service 88ab54
    parentdir = os.path.dirname(srcdir)
Packit Service 88ab54
Packit Service 88ab54
    exclusion = ('xml_idff.h', 'xml_idwsf.h', 'xml_saml2.h', \
Packit Service 88ab54
            'xml_idwsf2.h', 'xml_soap11.h',
Packit Service 88ab54
            'lasso_config.h', 'saml2_xsd.h' )
Packit Service 88ab54
    if not binding.options.idwsf:
Packit Service 88ab54
        exclusion += ( 'idwsf_strings.h', )
Packit Service 88ab54
    for base, dirnames, filenames in os.walk(srcdir):
Packit Service 88ab54
        bname = os.path.basename(base)
Packit Service 88ab54
        if bname == '.svn':
Packit Service 88ab54
            # ignore svn directories
Packit Service 88ab54
            continue
Packit Service 88ab54
        if not 'Makefile.am' in filenames:
Packit Service 88ab54
            # not a source dir
Packit Service 88ab54
            continue
Packit Service 88ab54
        if not binding.options.idwsf and (bname == 'id-wsf' or \
Packit Service 88ab54
                bname == 'id-wsf-2.0' or bname == 'ws'):
Packit Service 88ab54
            # ignore ID-WSF
Packit Service 88ab54
            continue
Packit Service 88ab54
        makefile_am = open(os.path.join(base, 'Makefile.am')).read()
Packit Service 88ab54
        filenames = [x for x in filenames if x.endswith('.h') if x in makefile_am]
Packit Service 88ab54
        for filename in filenames:
Packit Service 88ab54
            if filename in exclusion:
Packit Service 88ab54
                continue
Packit Service 88ab54
            if 'private' in filename:
Packit Service 88ab54
                continue
Packit Service 88ab54
            if not binding.options.idwsf:
Packit Service 88ab54
                if True in (filename.startswith(wsf_prefix) for wsf_prefix in wsf_prefixes):
Packit Service 88ab54
                    continue
Packit Service 88ab54
            header_path = os.path.join(base, filename)
Packit Service 88ab54
            header_relpath = os.path.relpath(header_path, parentdir)
Packit Service 88ab54
Packit Service 88ab54
            binding.headers.append(header_relpath)
Packit Service 88ab54
            parse_header(header_path)
Packit Service 88ab54
    binding.constants.append(('b', 'LASSO_WSF_ENABLED'))
Packit Service 88ab54
Packit Service 88ab54
def main():
Packit Service 88ab54
    global binding
Packit Service 88ab54
Packit Service 88ab54
    parser = OptionParser()
Packit Service 88ab54
    parser.add_option('-l', '--language', dest = 'language')
Packit Service 88ab54
    parser.add_option('-s', '--src-dir', dest = 'srcdir', default = '../lasso/')
Packit Service 88ab54
    parser.add_option('--enable-id-wsf', dest = 'idwsf', action = 'store_true')
Packit Service 88ab54
    parser.add_option('--enable-exception-docs', dest= 'exception_doc', action = 'store_true')
Packit Service 88ab54
Packit Service 88ab54
    options, args = parser.parse_args()
Packit Service 88ab54
    if not options.language:
Packit Service 88ab54
        parser.print_help()
Packit Service 88ab54
        sys.exit(1)
Packit Service 88ab54
Packit Service 88ab54
    binding = BindingData(options)
Packit Service 88ab54
    parse_headers(options.srcdir)
Packit Service 88ab54
    binding.look_for_docstrings(options.srcdir, options.exception_doc)
Packit Service 88ab54
    binding.order_class_hierarchy()
Packit Service 88ab54
    binding.attach_methods()
Packit Service 88ab54
Packit Service 88ab54
    if options.language == 'python':
Packit Service 88ab54
        from python import lang
Packit Service 88ab54
Packit Service 88ab54
        python_binding = lang.Binding(binding)
Packit Service 88ab54
        python_binding.generate()
Packit Service 88ab54
    elif options.language == 'php5':
Packit Service 88ab54
        from php5 import lang
Packit Service 88ab54
Packit Service 88ab54
        php5_binding = lang.Binding(binding)
Packit Service 88ab54
        php5_binding.generate()
Packit Service 88ab54
    elif options.language == 'java':
Packit Service 88ab54
        from java import lang
Packit Service 88ab54
Packit Service 88ab54
        java_binding = lang.Binding(binding)
Packit Service 88ab54
        java_binding.generate()
Packit Service 88ab54
    elif options.language == 'java-list':
Packit Service 88ab54
        from java import lang
Packit Service 88ab54
Packit Service 88ab54
        java_binding = lang.Binding(binding)
Packit Service 88ab54
        java_binding.print_list_of_files()
Packit Service 88ab54
    elif options.language == 'perl':
Packit Service 88ab54
        from perl import lang
Packit Service 88ab54
        perl_binding = lang.Binding(binding)
Packit Service 88ab54
        perl_binding.generate()
Packit Service 88ab54
Packit Service 88ab54
if __name__ == '__main__':
Packit Service 88ab54
    main()