pygobject r975 - trunk/codegen



Author: finlay
Date: Mon Nov  3 10:43:50 2008
New Revision: 975
URL: http://svn.gnome.org/viewvc/pygobject?rev=975&view=rev

Log:
	* codegen/defsgen.py (DefsWriter.write_enum_defs): Add option (-p)
	to use the modulename as a hint to the prefix of functions and
	type codes. Provide way to identify untyped enums and flags and
	print defs for them as well.



Modified:
   trunk/codegen/defsgen.py

Modified: trunk/codegen/defsgen.py
==============================================================================
--- trunk/codegen/defsgen.py	(original)
+++ trunk/codegen/defsgen.py	Mon Nov  3 10:43:50 2008
@@ -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 @@
     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 @@
     (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 @@
     (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 @@
             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 @@
 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 @@
 
 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 @@
         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 @@
                                                   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 @@
         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 @@
     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 @@
         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 @@
         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 @@
 
     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



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]