2 # GObject-Introspection - a framework for introspecting GObject libraries
3 # Copyright (C) 2010 Red Hat, Inc.
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2 of the License, or (at your option) any later version.
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # Lesser General Public License for more details.
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the
17 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 # Boston, MA 02111-1307, USA.
21 from __future__ import with_statement
23 from contextlib import contextmanager
28 class CCodeGenerator(object):
29 def __init__(self, namespace, out_h_filename, out_c_filename):
30 self.out_h_filename = out_h_filename
31 self.out_c_filename = out_c_filename
32 self._function_bodies = {}
33 self.namespace = namespace
35 def gen_symbol(self, name):
36 name = name.replace(' ', '_')
37 return '%s_%s' % (self.namespace.symbol_prefixes[0], name)
39 def _typecontainer_to_ctype(self, param):
40 if (isinstance(param, ast.Parameter)
41 and param.direction in (ast.PARAM_DIRECTION_OUT, ast.PARAM_DIRECTION_INOUT)):
46 if (param.type.is_equiv((ast.TYPE_STRING, ast.TYPE_FILENAME))
47 and param.transfer == ast.PARAM_TRANSFER_NONE):
48 return "const gchar*" + suffix
50 return param.type.ctype + suffix
52 def _write_prelude(self, out, func):
55 %s (""" % (self._typecontainer_to_ctype(func.retval), func.symbol))
56 l = len(func.parameters)
58 for i, param in enumerate(func.parameters):
59 ctype = self._typecontainer_to_ctype(param)
60 out.write('%s %s' % (ctype, param.argname))
67 def _write_prototype(self, func):
68 self._write_prelude(self.out_h, func)
69 self.out_h.write(";\n\n")
71 def _write_annotation_transfer(self, transfer):
72 self.out_c.write("(transfer %s)" % (transfer, ))
74 def _write_docs(self, func):
75 self.out_c.write("/**\n * %s:\n" % (func.symbol, ))
76 for param in func.parameters:
77 self.out_c.write(" * @%s: " % (param.argname, ))
78 if param.direction in (ast.PARAM_DIRECTION_OUT,
79 ast.PARAM_DIRECTION_INOUT):
80 if param.caller_allocates:
81 allocate_string = ' caller-allocates'
84 self.out_c.write("(%s%s) " % (param.direction,
86 self._write_annotation_transfer(param.transfer)
87 self.out_c.write(":\n")
88 self.out_c.write(' *\n')
89 self.out_c.write(' * Undocumented.\n')
90 self.out_c.write(' *\n')
91 self.out_c.write(' * Returns: ')
92 self._write_annotation_transfer(func.retval.transfer)
93 self.out_c.write('\n */')
96 def _function(self, func):
97 self._write_prototype(func)
98 self._write_docs(func)
99 self._write_prelude(self.out_c, func)
100 self.out_c.write("\n{\n")
102 self.out_c.write("}\n\n")
104 def _codegen_start(self):
105 warning = '/* GENERATED BY testcodegen.py; DO NOT EDIT */\n\n'
106 self.out_h.write(warning)
107 nsupper = self.namespace.name.upper()
112 #include <glib-object.h>
113 """ % (nsupper, nsupper))
115 self.out_c.write(warning)
116 self.out_c.write("""#include "%s"\n\n""" % (self.out_h_filename, ))
118 def _codegen_end(self):
119 self.out_h.write("""#endif\n""")
124 def set_function_body(self, node, body):
125 assert isinstance(node, ast.Function)
126 self._function_bodies[node] = body
129 self.out_h = open(self.out_h_filename, 'w')
130 self.out_c = open(self.out_c_filename, 'w')
132 self._codegen_start()
134 for node in self.namespace.itervalues():
135 if isinstance(node, ast.Function):
136 with self._function(node):
137 body = self._function_bodies.get(node)
140 self.out_c.write(body)