diff options
Diffstat (limited to 'codegen/defsgen.py')
-rw-r--r-- | codegen/defsgen.py | 102 |
1 files changed, 84 insertions, 18 deletions
diff --git a/codegen/defsgen.py b/codegen/defsgen.py index 902a5ba..670d411 100644 --- a/codegen/defsgen.py +++ b/codegen/defsgen.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- Mode: Python; py-indent-offset: 4 -*- # -# Copyright (C) 2006 John Finlay. +# Copyright (C) 2006-2008 John Finlay. # # Scan the given public .h files of a GTK module (or module using # GTK object conventions) and generates a set of scheme defs. @@ -44,6 +44,9 @@ # useful with the --defsfile option # -m --modulename The prefix to be stripped from the front of function names # for the given module +# -p --useprefix Use the modulename prefix as a hint to split names into +# module and name for object and enum defs. Also used for +# generating type codes. # --onlyenums Only produce defs for enums and flags # --onlyobjdefs Only produce defs for objects # --onlyvirtuals Only produce defs for virtuals @@ -80,7 +83,7 @@ import getopt import os -import re +import re, string import sys import ctypes import defsparser @@ -100,10 +103,11 @@ def to_upper_str(name): name = _upperstr_pat3.sub(r'\1_\2', name, count=1) return name.upper() -def typecode(typename, prefix=''): +def typecode(typename, prefix, use_prefix): """create a typecode (eg. GTK_TYPE_WIDGET) from a typename""" tcode = to_upper_str(typename) - if prefix and tcode.lower() != prefix and tcode.lower().startswith(prefix): + if (use_prefix and prefix and tcode.lower() != prefix + and tcode.lower().startswith(prefix)): l = len(prefix) tcode = tcode[:l] + '_TYPE' + tcode[l:] else: @@ -133,8 +137,6 @@ clean_patterns = [ (re.compile(r'^\s*(extern)\s+"C"\s+{', re.MULTILINE), ''), # remove singleline typedefs of stucts (re.compile(r'^typedef\s+struct\s*[^{;\n]*;\s*$', re.MULTILINE), ''), - # remove enum definitions - (re.compile(r'^typedef enum\s+{[^}]*}[^;]*;\s*$', re.MULTILINE), ''), # remove all struct definitons but those for object classes and interfaces (re.compile(r'^struct\s+(\w+)\s+{[^}]+}\s*;\s*$', re.MULTILINE), class_iface_sub), @@ -147,10 +149,13 @@ clean_patterns = [ (re.compile(r' \s* ([*|&]+) \s* ([(\w]+)', re.VERBOSE), r'\1 \2'), (re.compile(r'\s+ (\w+) \[ \s* \]', re.VERBOSE), r'[] \1'), # make return types that are const work. + (re.compile(r'\s*\*\s*G_CONST_RETURN\s*\*\s*'), '** '), (re.compile(r'G_CONST_RETURN |const '), 'const-'), # remove typedefs of callback types (re.compile(r'^typedef\s+\w+\s*\*?\s*\(\s*\*\s*\w+\)\s*\([^(]*\)\n', - re.MULTILINE), '') + re.MULTILINE), ''), + #strip GSEAL macros from the middle of function declarations: + (re.compile(r"""GSEAL""", re.VERBOSE), '') ] def clean_buffer(buf): @@ -283,6 +288,20 @@ def find_virt_defs(buf, deffile, defs): virts.append((func, ret, args, objname)) return +enum_pat = re.compile(r'^\s*typedef enum\s+{\s*([^}]*)}\s*([^\s]*)$', + re.MULTILINE) +values_splitter = re.compile(r'\s*,\s', re.MULTILINE) + +def find_enums(buf, defs): + for vals, name in enum_pat.findall(buf): + if name != 'GdkCursorType': + isflags = '<<' in vals + entries = [val.split()[0] for val in values_splitter.split(vals) + if val.strip()] + if entries: + defs['untypedenums'][name] = (isflags, entries) + return + # ------------------ write definitions ----------------- type_pat = re.compile(r'(?:const-)?([A-Za-z0-9]+)\*?\s+') @@ -290,10 +309,10 @@ pointer_pat = re.compile('(.*)\*$') func_new_pat = re.compile('(\w+)_new$') getset_pat = re.compile(r'^(?:get|set)_(.*)$') -def split_prefix(cname, prefix): +def split_prefix(cname, prefix, use_prefix): # use the module prefix to split the cname pre = prefix.replace('_', '') - if cname.lower().startswith(pre): + if use_prefix and cname.lower().startswith(pre): l = len(pre) module = cname[:l] name = cname[l:] @@ -306,8 +325,10 @@ def split_prefix(cname, prefix): class DefsWriter: def __init__(self, defs, fp=None, prefix=None, verbose=False, - defsfiles=None, defines={}, genpropgetsets=False): + defsfiles=None, defines={}, genpropgetsets=False, + useprefix=False): self.defs = defs + self.use_prefix = useprefix self.objnames = reduce(list.__add__, [[o.name for o in defs[base]] for base in defkeys.split()[:3]]) @@ -354,18 +375,24 @@ class DefsWriter: fp.write(';; Enumerations and Flags ...\n\n') for obj in objs: cname = name = obj.name + tcode = typecode(cname, self.prefix, self.use_prefix) if cname in filter: continue + if cname in self.defs['untypedenums']: + if tcode not in self.defs['typedefines']: + # no type define so skip and print as untyped enum + continue + self.defs['untypedenums'].pop(cname, None) parent_name = obj.parent_name klassptr = klassptrs[parent_name] typename = parent_name.lower()[1:] module = None - module, name = split_prefix(cname, self.prefix) + module, name = split_prefix(cname, self.prefix, self.use_prefix) fp.write('(define-' + typename + ' ' + name + '\n') if module: fp.write(' (in-module "' + module + '")\n') fp.write(' (c-name "' + cname + '")\n') - fp.write(' (gtype-id "' + typecode(cname, self.prefix) + '")\n') + fp.write(' (gtype-id "' + tcode + '")\n') fp.write(' (values\n') classref = self.gobj.g_type_class_ref(obj.type) itemclass = ctypes.cast(classref, klassptr).contents @@ -375,22 +402,51 @@ class DefsWriter: val.value_name)) fp.write(' )\n') fp.write(')\n\n') + if self.defs['untypedenums']: + self.write_untyped_enum_defs(fp) return + def write_untyped_enum_defs(self, fp): + fp.write(';; Untyped enumerations and flags ...\n\n') + filter = self._c_names + for cname, (isflags, entries) in self.defs['untypedenums'].items(): + if filter and cname in filter: continue + module, name = split_prefix(cname, self.prefix, self.use_prefix) + if isflags: + fp.write('(define-flags ' + name + '\n') + else: + fp.write('(define-enum ' + name + '\n') + if module: + fp.write(' (in-module "' + module + '")\n') + fp.write(' (c-name "' + cname + '")\n') + preindex = entries[0].rfind('_') + for ent in entries[1:]: + while (preindex > 0 + and ent[:preindex] != entries[0][:preindex]): + preindex = ent[:preindex].rfind('_') + fp.write(' (values\n') + for ent in entries: + fp.write(' \'("%s" "%s")\n' % + (ent[preindex+1:].lower().replace('_', '-'), ent)) + fp.write(' )\n') + fp.write(')\n\n') + + def _write_obj_helper(self, obj, fp): base_name = obj.base_name.lower()[1:] cmodule = None cname = name = obj.name type_id = obj.type parent_name = obj.parent_name - cmodule, name = split_prefix(cname, self.prefix) + cmodule, name = split_prefix(cname, self.prefix, self.use_prefix) fp.write('(define-' + base_name + ' ' + name + '\n') if cmodule: fp.write(' (in-module "' + cmodule + '")\n') if base_name == 'object': fp.write(' (parent "' + parent_name + '")\n') fp.write(' (c-name "' + cname + '")\n') - fp.write(' (gtype-id "' + typecode(cname, self.prefix) + '")\n') + fp.write(' (gtype-id "' + + typecode(cname, self.prefix, self.use_prefix) + '")\n') n = ctypes.c_uint() ifaces = self.gobj.g_type_interfaces(type_id, ctypes.byref(n)) for i in range(n.value): @@ -466,7 +522,7 @@ class DefsWriter: m = getset_pat.match(mname) if self.genpropgetsets and m and len(args[1:]) <= 1: prop = m.group(1) - if self.objifacedefs.has_key(obj): + if obj in self.objifacedefs: oidef = self.objifacedefs[obj] if prop.replace('_', '-') in oidef.props: self.fp.write(' (prop-getset "' + prop + '")\n') @@ -560,11 +616,12 @@ def main(args): modulelibs = [] defines = {} genpropgetsets = False - opts, args = getopt.getopt(args[1:], 'vs:m:f:D:L:l:', + use_prefix = False + opts, args = getopt.getopt(args[1:], 'vs:m:f:D:L:l:p', ['onlyenums', 'onlyobjdefs', 'onlyvirtuals', 'modulename=', 'separate=', 'defsfile=', 'defines=', 'genpropgetsets', - 'libgobject-', 'modulelib=']) + 'libgobject-', 'modulelib=', 'useprefix']) for o, v in opts: if o == '-v': verbose = True @@ -577,6 +634,8 @@ def main(args): if o == '--onlyobjdefs': onlyobjdefs = True all = False + if o in ('-p', '--useprefix'): + use_prefix = True if o == '--genpropgetsets': genpropgetsets = True if o in ('-s', '--separate'): @@ -629,12 +688,19 @@ def main(args): defs[key] = [] defs['funcs'] = {} defs['virts'] = {} + defs['untypedenums'] = {} + defs['typedefines'] = [] # read in all the object and function definitions args.sort() + type_define_pat = re.compile( + r'^#define\s+([A-Z]\S+_TYPE_\S+)\s+.*[a-z]\w+_get_type.*$', + re.MULTILINE) for filename in args: buf = open(filename).read() + defs['typedefines'] += type_define_pat.findall(buf) buf = clean_buffer(buf) + find_enums(buf, defs) find_defs(buf, gobj, modlib, defs) find_func_defs(buf, modlib, filename, defs, verbose) find_virt_defs(buf, filename, defs) @@ -649,7 +715,7 @@ def main(args): dw = DefsWriter(defs, methods, prefix=modulename, verbose=verbose, defsfiles=defsfiles, defines=defines, - genpropgetsets=genpropgetsets) + genpropgetsets=genpropgetsets, useprefix=use_prefix) dw.interfaces = [i.name for i in defs['GInterface']] dw.gobj = gobj dw.modlib = modlib |