1 /* GObject introspection: scanner
3 * Copyright (C) 2008 Johan Dahlin <johan@gnome.org>
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.
25 #include "sourcescanner.h"
31 #define WIN32_LEAN_AND_MEAN
36 DL_EXPORT(void) init_giscanner(void);
38 #define NEW_CLASS(ctype, name, cname) \
39 static const PyMethodDef _Py##cname##_methods[]; \
40 PyTypeObject Py##cname##_Type = { \
41 PyObject_HEAD_INIT(NULL) \
45 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
47 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, \
52 0, 0, NULL, NULL, 0, 0, \
56 #define REGISTER_TYPE(d, name, type) \
57 type.ob_type = &PyType_Type; \
58 type.tp_alloc = PyType_GenericAlloc; \
59 type.tp_new = PyType_GenericNew; \
60 if (PyType_Ready (&type)) \
62 PyDict_SetItemString (d, name, (PyObject *)&type); \
70 static PyObject * pygi_source_type_new (GISourceType *type);
74 GISourceSymbol *symbol;
79 GISourceScanner *scanner;
82 NEW_CLASS (PyGISourceSymbol, "SourceSymbol", GISourceSymbol);
83 NEW_CLASS (PyGISourceType, "SourceType", GISourceType);
84 NEW_CLASS (PyGISourceScanner, "SourceScanner", GISourceScanner);
90 pygi_source_symbol_new (GISourceSymbol *symbol)
92 PyGISourceSymbol *self;
100 self = (PyGISourceSymbol *)PyObject_New (PyGISourceSymbol,
101 &PyGISourceSymbol_Type);
102 self->symbol = symbol;
103 return (PyObject*)self;
107 symbol_get_type (PyGISourceSymbol *self,
110 return PyInt_FromLong (self->symbol->type);
114 symbol_get_ident (PyGISourceSymbol *self,
118 if (!self->symbol->ident)
124 return PyString_FromString (self->symbol->ident);
128 symbol_get_base_type (PyGISourceSymbol *self,
131 return pygi_source_type_new (self->symbol->base_type);
135 symbol_get_const_int (PyGISourceSymbol *self,
138 return PyInt_FromLong (self->symbol->const_int);
142 symbol_get_const_string (PyGISourceSymbol *self,
145 if (!self->symbol->const_string)
151 return PyString_FromString (self->symbol->const_string);
154 static const PyGetSetDef _PyGISourceSymbol_getsets[] = {
156 { "type", (getter)symbol_get_type, NULL, NULL},
158 { "ident", (getter)symbol_get_ident, NULL, NULL},
159 { "base_type", (getter)symbol_get_base_type, NULL, NULL},
160 /* gboolean const_int_set; */
161 { "const_int", (getter)symbol_get_const_int, NULL, NULL},
162 { "const_string", (getter)symbol_get_const_string, NULL, NULL},
171 pygi_source_type_new (GISourceType *type)
173 PyGISourceType *self;
181 self = (PyGISourceType *)PyObject_New (PyGISourceType,
182 &PyGISourceType_Type);
184 return (PyObject*)self;
188 type_get_type (PyGISourceType *self,
191 return PyInt_FromLong (self->type->type);
195 type_get_storage_class_specifier (PyGISourceType *self,
198 return PyInt_FromLong (self->type->storage_class_specifier);
202 type_get_type_qualifier (PyGISourceType *self,
205 return PyInt_FromLong (self->type->type_qualifier);
209 type_get_function_specifier (PyGISourceType *self,
212 return PyInt_FromLong (self->type->function_specifier);
216 type_get_name (PyGISourceType *self,
219 if (!self->type->name)
225 return PyString_FromString (self->type->name);
229 type_get_base_type (PyGISourceType *self,
232 return pygi_source_type_new (self->type->base_type);
236 type_get_child_list (PyGISourceType *self,
244 return Py_BuildValue("[]");
246 list = PyList_New (g_list_length (self->type->child_list));
248 for (l = self->type->child_list; l; l = l->next)
250 PyObject *item = pygi_source_symbol_new (l->data);
251 PyList_SetItem (list, i++, item);
260 type_get_is_bitfield (PyGISourceType *self,
263 return PyInt_FromLong (self->type->is_bitfield);
266 static const PyGetSetDef _PyGISourceType_getsets[] = {
267 { "type", (getter)type_get_type, NULL, NULL},
268 { "storage_class_specifier", (getter)type_get_storage_class_specifier, NULL, NULL},
269 { "type_qualifier", (getter)type_get_type_qualifier, NULL, NULL},
270 { "function_specifier", (getter)type_get_function_specifier, NULL, NULL},
271 { "name", (getter)type_get_name, NULL, NULL},
272 { "base_type", (getter)type_get_base_type, NULL, NULL},
273 { "child_list", (getter)type_get_child_list, NULL, NULL},
274 { "is_bitfield", (getter)type_get_is_bitfield, NULL, NULL},
283 pygi_source_scanner_init (PyGISourceScanner *self,
287 if (!PyArg_ParseTuple (args, ":SourceScanner.__init__"))
290 self->scanner = gi_source_scanner_new ();
296 pygi_source_scanner_append_filename (PyGISourceScanner *self,
301 if (!PyArg_ParseTuple (args, "s:SourceScanner.append_filename", &filename))
304 self->scanner->filenames = g_list_append (self->scanner->filenames,
305 g_strdup (filename));
312 pygi_source_scanner_parse_macros (PyGISourceScanner *self,
319 list = PyTuple_GET_ITEM (args, 0);
321 if (!PyList_Check (list))
323 PyErr_SetString (PyExc_RuntimeError, "parse macro takes a list of filenames");
328 for (i = 0; i < PyList_Size (list); ++i)
333 obj = PyList_GetItem (list, i);
334 filename = PyString_AsString (obj);
336 filenames = g_list_append (filenames, filename);
339 gi_source_scanner_parse_macros (self->scanner, filenames);
340 g_list_free (filenames);
347 pygi_source_scanner_parse_file (PyGISourceScanner *self,
353 if (!PyArg_ParseTuple (args, "i:SourceScanner.parse_file", &fd))
357 /* The file descriptor passed to us is from the C library Python
358 * uses. That is msvcr71.dll at least for Python 2.5. This code, at
359 * least if compiled with mingw, uses msvcrt.dll, so we cannot use
360 * the file descriptor directly. So perform appropriate magic.
364 int (*p__get_osfhandle) (int);
367 msvcr71 = GetModuleHandle ("msvcr71.dll");
370 g_print ("No msvcr71.dll loaded.\n");
374 p__get_osfhandle = GetProcAddress (msvcr71, "_get_osfhandle");
375 if (!p__get_osfhandle)
377 g_print ("No _get_osfhandle found in msvcr71.dll.\n");
381 handle = p__get_osfhandle (fd);
382 if (!p__get_osfhandle)
384 g_print ("Could not get OS handle from msvcr71 fd.\n");
388 fd = _open_osfhandle (handle, _O_RDONLY);
391 g_print ("Could not open C fd from OS handle.\n");
397 fp = fdopen (fd, "r");
400 PyErr_SetFromErrno (PyExc_OSError);
404 if (!gi_source_scanner_parse_file (self->scanner, fp))
406 g_print ("Something went wrong during parsing.\n");
415 pygi_source_scanner_lex_filename (PyGISourceScanner *self,
420 if (!PyArg_ParseTuple (args, "s:SourceScanner.lex_filename", &filename))
423 self->scanner->current_filename = g_strdup (filename);
424 if (!gi_source_scanner_lex_filename (self->scanner, filename))
426 g_print ("Something went wrong during lexing.\n");
429 self->scanner->filenames =
430 g_list_append (self->scanner->filenames, g_strdup (filename));
437 pygi_source_scanner_set_macro_scan (PyGISourceScanner *self,
442 if (!PyArg_ParseTuple (args, "b:SourceScanner.set_macro_scan", ¯o_scan))
445 gi_source_scanner_set_macro_scan (self->scanner, macro_scan);
452 pygi_source_scanner_get_symbols (PyGISourceScanner *self)
458 symbols = gi_source_scanner_get_symbols (self->scanner);
459 list = PyList_New (g_slist_length (symbols));
461 for (l = symbols; l; l = l->next)
463 PyObject *item = pygi_source_symbol_new (l->data);
464 PyList_SetItem (list, i++, item);
473 pygi_source_scanner_get_comments (PyGISourceScanner *self)
475 GSList *l, *comments;
479 comments = gi_source_scanner_get_comments (self->scanner);
480 list = PyList_New (g_slist_length (comments));
482 for (l = comments; l; l = l->next)
484 PyObject *item = PyString_FromString (l->data);
485 PyList_SetItem (list, i++, item);
493 static const PyMethodDef _PyGISourceScanner_methods[] = {
494 { "get_comments", (PyCFunction) pygi_source_scanner_get_comments, METH_NOARGS },
495 { "get_symbols", (PyCFunction) pygi_source_scanner_get_symbols, METH_NOARGS },
496 { "append_filename", (PyCFunction) pygi_source_scanner_append_filename, METH_VARARGS },
497 { "parse_file", (PyCFunction) pygi_source_scanner_parse_file, METH_VARARGS },
498 { "parse_macros", (PyCFunction) pygi_source_scanner_parse_macros, METH_VARARGS },
499 { "lex_filename", (PyCFunction) pygi_source_scanner_lex_filename, METH_VARARGS },
500 { "set_macro_scan", (PyCFunction) pygi_source_scanner_set_macro_scan, METH_VARARGS },
505 static int calc_attrs_length(PyObject *attributes, int indent,
514 for (i = 0; i < PyList_Size (attributes); ++i)
520 tuple = PyList_GetItem (attributes, i);
521 if (PyTuple_GetItem(tuple, 1) == Py_None)
524 if (!PyArg_ParseTuple(tuple, "ss", &attr, &value))
527 escaped = g_markup_escape_text (value, -1);
528 attr_length += 2 + strlen(attr) + strlen(escaped) + 2;
532 return attr_length + indent + self_indent;
535 /* Hall of shame, wasted time debugging the code below
536 * 20min - Johan 2009-02-19
539 pygi_collect_attributes (PyObject *self,
543 PyObject *attributes;
544 int indent, indent_len, i, j, self_indent;
550 if (!PyArg_ParseTuple(args, "sOisi",
551 &tag_name, &attributes,
552 &self_indent, &indent_char,
556 if (attributes == Py_None || !PyList_Size(attributes))
557 return PyString_FromString("");
559 len = calc_attrs_length(attributes, indent, self_indent);
563 indent_len = self_indent + strlen(tag_name) + 1;
568 attr_value = g_string_new ("");
570 g_assert(PyList_Check(attributes));
572 for (i = 0; i < PyList_Size (attributes); ++i)
575 char *attr, *value, *escaped;
577 tuple = PyList_GetItem (attributes, i);
578 g_assert(tuple != NULL);
579 g_assert(PyTuple_Check(tuple));
580 g_assert(PyTuple_Size(tuple) == 2);
581 if (PyTuple_GetItem(tuple, 1) == Py_None)
584 /* this leaks, but we exit after, so */
585 if (!PyArg_ParseTuple(tuple, "ss", &attr, &value))
588 if (indent_len && !first)
590 g_string_append_c (attr_value, '\n');
591 for (j = 0; j < indent_len; j++)
592 g_string_append_c (attr_value, ' ');
594 g_string_append_c (attr_value, ' ');
595 g_string_append (attr_value, attr);
596 g_string_append_c (attr_value, '=');
597 g_string_append_c (attr_value, '\"');
598 escaped = g_markup_escape_text (value, -1);
599 g_string_append (attr_value, escaped);
600 g_string_append_c (attr_value, '\"');
605 return PyString_FromString (g_string_free (attr_value, FALSE));
610 static const PyMethodDef pyscanner_functions[] = {
611 { "collect_attributes",
612 (PyCFunction) pygi_collect_attributes, METH_VARARGS },
613 { NULL, NULL, 0, NULL }
621 m = Py_InitModule ("giscanner._giscanner",
622 (PyMethodDef*)pyscanner_functions);
623 d = PyModule_GetDict (m);
625 PyGISourceScanner_Type.tp_init = (initproc)pygi_source_scanner_init;
626 PyGISourceScanner_Type.tp_methods = (PyMethodDef*)_PyGISourceScanner_methods;
627 REGISTER_TYPE (d, "SourceScanner", PyGISourceScanner_Type);
629 PyGISourceSymbol_Type.tp_getset = (PyGetSetDef*)_PyGISourceSymbol_getsets;
630 REGISTER_TYPE (d, "SourceSymbol", PyGISourceSymbol_Type);
632 PyGISourceType_Type.tp_getset = (PyGetSetDef*)_PyGISourceType_getsets;
633 REGISTER_TYPE (d, "SourceType", PyGISourceType_Type);