summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog17
-rw-r--r--giscanner/gidlwriter.py14
-rw-r--r--giscanner/girwriter.py9
-rw-r--r--giscanner/giscannermodule.c136
-rw-r--r--giscanner/sourcescanner.c7
-rw-r--r--giscanner/sourcescanner.h2
-rw-r--r--giscanner/sourcescanner.py47
-rw-r--r--giscanner/treebuilder.py74
-rwxr-xr-xtools/g-ir-scanner3
9 files changed, 270 insertions, 39 deletions
diff --git a/ChangeLog b/ChangeLog
index 1eb6710b..c35e7935 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2008-04-24 Johan Dahlin <jdahlin@async.com.br>
+
+ * giscanner/gidlwriter.py:
+ * giscanner/girwriter.py:
+ * giscanner/giscannermodule.c (directive_get_name),
+ (directive_get_value), (directive_get_options),
+ (symbol_get_directives), (symbol_set_directives),
+ (pygi_source_scanner_parse_file),
+ (pygi_source_scanner_lex_filename),
+ (pygi_source_scanner_get_directives), (init_giscanner):
+ * giscanner/sourcescanner.c (gi_source_scanner_get_directives):
+ * giscanner/sourcescanner.h:
+ * giscanner/sourcescanner.py:
+ * giscanner/treebuilder.py:
+ * tools/g-ir-scanner:
+ Add support for source/header annotations.
+
2008-04-22 Johan Dahlin <jdahlin@async.com.br>
* giscanner/gidlwriter.py:
diff --git a/giscanner/gidlwriter.py b/giscanner/gidlwriter.py
index 35fc521e..8d23e01f 100644
--- a/giscanner/gidlwriter.py
+++ b/giscanner/gidlwriter.py
@@ -50,7 +50,10 @@ class GIDLWriter(XMLWriter):
def _write_return_type(self, return_):
if not return_:
return
- self.write_tag('return-type', [('type', return_.type)])
+ attrs = [('type', return_.type)]
+ if return_.transfer != 'none':
+ attrs.append(('transfer', return_.transfer))
+ self.write_tag('return-type', attrs)
def _write_parameters(self, parameters):
if not parameters:
@@ -60,8 +63,13 @@ class GIDLWriter(XMLWriter):
self._write_parameter(parameter)
def _write_parameter(self, parameter):
- self.write_tag('parameter', [('name', parameter.name),
- ('type', parameter.type)])
+ attrs = [('name', parameter.name),
+ ('type', parameter.type)]
+ if parameter.direction != 'in':
+ attrs.append(('direction', parameter.direction))
+ if parameter.transfer != 'none':
+ attrs.append(('transfer', parameter.transfer))
+ self.write_tag('parameter', attrs)
def _write_enum(self, enum):
attrs = [('name', enum.name)]
diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py
index 009ba573..3a38ef8e 100644
--- a/giscanner/girwriter.py
+++ b/giscanner/girwriter.py
@@ -58,7 +58,10 @@ class GIRWriter(XMLWriter):
return
with self.tagcontext('return-values'):
with self.tagcontext('return-value'):
- self.write_tag('type', [('name', return_.type)])
+ attrs = [('name', return_.type)]
+ if return_.transfer != 'none':
+ attrs.append(('transfer', return_.transfer))
+ self.write_tag('type', attrs)
def _write_parameters(self, parameters):
if not parameters:
@@ -69,6 +72,10 @@ class GIRWriter(XMLWriter):
def _write_parameter(self, parameter):
attrs = [('name', parameter.name)]
+ if parameter.direction != 'in':
+ attrs.append(('direction', parameter.direction))
+ if parameter.transfer != 'none':
+ attrs.append(('transfer', parameter.transfer))
with self.tagcontext('parameters', attrs):
self.write_tag('type', [('name', parameter.type)])
diff --git a/giscanner/giscannermodule.c b/giscanner/giscannermodule.c
index a0ccf619..9ba2296b 100644
--- a/giscanner/giscannermodule.c
+++ b/giscanner/giscannermodule.c
@@ -54,12 +54,18 @@ PyTypeObject Py##cname##_Type = { \
typedef struct {
PyObject_HEAD
+ GISourceDirective *directive;
+} PyGISourceDirective;
+
+typedef struct {
+ PyObject_HEAD
GISourceType *type;
} PyGISourceType;
typedef struct {
PyObject_HEAD
GISourceSymbol *symbol;
+ PyObject *directives;
} PyGISourceSymbol;
typedef struct {
@@ -67,11 +73,59 @@ typedef struct {
GISourceScanner *scanner;
} PyGISourceScanner;
+NEW_CLASS (PyGISourceDirective, "SourceDirective", GISourceDirective);
NEW_CLASS (PyGISourceSymbol, "SourceSymbol", GISourceSymbol);
NEW_CLASS (PyGISourceType, "SourceType", GISourceType);
NEW_CLASS (PyGISourceScanner, "SourceScanner", GISourceScanner);
+/* Directive */
+
+static PyObject *
+directive_get_name (PyGISourceDirective *self,
+ void *context)
+{
+ return PyString_FromString (self->directive->name);
+}
+
+static PyObject *
+directive_get_value (PyGISourceDirective *self,
+ void *context)
+{
+ return PyString_FromString (self->directive->value);
+}
+
+static PyObject *
+directive_get_options (PyGISourceDirective *self,
+ void *context)
+{
+ GSList *l, *symbols;
+ PyObject *list;
+ int i = 0;
+
+ if (!self->directive)
+ return Py_BuildValue("[]");
+
+ list = PyList_New (g_slist_length (self->directive->options));
+
+ for (l = self->directive->options; l; l = l->next)
+ {
+ PyObject *item = PyString_FromString(l->data);
+ PyList_SetItem (list, i++, (PyObject*)item);
+ Py_INCREF (item);
+ }
+
+ Py_INCREF (list);
+ return list;
+}
+
+static const PyGetSetDef _PyGISourceDirective_getsets[] = {
+ { "name", (getter)directive_get_name, NULL, NULL},
+ { "value", (getter)directive_get_value, NULL, NULL},
+ { "options", (getter)directive_get_options, NULL, NULL},
+ { 0 }
+};
+
/* Symbol */
static PyObject *
@@ -119,6 +173,26 @@ symbol_get_const_string (PyGISourceSymbol *self,
return PyString_FromString (self->symbol->const_string);
}
+static PyObject *
+symbol_get_directives (PyGISourceSymbol *self,
+ void *context)
+{
+ if (!self->directives)
+ self->directives = Py_BuildValue("[]");
+ Py_INCREF (self->directives);
+ return self->directives;
+}
+
+static int
+symbol_set_directives (PyGISourceSymbol *self,
+ PyObject *value,
+ void *context)
+{
+ self->directives = value;
+ Py_INCREF(value);
+ return 0;
+}
+
static const PyGetSetDef _PyGISourceSymbol_getsets[] = {
/* int ref_count; */
{ "type", (getter)symbol_get_type, NULL, NULL},
@@ -128,7 +202,7 @@ static const PyGetSetDef _PyGISourceSymbol_getsets[] = {
/* gboolean const_int_set; */
{ "const_int", (getter)symbol_get_const_int, NULL, NULL},
{ "const_string", (getter)symbol_get_const_string, NULL, NULL},
- /* GSList *directives; */
+ { "directives", (getter)symbol_get_directives, symbol_set_directives, NULL},
{ 0 }
};
@@ -251,7 +325,7 @@ pygi_source_scanner_parse_file (PyGISourceScanner *self,
char *filename;
FILE *fp;
- if (!PyArg_ParseTuple (args, "is:SourceScanner.__init__", &fd, &filename))
+ if (!PyArg_ParseTuple (args, "is:SourceScanner.parse_file", &fd, &filename))
return NULL;
fp = fdopen (fd, "r");
@@ -267,9 +341,31 @@ pygi_source_scanner_parse_file (PyGISourceScanner *self,
if (!gi_source_scanner_parse_file (self->scanner, fp))
{
- g_print ("Something went wrong..\n");
+ g_print ("Something went wrong during parsing.\n");
+ return NULL;
+ }
+
+ Py_INCREF (Py_None);
+ return Py_None;
+}
+
+static PyObject *
+pygi_source_scanner_lex_filename (PyGISourceScanner *self,
+ PyObject *args)
+{
+ char *filename;
+
+ if (!PyArg_ParseTuple (args, "s:SourceScanner.lex_filename", &filename))
+ return NULL;
+
+ if (!gi_source_scanner_lex_filename (self->scanner, filename))
+ {
+ g_print ("Something went wrong during lexing.\n");
return NULL;
}
+ self->scanner->filenames =
+ g_list_append (self->scanner->filenames, g_strdup (filename));
+ self->scanner->current_filename = g_strdup (filename);
Py_INCREF (Py_None);
return Py_None;
@@ -314,9 +410,40 @@ pygi_source_scanner_get_symbols (PyGISourceScanner *self)
return list;
}
+static PyObject *
+pygi_source_scanner_get_directives (PyGISourceScanner *self,
+ PyObject *args)
+{
+ GSList *l, *directives;
+ PyObject *list;
+ int i = 0;
+ char *name;
+
+ if (!PyArg_ParseTuple (args, "s:SourceScanner.get_directives", &name))
+ return NULL;
+
+ directives = gi_source_scanner_get_directives (self->scanner, name);
+ list = PyList_New (g_slist_length (directives));
+
+ for (l = directives; l; l = l->next)
+ {
+ PyGISourceDirective *item;
+ item = (PyGISourceDirective *)PyObject_New (PyGISourceDirective,
+ &PyGISourceDirective_Type);
+ item->directive = l->data;
+ PyList_SetItem (list, i++, (PyObject*)item);
+ Py_INCREF (item);
+ }
+
+ Py_INCREF (list);
+ return list;
+}
+
static const PyMethodDef _PyGISourceScanner_methods[] = {
+ { "get_directives", (PyCFunction) pygi_source_scanner_get_directives, METH_VARARGS },
{ "get_symbols", (PyCFunction) pygi_source_scanner_get_symbols, METH_NOARGS },
{ "parse_file", (PyCFunction) pygi_source_scanner_parse_file, METH_VARARGS },
+ { "lex_filename", (PyCFunction) pygi_source_scanner_lex_filename, METH_VARARGS },
{ "set_macro_scan", (PyCFunction) pygi_source_scanner_set_macro_scan, METH_VARARGS },
{ NULL, NULL, 0 }
};
@@ -337,6 +464,9 @@ init_giscanner(void)
(PyMethodDef*)pyscanner_functions);
d = PyModule_GetDict (m);
+ PyGISourceDirective_Type.tp_getset = (PyGetSetDef*)_PyGISourceDirective_getsets;
+ REGISTER_TYPE (d, "SourceDirective", PyGISourceDirective_Type);
+
PyGISourceScanner_Type.tp_init = (initproc)pygi_source_scanner_init;
PyGISourceScanner_Type.tp_methods = (PyMethodDef*)_PyGISourceScanner_methods;
REGISTER_TYPE (d, "SourceScanner", PyGISourceScanner_Type);
diff --git a/giscanner/sourcescanner.c b/giscanner/sourcescanner.c
index 39507924..0087f60d 100644
--- a/giscanner/sourcescanner.c
+++ b/giscanner/sourcescanner.c
@@ -287,3 +287,10 @@ gi_source_scanner_get_symbols (GISourceScanner *scanner)
{
return g_slist_reverse (scanner->symbols);
}
+
+GSList *
+gi_source_scanner_get_directives(GISourceScanner *scanner,
+ const gchar *name)
+{
+ return g_hash_table_lookup (scanner->directives_map, name);
+}
diff --git a/giscanner/sourcescanner.h b/giscanner/sourcescanner.h
index 496a2267..b0f4de7c 100644
--- a/giscanner/sourcescanner.h
+++ b/giscanner/sourcescanner.h
@@ -143,6 +143,8 @@ gboolean gi_source_scanner_parse_file (GISourceScanner *igener
void gi_source_scanner_set_macro_scan (GISourceScanner *scanner,
gboolean macro_scan);
GSList * gi_source_scanner_get_symbols (GISourceScanner *scanner);
+GSList * gi_source_scanner_get_directives (GISourceScanner *scanner,
+ const gchar *name);
void gi_source_scanner_free (GISourceScanner *scanner);
GISourceSymbol * gi_source_symbol_new (GISourceSymbolType type);
diff --git a/giscanner/sourcescanner.py b/giscanner/sourcescanner.py
index 16b43163..c0b2044c 100644
--- a/giscanner/sourcescanner.py
+++ b/giscanner/sourcescanner.py
@@ -3,6 +3,31 @@ import subprocess
import giscanner
+
+class SourceSymbol(object):
+ def __init__(self, symbol, directives):
+ self._symbol = symbol
+ self._directives = directives
+
+ def directives(self):
+ mapping = {}
+ for directive in self._directives:
+ mapping[directive.name] = directive.options
+ return mapping
+
+ @property
+ def ident(self):
+ return self._symbol.ident
+
+ @property
+ def type(self):
+ return self._symbol.type
+
+ @property
+ def base_type(self):
+ return self._symbol.base_type
+
+
class SourceScanner(object):
def __init__(self):
self._scanner = giscanner.SourceScanner()
@@ -20,9 +45,18 @@ class SourceScanner(object):
if not opt in self._cpp_options:
self._cpp_options.append(opt)
- def parse_file(self, filename):
- self._parse_one(filename)
- self._filenames.append(filename)
+ def parse_files(self, filenames):
+ headers = []
+ for filename in filenames:
+ if filename.endswith('.c'):
+ filename = os.path.abspath(filename)
+ self._scanner.lex_filename(filename)
+ else:
+ headers.append(filename)
+
+ for filename in headers:
+ self._parse_one(filename)
+ self._filenames.append(filename)
def parse_macros(self):
self._scanner.set_macro_scan(True)
@@ -32,7 +66,8 @@ class SourceScanner(object):
def get_symbols(self):
for symbol in self._scanner.get_symbols():
- yield symbol
+ yield SourceSymbol(
+ symbol, self._scanner.get_directives(symbol.ident))
def dump(self):
print '-'*30
@@ -42,10 +77,6 @@ class SourceScanner(object):
# Private
def _parse_one(self, filename):
- if filename.endswith('.c'):
- # FIXME lex only
- return
-
filename = os.path.abspath(filename)
proc = self._preprocess(filename)
fd = proc.stdout.fileno()
diff --git a/giscanner/treebuilder.py b/giscanner/treebuilder.py
index f2ee906a..9508bc74 100644
--- a/giscanner/treebuilder.py
+++ b/giscanner/treebuilder.py
@@ -2,12 +2,13 @@ import giscanner
class Node(object):
- pass
+ def __init__(self, name=None):
+ self.name = name
class Function(Node):
def __init__(self, name, retval, parameters, symbol):
- self.name = name
+ Node.__init__(self, name)
self.retval = retval
self.parameters = parameters
self.symbol = symbol
@@ -19,8 +20,10 @@ class Function(Node):
class Parameter(Node):
def __init__(self, name, type):
- self.name = name
+ Node.__init__(self, name)
self.type = type
+ self.direction = 'in'
+ self.transfer = 'none'
def __repr__(self):
return 'Parameter(%r, %r)' % (self.name, self.type)
@@ -28,7 +31,7 @@ class Parameter(Node):
class Enum(Node):
def __init__(self, name, members):
- self.name = name
+ Node.__init__(self, name)
self.members = members
def __repr__(self):
@@ -37,7 +40,7 @@ class Enum(Node):
class Member(Node):
def __init__(self, name, value):
- self.name = name
+ Node.__init__(self, name)
self.value = value
def __repr__(self):
@@ -45,16 +48,15 @@ class Member(Node):
class Struct(Node):
- def __init__(self, name):
- self.name = name
-
def __repr__(self):
return 'Struct(%r)' % (self.name,)
class Return(Node):
def __init__(self, type):
+ Node.__init__(self)
self.type = type
+ self.transfer = 'none'
def __repr__(self):
return 'Return(%r)' % (self.type,)
@@ -62,7 +64,7 @@ class Return(Node):
class Class(Node):
def __init__(self, name, parent):
- self.name = name
+ Node.__init__(self, name)
self.parent = parent
self.methods = []
self.constructors = []
@@ -76,7 +78,7 @@ class Class(Node):
class Interface(Node):
def __init__(self, name):
- self.name = name
+ Node.__init__(self, name)
self.methods = []
self.properties = []
@@ -88,7 +90,7 @@ class Interface(Node):
class Constant(Node):
def __init__(self, name, type, value):
- self.name = name
+ Node.__init__(self, name)
self.type = type
self.value = value
@@ -99,7 +101,7 @@ class Constant(Node):
class Property(Node):
def __init__(self, name, type):
- self.name = name
+ Node.__init__(self, name)
self.type = type
def __repr__(self):
@@ -110,7 +112,7 @@ class Property(Node):
class Callback(Node):
def __init__(self, name, retval, parameters):
- self.name = name
+ Node.__init__(self, name)
self.retval = retval
self.parameters = parameters
@@ -166,9 +168,11 @@ class TreeBuilder(object):
return Enum(symbol.ident, members)
def _create_function(self, symbol):
- parameters = self._create_parameters(symbol.base_type)
- retval = Return(self._create_source_type(symbol.base_type.base_type))
- return Function(symbol.ident, retval, list(parameters), symbol.ident)
+ directives = symbol.directives()
+ parameters = list(self._create_parameters(symbol.base_type, directives))
+ return_ = self._create_return(symbol.base_type.base_type,
+ directives.get('return', []))
+ return Function(symbol.ident, return_, parameters, symbol.ident)
def _create_source_type(self, source_type):
if source_type.type == giscanner.CTYPE_VOID:
@@ -184,13 +188,39 @@ class TreeBuilder(object):
value = '???'
return value
- def _create_parameters(self, base_type):
+ def _create_parameters(self, base_type, options=None):
+ if not options:
+ options = {}
for child in base_type.child_list:
- yield self._create_parameter(child)
-
- def _create_parameter(self, symbol):
- return Parameter(symbol.ident,
- self._create_source_type(symbol.base_type))
+ yield self._create_parameter(
+ child, options.get(child.ident, []))
+
+ def _create_parameter(self, symbol, options):
+ param = Parameter(symbol.ident,
+ self._create_source_type(symbol.base_type))
+ for option in options:
+ if option in ['in-out', 'inout']:
+ param.direction = 'inout'
+ elif option == 'in':
+ param.direction = 'in'
+ elif option == 'out':
+ param.direction = 'out'
+ elif option == 'callee-owns':
+ param.transfer = 'full'
+ else:
+ print 'Unhandled parameter annotation option: %s' % (
+ option,)
+ return param
+
+ def _create_return(self, symbol, options):
+ return_ = Return(self._create_source_type(symbol))
+ for option in options:
+ if option == 'caller-owns':
+ return_.transfer = 'full'
+ else:
+ print 'Unhandled parameter annotation option: %s' % (
+ option,)
+ return return_
def _create_struct(self, symbol):
return Struct(symbol.ident)
diff --git a/tools/g-ir-scanner b/tools/g-ir-scanner
index 04da3ced..9dfe2f30 100755
--- a/tools/g-ir-scanner
+++ b/tools/g-ir-scanner
@@ -70,8 +70,7 @@ def main(args):
arg.endswith('.h')):
filenames.append(arg)
- for filename in filenames:
- ss.parse_file(filename)
+ ss.parse_files(filenames)
ss.parse_macros()
builder = GObjectTreeBuilder(options.namespace)