gimarshallingtests: Add string_ to boxed structure
[platform/upstream/gobject-introspection.git] / giscanner / giscannermodule.c
1 /* GObject introspection: scanner
2  *
3  * Copyright (C) 2008  Johan Dahlin <johan@gnome.org>
4  *
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.
9  *
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.
14  *
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.
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #  include "config.h"
24 #endif
25 #include <Python.h>
26 #include "sourcescanner.h"
27
28 #ifdef G_OS_WIN32
29 #define USE_WINDOWS
30 #endif
31 #include "grealpath.h"
32
33 #ifdef _WIN32
34 #include <fcntl.h>
35 #include <io.h>
36 #define WIN32_LEAN_AND_MEAN
37 #define STRICT
38 #include <windows.h>
39 #endif
40
41 #include <glib-object.h>
42
43 DL_EXPORT(void) init_giscanner(void);
44
45 #define NEW_CLASS(ctype, name, cname, num_methods)            \
46 static const PyMethodDef _Py##cname##_methods[num_methods];    \
47 PyTypeObject Py##cname##_Type = {             \
48     PyObject_HEAD_INIT(NULL)                  \
49     0,                                        \
50     "scanner." name,                          \
51     sizeof(ctype),                    \
52     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,             \
53     0, 0, 0, 0, 0, 0,                         \
54     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, \
55     NULL, 0, 0, 0,                            \
56     0,        \
57     0, 0,                                     \
58     0,                                        \
59     0, 0, NULL, NULL, 0, 0,                   \
60     0             \
61 }
62
63 #define REGISTER_TYPE(d, name, type)          \
64     type.ob_type = &PyType_Type;              \
65     type.tp_alloc = PyType_GenericAlloc;      \
66     type.tp_new = PyType_GenericNew;          \
67     if (PyType_Ready (&type))                 \
68         return;                               \
69     PyDict_SetItemString (d, name, (PyObject *)&type); \
70     Py_INCREF (&type);
71
72 typedef struct {
73   PyObject_HEAD
74   GISourceType *type;
75 } PyGISourceType;
76
77 static PyObject * pygi_source_type_new (GISourceType *type);
78
79 typedef struct {
80   PyObject_HEAD
81   GISourceSymbol *symbol;
82 } PyGISourceSymbol;
83
84 typedef struct {
85   PyObject_HEAD
86   GISourceScanner *scanner;
87 } PyGISourceScanner;
88
89 NEW_CLASS (PyGISourceSymbol, "SourceSymbol", GISourceSymbol, 10);
90 NEW_CLASS (PyGISourceType, "SourceType", GISourceType, 9);
91 NEW_CLASS (PyGISourceScanner, "SourceScanner", GISourceScanner, 8);
92
93
94 /* Symbol */
95
96 static PyObject *
97 pygi_source_symbol_new (GISourceSymbol *symbol)
98 {
99   PyGISourceSymbol *self;
100
101   if (symbol == NULL)
102     {
103       Py_INCREF (Py_None);
104       return Py_None;
105     }
106
107   self = (PyGISourceSymbol *)PyObject_New (PyGISourceSymbol,
108                                            &PyGISourceSymbol_Type);
109   self->symbol = symbol;
110   return (PyObject*)self;
111 }
112
113 static PyObject *
114 symbol_get_type (PyGISourceSymbol *self,
115                  void             *context)
116 {
117   return PyInt_FromLong (self->symbol->type);
118 }
119
120 static PyObject *
121 symbol_get_line (PyGISourceSymbol *self,
122                  void             *context)
123 {
124   return PyInt_FromLong (self->symbol->line);
125 }
126
127 static PyObject *
128 symbol_get_private (PyGISourceSymbol *self,
129                     void             *context)
130 {
131   return PyBool_FromLong (self->symbol->private);
132 }
133
134 static PyObject *
135 symbol_get_ident (PyGISourceSymbol *self,
136                   void            *context)
137 {
138
139   if (!self->symbol->ident)
140     {
141       Py_INCREF(Py_None);
142       return Py_None;
143     }
144
145   return PyString_FromString (self->symbol->ident);
146 }
147
148 static PyObject *
149 symbol_get_base_type (PyGISourceSymbol *self,
150                       void             *context)
151 {
152   return pygi_source_type_new (self->symbol->base_type);
153 }
154
155 static PyObject *
156 symbol_get_const_int (PyGISourceSymbol *self,
157                       void             *context)
158 {
159   if (!self->symbol->const_int_set)
160     {
161       Py_INCREF(Py_None);
162       return Py_None;
163     }
164
165   if (self->symbol->const_int_is_unsigned)
166     return PyLong_FromUnsignedLongLong ((unsigned long long)self->symbol->const_int);
167   else
168     return PyLong_FromLongLong ((long long)self->symbol->const_int);
169 }
170
171 static PyObject *
172 symbol_get_const_double (PyGISourceSymbol *self,
173                          void             *context)
174 {
175   if (!self->symbol->const_double_set)
176     {
177       Py_INCREF(Py_None);
178       return Py_None;
179     }
180   return PyFloat_FromDouble (self->symbol->const_double);
181 }
182
183 static PyObject *
184 symbol_get_const_string (PyGISourceSymbol *self,
185                          void             *context)
186 {
187   if (!self->symbol->const_string)
188     {
189       Py_INCREF(Py_None);
190       return Py_None;
191     }
192
193   return PyString_FromString (self->symbol->const_string);
194 }
195
196 static PyObject *
197 symbol_get_source_filename (PyGISourceSymbol *self,
198                             void             *context)
199 {
200   if (!self->symbol->source_filename)
201     {
202       Py_INCREF(Py_None);
203       return Py_None;
204     }
205
206   return PyString_FromString (self->symbol->source_filename);
207 }
208
209 static const PyGetSetDef _PyGISourceSymbol_getsets[] = {
210   /* int ref_count; */
211   { "type", (getter)symbol_get_type, NULL, NULL},
212   /* int id; */
213   { "ident", (getter)symbol_get_ident, NULL, NULL},
214   { "base_type", (getter)symbol_get_base_type, NULL, NULL},
215   /* gboolean const_int_set; */
216   { "const_int", (getter)symbol_get_const_int, NULL, NULL},
217   /* gboolean const_double_set; */
218   { "const_double", (getter)symbol_get_const_double, NULL, NULL},
219   { "const_string", (getter)symbol_get_const_string, NULL, NULL},
220   { "source_filename", (getter)symbol_get_source_filename, NULL, NULL},
221   { "line", (getter)symbol_get_line, NULL, NULL},
222   { "private", (getter)symbol_get_private, NULL, NULL},
223   { 0 }
224 };
225
226
227
228 /* Type */
229
230 static PyObject *
231 pygi_source_type_new (GISourceType *type)
232 {
233   PyGISourceType *self;
234
235   if (type == NULL)
236     {
237       Py_INCREF (Py_None);
238       return Py_None;
239     }
240
241   self = (PyGISourceType *)PyObject_New (PyGISourceType,
242                                          &PyGISourceType_Type);
243   self->type = type;
244   return (PyObject*)self;
245 }
246
247 static PyObject *
248 type_get_type (PyGISourceType *self,
249                void           *context)
250 {
251   return PyInt_FromLong (self->type->type);
252 }
253
254 static PyObject *
255 type_get_storage_class_specifier (PyGISourceType *self,
256                                   void           *context)
257 {
258   return PyInt_FromLong (self->type->storage_class_specifier);
259 }
260
261 static PyObject *
262 type_get_type_qualifier (PyGISourceType *self,
263                          void           *context)
264 {
265   return PyInt_FromLong (self->type->type_qualifier);
266 }
267
268 static PyObject *
269 type_get_function_specifier (PyGISourceType *self,
270                              void           *context)
271 {
272   return PyInt_FromLong (self->type->function_specifier);
273 }
274
275 static PyObject *
276 type_get_name (PyGISourceType *self,
277                void           *context)
278 {
279   if (!self->type->name)
280     {
281       Py_INCREF (Py_None);
282       return Py_None;
283     }
284
285   return PyString_FromString (self->type->name);
286 }
287
288 static PyObject *
289 type_get_base_type (PyGISourceType *self,
290                     void           *context)
291 {
292   return pygi_source_type_new (self->type->base_type);
293 }
294
295 static PyObject *
296 type_get_child_list (PyGISourceType *self,
297                      void           *context)
298 {
299   GList *l;
300   PyObject *list;
301   int i = 0;
302
303   if (!self->type)
304     return Py_BuildValue("[]");
305
306   list = PyList_New (g_list_length (self->type->child_list));
307
308   for (l = self->type->child_list; l; l = l->next)
309     {
310       PyObject *item = pygi_source_symbol_new (l->data);
311       PyList_SetItem (list, i++, item);
312     }
313
314   Py_INCREF (list);
315   return list;
316 }
317
318 static PyObject *
319 type_get_is_bitfield (PyGISourceType *self,
320                              void           *context)
321 {
322   return PyInt_FromLong (self->type->is_bitfield);
323 }
324
325 static const PyGetSetDef _PyGISourceType_getsets[] = {
326   { "type", (getter)type_get_type, NULL, NULL},
327   { "storage_class_specifier", (getter)type_get_storage_class_specifier, NULL, NULL},
328   { "type_qualifier", (getter)type_get_type_qualifier, NULL, NULL},
329   { "function_specifier", (getter)type_get_function_specifier, NULL, NULL},
330   { "name", (getter)type_get_name, NULL, NULL},
331   { "base_type", (getter)type_get_base_type, NULL, NULL},
332   { "child_list", (getter)type_get_child_list, NULL, NULL},
333   { "is_bitfield", (getter)type_get_is_bitfield, NULL, NULL},
334   { 0 }
335 };
336
337
338
339 /* Scanner */
340
341 static int
342 pygi_source_scanner_init (PyGISourceScanner *self,
343                           PyObject          *args,
344                           PyObject          *kwargs)
345 {
346   if (!PyArg_ParseTuple (args, ":SourceScanner.__init__"))
347     return -1;
348
349   self->scanner = gi_source_scanner_new ();
350
351   return 0;
352 }
353
354 static PyObject *
355 pygi_source_scanner_append_filename (PyGISourceScanner *self,
356                                      PyObject          *args)
357 {
358   char *filename;
359
360   if (!PyArg_ParseTuple (args, "s:SourceScanner.append_filename", &filename))
361     return NULL;
362
363   self->scanner->filenames = g_list_append (self->scanner->filenames,
364                                             g_realpath (filename));
365
366   Py_INCREF (Py_None);
367   return Py_None;
368 }
369
370 static PyObject *
371 pygi_source_scanner_parse_macros (PyGISourceScanner *self,
372                                   PyObject          *args)
373 {
374   GList *filenames;
375   int i;
376   PyObject *list;
377
378   list = PyTuple_GET_ITEM (args, 0);
379
380   if (!PyList_Check (list))
381     {
382       PyErr_SetString (PyExc_RuntimeError, "parse macro takes a list of filenames");
383       return NULL;
384     }
385
386   filenames = NULL;
387   for (i = 0; i < PyList_Size (list); ++i)
388     {
389       PyObject *obj;
390       char *filename;
391
392       obj = PyList_GetItem (list, i);
393       filename = PyString_AsString (obj);
394
395       filenames = g_list_append (filenames, filename);
396     }
397
398   gi_source_scanner_parse_macros (self->scanner, filenames);
399   g_list_free (filenames);
400
401   Py_INCREF (Py_None);
402   return Py_None;
403 }
404
405 static PyObject *
406 pygi_source_scanner_parse_file (PyGISourceScanner *self,
407                                 PyObject          *args)
408 {
409   int fd;
410   FILE *fp;
411
412   if (!PyArg_ParseTuple (args, "i:SourceScanner.parse_file", &fd))
413     return NULL;
414
415 #ifdef _WIN32
416   /* The file descriptor passed to us is from the C library Python
417    * uses. That is msvcr71.dll for Python 2.5 and msvcr90.dll for
418    * Python 2.6, 2.7, 3.2 etc; and msvcr100.dll for Python 3.3 and later.
419    * This code, at least if compiled with mingw, uses
420    * msvcrt.dll, so we cannot use the file descriptor directly. So
421    * perform appropriate magic.
422    */
423
424   /* If we are using the following combinations,
425    * we can use the file descriptors directly
426    * (Not if a build using WDK is used):
427    * Python 2.6.x/2.7.x with Visual C++ 2008
428    * Python 3.1.x/3.2.x with Visual C++ 2008
429    * Python 3.3+ with Visual C++ 2010
430    */
431
432 #if (defined(_MSC_VER) && !defined(USE_WIN_DDK))
433 #if (PY_MAJOR_VERSION==2 && PY_MINOR_VERSION>=6 && (_MSC_VER >= 1500 && _MSC_VER < 1600))
434 #define MSVC_USE_FD_DIRECTLY 1
435 #elif (PY_MAJOR_VERSION==3 && PY_MINOR_VERSION<=2 && (_MSC_VER >= 1500 && _MSC_VER < 1600))
436 #define MSVC_USE_FD_DIRECTLY 1
437 #elif (PY_MAJOR_VERSION==3 && PY_MINOR_VERSION>=3 && (_MSC_VER >= 1600 && _MSC_VER < 1700))
438 #define MSVC_USE_FD_DIRECTLY 1
439 #endif
440 #endif
441
442 #ifndef MSVC_USE_FD_DIRECTLY
443   {
444 #if defined(PY_MAJOR_VERSION) && PY_MAJOR_VERSION==2 && PY_MINOR_VERSION==5
445 #define PYTHON_MSVCRXX_DLL "msvcr71.dll"
446 #elif defined(PY_MAJOR_VERSION) && PY_MAJOR_VERSION==2 && PY_MINOR_VERSION==6
447 #define PYTHON_MSVCRXX_DLL "msvcr90.dll"
448 #elif defined(PY_MAJOR_VERSION) && PY_MAJOR_VERSION==2 && PY_MINOR_VERSION==7
449 #define PYTHON_MSVCRXX_DLL "msvcr90.dll"
450 #elif defined(PY_MAJOR_VERSION) && PY_MAJOR_VERSION==3 && PY_MINOR_VERSION==2
451 #define PYTHON_MSVCRXX_DLL "msvcr90.dll"
452 #elif defined(PY_MAJOR_VERSION) && PY_MAJOR_VERSION==3 && PY_MINOR_VERSION>=3
453 #define PYTHON_MSVCRXX_DLL "msvcr100.dll"
454 #else
455 #error This Python version not handled
456 #endif
457     HMODULE msvcrxx;
458     intptr_t (*p__get_osfhandle) (int);
459     HANDLE handle;
460
461     msvcrxx = GetModuleHandle (PYTHON_MSVCRXX_DLL);
462     if (!msvcrxx)
463     {
464       g_print ("No " PYTHON_MSVCRXX_DLL " loaded.\n");
465       return NULL;
466     }
467
468     p__get_osfhandle = (intptr_t (*) (int)) GetProcAddress (msvcrxx, "_get_osfhandle");
469     if (!p__get_osfhandle)
470     {
471       g_print ("No _get_osfhandle found in " PYTHON_MSVCRXX_DLL ".\n");
472       return NULL;
473     }
474
475     handle = (HANDLE) p__get_osfhandle (fd);
476     if (!p__get_osfhandle)
477     {
478       g_print ("Could not get OS handle from " PYTHON_MSVCRXX_DLL " fd.\n");
479       return NULL;
480     }
481
482     fd = _open_osfhandle ((intptr_t) handle, _O_RDONLY);
483     if (fd == -1)
484     {
485       g_print ("Could not open C fd from OS handle.\n");
486       return NULL;
487     }
488   }
489 #endif
490 #endif
491
492   fp = fdopen (fd, "r");
493   if (!fp)
494     {
495       PyErr_SetFromErrno (PyExc_OSError);
496       return NULL;
497     }
498
499   if (!gi_source_scanner_parse_file (self->scanner, fp))
500     {
501       g_print ("Something went wrong during parsing.\n");
502       return NULL;
503     }
504
505   Py_INCREF (Py_None);
506   return Py_None;
507 }
508
509 static PyObject *
510 pygi_source_scanner_lex_filename (PyGISourceScanner *self,
511                                   PyObject          *args)
512 {
513   char *filename;
514
515   if (!PyArg_ParseTuple (args, "s:SourceScanner.lex_filename", &filename))
516     return NULL;
517
518   self->scanner->current_filename = g_strdup (filename);
519   if (!gi_source_scanner_lex_filename (self->scanner, filename))
520     {
521       g_print ("Something went wrong during lexing.\n");
522       return NULL;
523     }
524   self->scanner->filenames =
525     g_list_append (self->scanner->filenames, g_strdup (filename));
526
527   Py_INCREF (Py_None);
528   return Py_None;
529 }
530
531 static PyObject *
532 pygi_source_scanner_set_macro_scan (PyGISourceScanner *self,
533                                     PyObject          *args)
534 {
535   int macro_scan;
536
537   if (!PyArg_ParseTuple (args, "b:SourceScanner.set_macro_scan", &macro_scan))
538     return NULL;
539
540   gi_source_scanner_set_macro_scan (self->scanner, macro_scan);
541
542   Py_INCREF (Py_None);
543   return Py_None;
544 }
545
546 static PyObject *
547 pygi_source_scanner_get_symbols (PyGISourceScanner *self)
548 {
549   GSList *l, *symbols;
550   PyObject *list;
551   int i = 0;
552
553   symbols = gi_source_scanner_get_symbols (self->scanner);
554   list = PyList_New (g_slist_length (symbols));
555
556   for (l = symbols; l; l = l->next)
557     {
558       PyObject *item = pygi_source_symbol_new (l->data);
559       PyList_SetItem (list, i++, item);
560     }
561
562   Py_INCREF (list);
563   return list;
564 }
565
566 static PyObject *
567 pygi_source_scanner_get_comments (PyGISourceScanner *self)
568 {
569   GSList *l, *comments;
570   PyObject *list;
571   int i = 0;
572
573   comments = gi_source_scanner_get_comments (self->scanner);
574   list = PyList_New (g_slist_length (comments));
575
576   for (l = comments; l; l = l->next)
577     {
578       GISourceComment *comment = l->data;
579       PyObject *item = Py_BuildValue ("(ssi)", comment->comment,
580                                       comment->filename,
581                                       comment->line);
582       PyList_SetItem (list, i++, item);
583     }
584
585   Py_INCREF (list);
586   return list;
587 }
588
589 static const PyMethodDef _PyGISourceScanner_methods[] = {
590   { "get_comments", (PyCFunction) pygi_source_scanner_get_comments, METH_NOARGS },
591   { "get_symbols", (PyCFunction) pygi_source_scanner_get_symbols, METH_NOARGS },
592   { "append_filename", (PyCFunction) pygi_source_scanner_append_filename, METH_VARARGS },
593   { "parse_file", (PyCFunction) pygi_source_scanner_parse_file, METH_VARARGS },
594   { "parse_macros", (PyCFunction) pygi_source_scanner_parse_macros, METH_VARARGS },
595   { "lex_filename", (PyCFunction) pygi_source_scanner_lex_filename, METH_VARARGS },
596   { "set_macro_scan", (PyCFunction) pygi_source_scanner_set_macro_scan, METH_VARARGS },
597   { NULL, NULL, 0 }
598 };
599
600
601 static int calc_attrs_length(PyObject *attributes, int indent,
602                              int self_indent)
603 {
604   int attr_length = 0;
605   int i;
606
607   if (indent == -1)
608     return -1;
609
610   for (i = 0; i < PyList_Size (attributes); ++i)
611     {
612       PyObject *tuple, *pyvalue;
613       PyObject *s = NULL;
614       char *attr, *value;
615       char *escaped;
616
617       tuple = PyList_GetItem (attributes, i);
618       if (PyTuple_GetItem(tuple, 1) == Py_None)
619         continue;
620
621       if (!PyArg_ParseTuple(tuple, "sO", &attr, &pyvalue))
622         return -1;
623
624       if (PyUnicode_Check(pyvalue)) {
625         s = PyUnicode_AsUTF8String(pyvalue);
626         if (!s) {
627           return -1;
628         }
629         value = PyString_AsString(s);
630       } else if (PyString_Check(pyvalue)) {
631         value = PyString_AsString(pyvalue);
632       } else {
633         PyErr_SetString(PyExc_TypeError,
634                         "value must be string or unicode");
635         return -1;
636       }
637
638       escaped = g_markup_escape_text (value, -1);
639       attr_length += 2 + strlen(attr) + strlen(escaped) + 2;
640       g_free(escaped);
641       Py_XDECREF(s);
642     }
643
644   return attr_length + indent + self_indent;
645 }
646
647 /* Hall of shame, wasted time debugging the code below
648  * 20min - Johan 2009-02-19
649  */
650 static PyObject *
651 pygi_collect_attributes (PyObject *self,
652                          PyObject *args)
653 {
654   char *tag_name;
655   PyObject *attributes;
656   int indent, indent_len, i, j, self_indent;
657   char *indent_char;
658   gboolean first;
659   GString *attr_value = NULL;
660   int len;
661   PyObject *result = NULL;
662
663   if (!PyArg_ParseTuple(args, "sO!isi",
664                         &tag_name, &PyList_Type, &attributes,
665                         &self_indent, &indent_char,
666                         &indent))
667     return NULL;
668
669   if (attributes == Py_None || !PyList_Size(attributes))
670     return PyUnicode_DecodeUTF8("", 0, "strict");
671
672   len = calc_attrs_length(attributes, indent, self_indent);
673   if (len < 0)
674     return NULL;
675   if (len > 79)
676     indent_len = self_indent + strlen(tag_name) + 1;
677   else
678     indent_len = 0;
679
680   first = TRUE;
681   attr_value = g_string_new ("");
682
683   for (i = 0; i < PyList_Size (attributes); ++i)
684     {
685       PyObject *tuple, *pyvalue;
686       PyObject *s = NULL;
687       char *attr, *value, *escaped;
688
689       tuple = PyList_GetItem (attributes, i);
690
691       if (!PyTuple_Check (tuple))
692         {
693           PyErr_SetString(PyExc_TypeError,
694                           "attribute item must be a tuple");
695           goto out;
696         }
697
698       if (!PyTuple_Size (tuple) == 2)
699         {
700           PyErr_SetString(PyExc_IndexError,
701                           "attribute item must be a tuple of length 2");
702           goto out;
703         }
704
705       if (PyTuple_GetItem(tuple, 1) == Py_None)
706         continue;
707
708       /* this leaks, but we exit after, so */
709       if (!PyArg_ParseTuple(tuple, "sO", &attr, &pyvalue))
710         goto out;
711
712       if (PyUnicode_Check(pyvalue)) {
713         s = PyUnicode_AsUTF8String(pyvalue);
714         if (!s)
715           goto out;
716         value = PyString_AsString(s);
717       } else if (PyString_Check(pyvalue)) {
718         value = PyString_AsString(pyvalue);
719       } else {
720         PyErr_SetString(PyExc_TypeError,
721                         "value must be string or unicode");
722         goto out;
723       }
724
725       if (indent_len && !first)
726         {
727           g_string_append_c (attr_value, '\n');
728           for (j = 0; j < indent_len; j++)
729             g_string_append_c (attr_value, ' ');
730         }
731       g_string_append_c (attr_value, ' ');
732       g_string_append (attr_value, attr);
733       g_string_append_c (attr_value, '=');
734       g_string_append_c (attr_value, '\"');
735       escaped = g_markup_escape_text (value, -1);
736       g_string_append (attr_value, escaped);
737       g_string_append_c (attr_value, '\"');
738       if (first)
739         first = FALSE;
740       Py_XDECREF(s);
741   }
742
743   result = PyUnicode_DecodeUTF8 (attr_value->str, attr_value->len, "strict");
744  out:
745   if (attr_value != NULL)
746     g_string_free (attr_value, TRUE);
747   return result;
748 }
749
750 /* Module */
751
752 static const PyMethodDef pyscanner_functions[] = {
753   { "collect_attributes",
754     (PyCFunction) pygi_collect_attributes, METH_VARARGS },
755   { NULL, NULL, 0, NULL }
756 };
757
758 DL_EXPORT(void)
759 init_giscanner(void)
760 {
761     PyObject *m, *d;
762     gboolean is_uninstalled;
763
764     /* Hack to avoid having to create a fake directory structure; when
765      * running uninstalled, the module will be in the top builddir,
766      * with no _giscanner prefix.
767      */
768     is_uninstalled = g_getenv ("UNINSTALLED_INTROSPECTION_SRCDIR") != NULL;
769     m = Py_InitModule (is_uninstalled ? "_giscanner" : "giscanner._giscanner",
770                        (PyMethodDef*)pyscanner_functions);
771     d = PyModule_GetDict (m);
772
773     PyGISourceScanner_Type.tp_init = (initproc)pygi_source_scanner_init;
774     PyGISourceScanner_Type.tp_methods = (PyMethodDef*)_PyGISourceScanner_methods;
775     REGISTER_TYPE (d, "SourceScanner", PyGISourceScanner_Type);
776
777     PyGISourceSymbol_Type.tp_getset = (PyGetSetDef*)_PyGISourceSymbol_getsets;
778     REGISTER_TYPE (d, "SourceSymbol", PyGISourceSymbol_Type);
779
780     PyGISourceType_Type.tp_getset = (PyGetSetDef*)_PyGISourceType_getsets;
781     REGISTER_TYPE (d, "SourceType", PyGISourceType_Type);
782 }