diff options
author | Johan Dahlin <jdahlin@async.com.br> | 2008-04-25 00:17:15 +0000 |
---|---|---|
committer | Johan Dahlin <johan@src.gnome.org> | 2008-04-25 00:17:15 +0000 |
commit | 3554af8cb2e3141c9a9386018dd7b0564b2a00f5 (patch) | |
tree | 776b7a7756e526ca7a412e13ac30dbe10570e1c1 /giscanner | |
parent | 36a587e0e6dd36bbe4956286b9ab5ec7b925ae0d (diff) | |
download | gobject-introspection-3554af8cb2e3141c9a9386018dd7b0564b2a00f5.tar.gz |
Add support for source/header annotations.
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.
svn path=/trunk/; revision=224
Diffstat (limited to 'giscanner')
-rw-r--r-- | giscanner/gidlwriter.py | 14 | ||||
-rw-r--r-- | giscanner/girwriter.py | 9 | ||||
-rw-r--r-- | giscanner/giscannermodule.c | 136 | ||||
-rw-r--r-- | giscanner/sourcescanner.c | 7 | ||||
-rw-r--r-- | giscanner/sourcescanner.h | 2 | ||||
-rw-r--r-- | giscanner/sourcescanner.py | 47 | ||||
-rw-r--r-- | giscanner/treebuilder.py | 74 |
7 files changed, 252 insertions, 37 deletions
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) |