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