yet another defs extractor script
- From: James Henstridge <james daa com au>
- To: language-bindings gnome org
- Subject: yet another defs extractor script
- Date: Tue, 12 Feb 2002 10:06:30 +0800
Attached is a small script that can be used to use the introspection
features of libgobject to extract some defs from a library. It takes a
file with a list of types and includes (similar to the input file for
gtkdoc-scanobj), and outputs various definitions:
object defs (with correct implements lines)
interface defs
boxed defs
enum and flag defs
signal defs
property defs
It uses pkg-config to work out how to link with the library. An example
of its use:
$ cat > gtk-types << EOF
#include <gtk/gtk.h>
GDK_TYPE_CURSOR_TYPE
GDK_TYPE_EVENT_MASK
GTK_TYPE_WINDOW_TYPE
GTK_TYPE_OBJECT
GTK_TYPE_WIDGET
GTK_TYPE_TREE_MODEL
GTK_TYPE_TREE_STORE
GTK_TYPE_TREE_ITER
EOF
$ python extract.py -m gtk+-2.0 -t gtk-types
--type-init-func='gtk_type_init(0);'
This will print out the definitions related to the given types. The
program creates a simple C program, which is compiled and run. The
output of this program is the definitions related to those types.
It could probably be modified to scan a set of headers for types to examine.
James.
--
Email: james daa com au
WWW: http://www.daa.com.au/~james/
import sys, os, string, getopt
# handlers for writing out information gained through introspection
usage = 'usage: extract -m pkgconfigmodule -t typesfile [ --type-init-func func ]\n'
help = usage + \
'''Extract defs info from a library via introspection
-m, --module=MODULE a pkg-config module name (for compiler flags)
-t, --types=TYPESFILE a file containing the list of types to check
--type-init-func=FUNC a function called to initialise types
The types file can contain #include directives needed to access the
types. Other lines are treated as type ids (eg. GTK_TYPE_WIDGET) to
parse.
The output will be a list of definitions for various things that can
be accessed at runtime.
'''
handlers = r'''
typedef void (* InfoWriterFunc)(GType type, const gchar *gtypeid);
static const gchar *
get_name(GType type)
{
const gchar *type_name;
type_name = g_type_name(type);
while (*(++type_name) != '\0') {
if (g_ascii_isupper(type_name[0]))
return type_name;
}
return g_type_name(type);
}
static void
print_module(GType type)
{
gchar *type_name, *p;
type_name = g_strdup(g_type_name(type));
p = type_name;
while (*(++p) != '\0') {
if (g_ascii_isupper(*p)) {
*p = '\0';
break;
}
}
printf(" (in-module \"%s\")\n", type_name);
g_free(type_name);
}
static void
write_signal_info(GType type, const gchar *gtypeid)
{
GTypeClass *tclass = NULL;
guint *signal_ids, n_signals = 0, i;
if (!G_TYPE_IS_INSTANTIATABLE(type) && !G_TYPE_IS_INTERFACE(type))
return;
if (G_TYPE_IS_CLASSED(type))
tclass = g_type_class_ref(type);
signal_ids = g_signal_list_ids(type, &n_signals);
for (i = 0; i < n_signals; i++) {
GSignalQuery query;
g_signal_query(signal_ids[i], &query);
printf("(define-signal \"%s\"\n", query.signal_name);
printf(" (of-object \"%s\")\n", g_type_name(type));
printf(" (return-type \"%s\")\n", g_type_name(query.return_type));
if ((query.signal_flags & G_SIGNAL_RUN_FIRST) &&
(query.signal_flags & G_SIGNAL_RUN_LAST)) {
printf(" (when \"both\")\n");
} else if (query.signal_flags & G_SIGNAL_RUN_FIRST) {
printf(" (when \"first\")\n");
} else if (query.signal_flags & G_SIGNAL_RUN_LAST) {
printf(" (when \"last\")\n");
}
if (query.n_params > 0) {
guint j;
printf(" (parameters\n");
for (j = 0; j < query.n_params; j++) {
printf(" '(\"%s\" \"arg%d\"", g_type_name(query.param_types[j] & ~G_SIGNAL_TYPE_STATIC_SCOPE), j);
if (query.param_types[j] & G_SIGNAL_TYPE_STATIC_SCOPE)
printf(" \"static-scope\"");
printf(")\n");
}
printf(" )\n");
}
printf(")\n\n");
}
g_free(signal_ids);
if (tclass)
g_type_class_unref(tclass);
}
static void
write_property_info(GType type, const gchar *gtypeid)
{
GObjectClass *oclass = NULL;
GParamSpec **properties;
guint n_properties = 0, i;
if (!G_TYPE_IS_OBJECT(type))
return;
oclass = g_type_class_ref(type);
properties = g_object_class_list_properties(oclass, &n_properties);
for (i = 0; i < n_properties; i++) {
printf("(define-property \"%s\"\n",
g_param_spec_get_name(properties[i]));
printf(" (of-object \"%s\")\n", g_type_name(type));
printf(" (prop-type \"%s\")\n",
g_type_name(properties[i]->value_type));
printf(" (readable %s)\n",
(properties[i]->flags & G_PARAM_READABLE) ? "#t" : "#f");
printf(" (writable %s)\n",
(properties[i]->flags & G_PARAM_WRITABLE) ? "#t" : "#f");
printf(" (construct-only %s)\n",
(properties[i]->flags & G_PARAM_CONSTRUCT_ONLY) ? "#t" : "#f");
printf(")\n\n");
}
g_free(properties);
g_type_class_unref(oclass);
}
static void
write_enum_info(GType type, const gchar *gtypeid)
{
GEnumClass *eclass;
guint i;
if (!G_TYPE_IS_ENUM(type))
return;
eclass = g_type_class_ref(type);
printf("(define-enum \"%s\"\n", get_name(type));
print_module(type);
printf(" (c-name \"%s\")\n", g_type_name(type));
printf(" (gtype-id \"%s\")\n", gtypeid);
printf(" (values\n");
for (i = 0; i < eclass->n_values; i++) {
printf(" '(\"%s\" \"%s\" %d)\n", eclass->values[i].value_nick,
eclass->values[i].value_name, eclass->values[i].value);
}
printf(" )\n");
printf(")\n\n");
g_type_class_unref(eclass);
}
static void
write_flags_info(GType type, const gchar *gtypeid)
{
GFlagsClass *fclass;
guint i;
if (!G_TYPE_IS_FLAGS(type))
return;
fclass = g_type_class_ref(type);
printf("(define-flags \"%s\"\n", get_name(type));
print_module(type);
printf(" (c-name \"%s\")\n", g_type_name(type));
printf(" (gtype-id \"%s\")\n", gtypeid);
printf(" (values\n");
for (i = 0; i < fclass->n_values; i++) {
printf(" '(\"%s\" \"%s\" %u)\n", fclass->values[i].value_nick,
fclass->values[i].value_name, fclass->values[i].value);
}
printf(" )\n");
printf(")\n\n");
g_type_class_unref(fclass);
}
static void
write_interface_info(GType type, const gchar *gtypeid)
{
if (!G_TYPE_IS_INTERFACE(type))
return;
printf("(define-interface \"%s\"\n", get_name(type));
print_module(type);
printf(" (c-name \"%s\")\n", g_type_name(type));
printf(" (gtype-id \"%s\")\n", gtypeid);
printf(")\n\n");
}
static void
write_object_info(GType type, const gchar *gtypeid)
{
GType *interfaces;
guint n_interfaces = 0, i;
if (!G_TYPE_IS_OBJECT(type))
return;
printf("(define-object \"%s\"\n", get_name(type));
print_module(type);
if (g_type_parent(type) != G_TYPE_INVALID)
printf(" (parent \"%s\")\n", g_type_name(g_type_parent(type)));
printf(" (c-name \"%s\")\n", g_type_name(type));
printf(" (gtype-id \"%s\")\n", gtypeid);
interfaces = g_type_interfaces(type, &n_interfaces);
for (i = 0; i < n_interfaces; i++)
printf(" (implements \"%s\")\n", g_type_name(interfaces[i]));
g_free(interfaces);
printf(")\n\n");
}
static void
write_boxed_info(GType type, const gchar *gtypeid)
{
if (!G_TYPE_IS_BOXED(type))
return;
printf("(define-boxed \"%s\"\n", get_name(type));
print_module(type);
printf(" (c-name \"%s\")\n", g_type_name(type));
printf(" (gtype-id \"%s\")\n", gtypeid);
printf(")\n\n");
}
'''
main_func = r'''
int
main(int argc, char **argv)
{
g_type_init();
%(typeinit)s
printf(";; -*- mode: scheme -*-\n\n");
printf(";; --------- type defs ---------\n");
foreach_type(write_interface_info);
foreach_type(write_object_info);
foreach_type(write_boxed_info);
printf("\n");
printf(";; --------- enum and flags defs ---------\n");
foreach_type(write_enum_info);
foreach_type(write_flags_info);
printf("\n");
printf(";; --------- property defs ---------\n");
foreach_type(write_property_info);
printf("\n");
printf(";; --------- signal defs ---------\n");
foreach_type(write_signal_info);
printf("\n");
return 0;
}
'''
def read_types_file(fp):
'''returns (types, includes)'''
types = []
includes = []
for line in fp.readlines():
line = string.strip(line)
if not line: continue
if line[0] == '#':
includes.append(line)
else:
types.append(line)
return (types, includes)
def write_check_prog(fp, types, includes, type_init=''):
fp.write("/* -*- mode: C; c-basic-offset: 4 -*- */\n")
fp.write("#include <glib-object.h>\n")
for line in includes:
fp.write(line + '\n')
# write out the handlers
fp.write(handlers)
# write out the function to iterate over types
fp.write("static void\nforeach_type(InfoWriterFunc func)\n{\n")
for type in types:
fp.write(" func(%s, \"%s\");\n" % (type, type))
fp.write("}\n\n")
fp.write(main_func % { 'typeinit': type_init })
def main():
module = None
typesfile = None
type_init = ''
try:
opts, args = getopt.getopt(sys.argv[1:], 'm:t:',
['module=', 'types=', 'type-init-func=', 'help'])
except getopt.error, msg:
sys.stderr.write('extract: %s\n' % msg)
sys.stderr.write(usage)
sys.exit(1)
for opt, arg in opts:
if opt in ('-m', '--module'):
module = arg
elif opt in ('-t', '--types'):
typesfile = arg
elif opt in ('--type-init-func',):
type_init = arg
elif opt in ('--help',):
sys.stdout.write(help)
sys.exit(0)
if len(args) > 0:
sys.stderr.write('extract: no extra args expected\n')
sys.stderr.write(usage)
sys.exit(1)
if not module or not typesfile:
sys.stderr.write('extrace: required argument missing\n')
sys.stderr.write(usage)
sys.exit(1)
# read the type names to work with
types, includes = read_types_file(open(typesfile, 'r'))
# use pkg-config to work out what flags to use
cflags = string.strip(os.popen('pkg-config --cflags ' + module).read())
libs = string.strip(os.popen('pkg-config --libs ' + module).read())
# write the test program
write_check_prog(open('__extract.c', 'w'),
types, includes, type_init)
# compile the program
os.system('cc %s -o __extract __extract.c %s' % (cflags, libs))
# run the program
os.system('./__extract')
os.unlink('__extract')
os.unlink('__extract.c')
if __name__ == '__main__':
main()
[Date Prev][
Date Next] [Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]