[gobject-introspection/wip/transformer] Add testcodegen



commit 0a583f1c810c17842f4a4fe9ba8d9a415e595409
Author: Colin Walters <walters verbum org>
Date:   Tue Jul 27 15:59:47 2010 -0400

    Add testcodegen

 giscanner/scannermain.py |   12 +++++
 giscanner/testcodegen.py |  111 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/Makefile.am        |   20 ++++++++
 3 files changed, 143 insertions(+), 0 deletions(-)
---
diff --git a/giscanner/scannermain.py b/giscanner/scannermain.py
index fc59c76..1c741ac 100644
--- a/giscanner/scannermain.py
+++ b/giscanner/scannermain.py
@@ -55,6 +55,9 @@ def _get_option_parser():
     parser.add_option("-i", "--include",
                       action="append", dest="includes", default=[],
                       help="include types for other gidls")
+    parser.add_option('', "--test-codegen",
+                      action="store", dest="test_codegen", default=None,
+                      help="Generate test code for given namespace,output.h,output.c")
     parser.add_option('', "--passthrough-gir",
                       action="store", dest="passthrough_gir", default=None,
                       help="Parse and re-output the specified GIR")
@@ -153,6 +156,13 @@ def passthrough_gir(path, f):
                        parser.get_c_includes())
     f.write(writer.get_xml())
 
+def test_codegen(optstring):
+    (namespace, out_h_filename, out_c_filename) = optstring.split(',')
+    from .testcodegen import CCodeGenerator
+    gen = CCodeGenerator(namespace, out_h_filename, out_c_filename)
+    gen.codegen()
+    return 0
+
 def validate(assertions, path):
     from xml.etree.cElementTree import parse
     doc = parse(open(path))
@@ -207,6 +217,8 @@ def scanner_main(args):
 
     if options.passthrough_gir:
         passthrough_gir(options.passthrough_gir, sys.stdout)
+    if options.test_codegen:
+        return test_codegen(options.test_codegen)
 
     if len(args) <= 1:
         _error('Need at least one filename')
diff --git a/giscanner/testcodegen.py b/giscanner/testcodegen.py
new file mode 100644
index 0000000..fd20e65
--- /dev/null
+++ b/giscanner/testcodegen.py
@@ -0,0 +1,111 @@
+# -*- Mode: Python -*-
+# GObject-Introspection - a framework for introspecting GObject libraries
+# Copyright (C) 2010  Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+
+import os, sys
+from contextlib import contextmanager
+from .ast import *
+from .glibast import *
+
+INTROSPECTABLE_BASIC = filter(lambda x: x not in (TYPE_LONG_LONG, TYPE_LONG_DOUBLE), GIR_TYPES)
+
+DEFAULT_C_VALUES = {TYPE_ANY: 'NULL',
+                    TYPE_STRING: '""',
+                    TYPE_FILENAME: '""',
+                    TYPE_GTYPE: 'g_object_get_type ()'}
+
+def get_default_for_typeval(typeval):
+    default = DEFAULT_C_VALUES.get(typeval)
+    if typeval is TYPE_NONE:
+        return ""
+    if default:
+        return default
+    return "0"
+
+def uscore_from_type(typeval):
+    return typeval.ctype.replace('*', 'P').replace(' ', '_')
+
+class CCodeGenerator(object):
+    def __init__(self, namespace, out_h_filename, out_c_filename):
+        self.out_h_filename = out_h_filename
+        self.out_c_filename = out_c_filename
+        self.out_h = open(out_h_filename, 'w')
+        self.out_c = open(out_c_filename, 'w')
+        self.namespace = namespace
+        self._lnamespace = self.namespace.lower()
+
+    def _gen_symbol(self, name):
+        return '%s_%s' % (self._lnamespace, name)
+
+    def _typecontainer_to_ctype(self, param):
+        if (param.type.is_equiv((TYPE_STRING, TYPE_FILENAME)) and
+            param.transfer == PARAM_TRANSFER_NONE):
+            return "const gchar*" 
+        return param.type.ctype
+
+    def _write_prelude(self, out, func):
+        out.write("""
+%s
+%s (""" % (self._typecontainer_to_ctype(func.retval), func.symbol))
+        l = len(func.parameters)
+        for i,param in enumerate(func.parameters):
+            ctype = self._typecontainer_to_ctype(param)
+            self.out_h.write('%s %s' % (ctype, param.argname))
+            if i < l - 1:
+                out_h.write(", ")
+        out.write(")")
+
+    def _write_prototype(self, func):
+        self._write_prelude(self.out_h, func)
+        self.out_h.write(";\n\n")
+
+    @contextmanager
+    def _function(self, func):
+        self._write_prototype(func)
+        self._write_prelude(self.out_c, func)
+        self.out_c.write("\n{\n")
+        yield
+        self.out_c.write("}\n\n")
+
+    def codegen(self):
+        warning = '/* GENERATED BY testcodegen.py; DO NOT EDIT */\n\n'
+        self.out_h.write(warning)
+        nsupper = self.namespace.upper()
+        self.out_h.write("""
+#ifndef __%s_H__
+#define __%s_H__
+""" % (nsupper, nsupper))
+
+        self.out_c.write(warning)
+        self.out_c.write("""#include "%s"\n\n""" % (self.out_h_filename, ))
+
+        # First pass, generate constant returns
+        for typeval in INTROSPECTABLE_BASIC:
+            name = uscore_from_type(typeval)
+            sym = self._gen_symbol(typeval.target_fundamental)
+            func = Function(name, Return(typeval, transfer=PARAM_TRANSFER_NONE),
+                            [], False, sym)
+            with self._function(func):
+                default = get_default_for_typeval(typeval)
+                self.out_c.write("  return %s;\n" % (default, ))
+
+        self.out_h.write("""#endif\n""")
+        
+        self.out_h.close()
+        self.out_c.close()
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 0c51358..b94f5b7 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1 +1,21 @@
 SUBDIRS = . scanner repository offsets
+
+BUILT_SOURCES=
+
+noinst_libeverything_1_0_la_SOURCES = everything.c everything.h
+
+BUILT_SOURCES += everything.c everything.h
+
+everything-sources.stamp:
+	$(top_builddir)/tools/g-ir-scanner --test-codegen=Everything,everything.h,everything.c
+	touch $@
+
+everything.c: everything-sources.stamp
+
+everything.h: everything-sources.stamp
+
+Everything-1.0.gir: libeverything-1.0.la
+	$(AM_V_GEN) $(top_builddir)/tools/g-ir-scanner --namespace=Everything --version=1.0 --library=libeverything-1.0.la everything.h everything.c --output=$@
+
+Everything-1.0.typelib: Everything-1.0.gir
+	$(AM_V_GEN) $(top_builddir)/tools/g-ir-compiler $< -o $@



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