ignore non-UTF-8 string constants
[gnome.gobject-introspection] / 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.1 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 "sourcescanner.h"
26 #include <Python.h>
27
28 #ifdef _WIN32
29 #include <fcntl.h>
30 #include <io.h>
31 #define WIN32_LEAN_AND_MEAN
32 #define STRICT
33 #include <windows.h>
34 #endif
35
36 #define NEW_CLASS(ctype, name, cname)         \
37 static const PyMethodDef _Py##cname##_methods[];    \
38 PyTypeObject Py##cname##_Type = {             \
39     PyObject_HEAD_INIT(NULL)                  \
40     0,                                        \
41     "scanner." name,                          \
42     sizeof(ctype),                    \
43     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,             \
44     0, 0, 0, 0, 0, 0,                         \
45     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, \
46     NULL, 0, 0, 0,                            \
47     0,        \
48     0, 0,                                     \
49     0,                                        \
50     0, 0, NULL, NULL, 0, 0,                   \
51     0             \
52 }
53
54 #define REGISTER_TYPE(d, name, type)          \
55     type.ob_type = &PyType_Type;              \
56     type.tp_alloc = PyType_GenericAlloc;      \
57     type.tp_new = PyType_GenericNew;          \
58     if (PyType_Ready (&type))                 \
59         return;                               \
60     PyDict_SetItemString (d, name, (PyObject *)&type); \
61     Py_INCREF (&type);
62
63 typedef struct {
64   PyObject_HEAD
65   GISourceDirective *directive;
66 } PyGISourceDirective;
67
68 typedef struct {
69   PyObject_HEAD
70   GISourceType *type;
71 } PyGISourceType;
72
73 static PyObject * pygi_source_type_new (GISourceType *type);
74
75 typedef struct {
76   PyObject_HEAD
77   GISourceSymbol *symbol;
78   PyObject *directives;
79 } PyGISourceSymbol;
80
81 typedef struct {
82   PyObject_HEAD
83   GISourceScanner *scanner;
84 } PyGISourceScanner;
85
86 NEW_CLASS (PyGISourceDirective, "SourceDirective", GISourceDirective);
87 NEW_CLASS (PyGISourceSymbol, "SourceSymbol", GISourceSymbol);
88 NEW_CLASS (PyGISourceType, "SourceType", GISourceType);
89 NEW_CLASS (PyGISourceScanner, "SourceScanner", GISourceScanner);
90
91
92 /* Directive */
93
94 static PyObject *
95 pygi_source_directive_new (GISourceDirective *directive)
96 {
97   PyGISourceDirective *self;
98
99   if (directive == NULL)
100     {
101       Py_INCREF (Py_None);
102       return Py_None;
103     }
104     
105   self = (PyGISourceDirective *)PyObject_New (PyGISourceDirective,
106                                               &PyGISourceDirective_Type);
107   self->directive = directive;
108   return (PyObject*)self;
109 }
110
111 static PyObject *
112 directive_get_name (PyGISourceDirective *self,
113                     void                *context)
114 {
115   return PyString_FromString (self->directive->name);
116 }
117
118 static PyObject *
119 directive_get_value (PyGISourceDirective *self,
120                      void                *context)
121 {
122   return PyString_FromString (self->directive->value);
123 }
124
125 static PyObject *
126 directive_get_options (PyGISourceDirective *self,
127                        void                *context)
128 {
129   GSList *l, *symbols;
130   PyObject *list;
131   int i = 0;
132
133   if (!self->directive)
134     return Py_BuildValue("[]");
135   
136   list = PyList_New (g_slist_length (self->directive->options));
137   
138   for (l = self->directive->options; l; l = l->next)
139     {
140       PyObject *item = PyString_FromString (l->data);
141       PyList_SetItem (list, i++, item);
142       Py_INCREF (item);
143     }
144
145   Py_INCREF (list);
146   return list;
147 }
148
149 static const PyGetSetDef _PyGISourceDirective_getsets[] = {
150   { "name", (getter)directive_get_name, NULL, NULL},
151   { "value", (getter)directive_get_value, NULL, NULL},
152   { "options", (getter)directive_get_options, NULL, NULL},
153   { 0 }
154 };
155
156 /* Symbol */
157
158 static PyObject *
159 pygi_source_symbol_new (GISourceSymbol *symbol)
160 {
161   PyGISourceSymbol *self;
162   
163   if (symbol == NULL)
164     {
165       Py_INCREF (Py_None);
166       return Py_None;
167     }
168     
169   self = (PyGISourceSymbol *)PyObject_New (PyGISourceSymbol,
170                                            &PyGISourceSymbol_Type);
171   self->symbol = symbol;
172   return (PyObject*)self;
173 }
174
175 static PyObject *
176 symbol_get_type (PyGISourceSymbol *self,
177                  void             *context)
178 {
179   return PyInt_FromLong (self->symbol->type);
180 }
181
182 static PyObject *
183 symbol_get_ident (PyGISourceSymbol *self,
184                   void            *context)
185 {
186   
187   if (!self->symbol->ident)
188     {
189       Py_INCREF(Py_None);
190       return Py_None;
191     }
192     
193   return PyString_FromString (self->symbol->ident);
194 }
195
196 static PyObject *
197 symbol_get_base_type (PyGISourceSymbol *self,
198                       void             *context)
199 {
200   return pygi_source_type_new (self->symbol->base_type);
201 }
202
203 static PyObject *
204 symbol_get_const_int (PyGISourceSymbol *self,
205                       void             *context)
206 {
207   return PyInt_FromLong (self->symbol->const_int);
208 }
209
210 static PyObject *
211 symbol_get_const_string (PyGISourceSymbol *self,
212                          void             *context)
213 {
214   if (!self->symbol->const_string)
215     {
216       Py_INCREF(Py_None);
217       return Py_None;
218     }
219     
220   return PyString_FromString (self->symbol->const_string);
221 }
222
223 static PyObject *
224 symbol_get_directives (PyGISourceSymbol *self,
225                        void             *context)
226 {
227   if (!self->directives)
228     self->directives = Py_BuildValue("[]");
229   Py_INCREF (self->directives);
230   return self->directives;
231 }
232
233 static int
234 symbol_set_directives (PyGISourceSymbol *self,
235                        PyObject         *value,
236                        void             *context)
237 {
238   self->directives = value;
239   Py_INCREF(value);
240   return 0;
241 }
242
243 static const PyGetSetDef _PyGISourceSymbol_getsets[] = {
244   /* int ref_count; */
245   { "type", (getter)symbol_get_type, NULL, NULL},
246   /* int id; */
247   { "ident", (getter)symbol_get_ident, NULL, NULL},
248   { "base_type", (getter)symbol_get_base_type, NULL, NULL},
249   /* gboolean const_int_set; */
250   { "const_int", (getter)symbol_get_const_int, NULL, NULL},  
251   { "const_string", (getter)symbol_get_const_string, NULL, NULL},  
252   { "directives", (getter)symbol_get_directives,
253     (setter)symbol_set_directives, NULL},  
254   { 0 }
255 };
256
257
258
259 /* Type */
260
261 static PyObject *
262 pygi_source_type_new (GISourceType *type)
263 {
264   PyGISourceType *self;
265   
266   if (type == NULL)
267     {
268       Py_INCREF (Py_None);
269       return Py_None;
270     }
271   
272   self = (PyGISourceType *)PyObject_New (PyGISourceType,
273                                          &PyGISourceType_Type);
274   self->type = type;
275   return (PyObject*)self;
276 }
277
278 static PyObject *
279 type_get_type (PyGISourceType *self,
280                void           *context)
281 {
282   return PyInt_FromLong (self->type->type);
283 }
284
285 static PyObject *
286 type_get_storage_class_specifier (PyGISourceType *self,
287                                   void           *context)
288 {
289   return PyInt_FromLong (self->type->storage_class_specifier);
290 }
291
292 static PyObject *
293 type_get_type_qualifier (PyGISourceType *self,
294                          void           *context)
295 {
296   return PyInt_FromLong (self->type->type_qualifier);
297 }
298
299 static PyObject *
300 type_get_function_specifier (PyGISourceType *self,
301                              void           *context)
302 {
303   return PyInt_FromLong (self->type->function_specifier);
304 }
305
306 static PyObject *
307 type_get_name (PyGISourceType *self,
308                void           *context)
309 {
310   if (!self->type->name)
311     {
312       Py_INCREF (Py_None);
313       return Py_None;
314     }
315     
316   return PyString_FromString (self->type->name);
317 }
318
319 static PyObject *
320 type_get_base_type (PyGISourceType *self,
321                     void           *context)
322 {
323   return pygi_source_type_new (self->type->base_type);
324 }
325
326 static PyObject *
327 type_get_child_list (PyGISourceType *self,
328                      void           *context)
329 {
330   GList *l, *symbols;
331   PyObject *list;
332   int i = 0;
333
334   if (!self->type)
335     return Py_BuildValue("[]");
336   
337   list = PyList_New (g_list_length (self->type->child_list));
338   
339   for (l = self->type->child_list; l; l = l->next)
340     {
341       PyObject *item = pygi_source_symbol_new (l->data);
342       PyList_SetItem (list, i++, item);
343       Py_INCREF (item);
344     }
345
346   Py_INCREF (list);
347   return list;
348 }
349
350 static const PyGetSetDef _PyGISourceType_getsets[] = {
351   { "type", (getter)type_get_type, NULL, NULL},
352   { "storage_class_specifier", (getter)type_get_storage_class_specifier, NULL, NULL},
353   { "type_qualifier", (getter)type_get_type_qualifier, NULL, NULL},
354   { "function_specifier", (getter)type_get_function_specifier, NULL, NULL},
355   { "name", (getter)type_get_name, NULL, NULL},
356   { "base_type", (getter)type_get_base_type, NULL, NULL},
357   { "child_list", (getter)type_get_child_list, NULL, NULL},
358   { 0 }
359 };
360
361
362
363 /* Scanner */
364
365 static int
366 pygi_source_scanner_init (PyGISourceScanner *self,
367                           PyObject          *args,
368                           PyObject          *kwargs)
369 {
370   if (!PyArg_ParseTuple (args, ":SourceScanner.__init__"))
371     return -1;
372
373   self->scanner = gi_source_scanner_new ();
374
375   return 0;
376 }
377
378 static PyObject *
379 pygi_source_scanner_append_filename (PyGISourceScanner *self,
380                                      PyObject          *args)
381 {
382   char *filename;
383
384   if (!PyArg_ParseTuple (args, "s:SourceScanner.append_filename", &filename))
385     return NULL;
386
387   self->scanner->filenames = g_list_append (self->scanner->filenames,
388                                             g_strdup (filename));
389   
390   Py_INCREF (Py_None);
391   return Py_None;
392 }
393
394 static PyObject *
395 pygi_source_scanner_parse_macros (PyGISourceScanner *self,
396                                   PyObject          *args)
397 {
398   GList *filenames;
399   int i;
400   PyObject *list;
401
402   list = PyTuple_GET_ITEM (args, 0);
403
404   if (!PyList_Check (list))
405     {
406       PyErr_SetString (PyExc_RuntimeError, "parse macro takes a list of filenames");
407       return NULL;
408     }
409
410   filenames = NULL;
411   for (i = 0; i < PyList_Size (list); ++i)
412     {
413       PyObject *obj;
414       char *filename;
415
416       obj = PyList_GetItem (list, i);
417       filename = PyString_AsString (obj);
418
419       filenames = g_list_append (filenames, filename);
420     }
421
422   gi_source_scanner_parse_macros (self->scanner, filenames);
423   g_list_free (filenames);
424
425   Py_INCREF (Py_None);
426   return Py_None;
427 }
428
429 static PyObject *
430 pygi_source_scanner_parse_file (PyGISourceScanner *self,
431                                 PyObject          *args)
432 {
433   int fd;
434   FILE *fp;
435   
436   if (!PyArg_ParseTuple (args, "i:SourceScanner.parse_file", &fd))
437     return NULL;
438
439 #ifdef _WIN32
440   /* The file descriptor passed to us is from the C library Python
441    * uses. That is msvcr71.dll at least for Python 2.5. This code, at
442    * least if compiled with mingw, uses msvcrt.dll, so we cannot use
443    * the file descriptor directly. So perform appropriate magic.
444    */
445   {
446     HMODULE msvcr71;
447     int (*p__get_osfhandle) (int);
448     HANDLE handle;
449
450     msvcr71 = GetModuleHandle ("msvcr71.dll");
451     if (!msvcr71)
452       {
453         g_print ("No msvcr71.dll loaded.\n");
454         return NULL;
455       }
456
457     p__get_osfhandle = GetProcAddress (msvcr71, "_get_osfhandle");
458     if (!p__get_osfhandle)
459       {
460         g_print ("No _get_osfhandle found in msvcr71.dll.\n");
461         return NULL;
462       }
463
464     handle = p__get_osfhandle (fd);
465     if (!p__get_osfhandle)
466       {
467         g_print ("Could not get OS handle from msvcr71 fd.\n");
468         return NULL;
469       }
470     
471     fd = _open_osfhandle (handle, _O_RDONLY);
472     if (fd == -1)
473       {
474         g_print ("Could not open C fd from OS handle.\n");
475         return NULL;
476       }
477   }
478 #endif
479
480   fp = fdopen (fd, "r");
481   if (!fp)
482     {
483       PyErr_SetFromErrno (PyExc_OSError);
484       return NULL;
485     }
486
487   if (!gi_source_scanner_parse_file (self->scanner, fp))
488     {
489       g_print ("Something went wrong during parsing.\n");
490       return NULL;
491     }
492
493   Py_INCREF (Py_None);
494   return Py_None;
495 }
496
497 static PyObject *
498 pygi_source_scanner_lex_filename (PyGISourceScanner *self,
499                                   PyObject          *args)
500 {
501   char *filename;
502   
503   if (!PyArg_ParseTuple (args, "s:SourceScanner.lex_filename", &filename))
504     return NULL;
505
506   if (!gi_source_scanner_lex_filename (self->scanner, filename))
507     {
508       g_print ("Something went wrong during lexing.\n");
509       return NULL;
510     }
511   self->scanner->filenames =
512     g_list_append (self->scanner->filenames, g_strdup (filename));
513   self->scanner->current_filename = g_strdup (filename);
514
515   Py_INCREF (Py_None);
516   return Py_None;
517 }
518
519 static PyObject *
520 pygi_source_scanner_set_macro_scan (PyGISourceScanner *self,
521                                     PyObject          *args)
522 {
523   int macro_scan;
524   
525   if (!PyArg_ParseTuple (args, "b:SourceScanner.set_macro_scan", &macro_scan))
526     return NULL;
527
528   gi_source_scanner_set_macro_scan (self->scanner, macro_scan);
529
530   Py_INCREF (Py_None);
531   return Py_None;
532 }
533
534 static PyObject *
535 pygi_source_scanner_get_symbols (PyGISourceScanner *self)
536 {
537   GSList *l, *symbols;
538   PyObject *list;
539   int i = 0;
540   
541   symbols = gi_source_scanner_get_symbols (self->scanner);
542   list = PyList_New (g_slist_length (symbols));
543   
544   for (l = symbols; l; l = l->next)
545     {
546       PyObject *item = pygi_source_symbol_new (l->data);
547       PyList_SetItem (list, i++, item);
548       Py_INCREF (item);
549     }
550
551   Py_INCREF (list);
552   return list;
553 }
554
555 static PyObject *
556 pygi_source_scanner_get_directives (PyGISourceScanner *self,
557                                     PyObject          *args)
558 {
559   GSList *l, *directives;
560   PyObject *list;
561   int i = 0;
562   char *name;
563   
564   if (!PyArg_ParseTuple (args, "s:SourceScanner.get_directives", &name))
565     return NULL;
566   
567   directives = gi_source_scanner_get_directives (self->scanner, name);
568   list = PyList_New (g_slist_length (directives));
569   
570   for (l = directives; l; l = l->next)
571     {
572       PyObject *item = pygi_source_directive_new (l->data);
573       PyList_SetItem (list, i++, item);
574       Py_INCREF (item);
575     }
576
577   Py_INCREF (list);
578   return list;
579 }
580
581 static const PyMethodDef _PyGISourceScanner_methods[] = {
582   { "get_directives", (PyCFunction) pygi_source_scanner_get_directives, METH_VARARGS },
583   { "get_symbols", (PyCFunction) pygi_source_scanner_get_symbols, METH_NOARGS },
584   { "append_filename", (PyCFunction) pygi_source_scanner_append_filename, METH_VARARGS },
585   { "parse_file", (PyCFunction) pygi_source_scanner_parse_file, METH_VARARGS },
586   { "parse_macros", (PyCFunction) pygi_source_scanner_parse_macros, METH_VARARGS },
587   { "lex_filename", (PyCFunction) pygi_source_scanner_lex_filename, METH_VARARGS },
588   { "set_macro_scan", (PyCFunction) pygi_source_scanner_set_macro_scan, METH_VARARGS },
589   { NULL, NULL, 0 }
590 };
591
592
593 /* Module */
594
595 static const PyMethodDef pyscanner_functions[] = {
596   { NULL, NULL, 0, NULL }
597 };
598
599 DL_EXPORT(void)
600 init_giscanner(void)
601 {
602     PyObject *m, *d;
603
604     m = Py_InitModule ("giscanner._giscanner",
605                        (PyMethodDef*)pyscanner_functions);
606     d = PyModule_GetDict (m);
607
608     PyGISourceDirective_Type.tp_getset = (PyGetSetDef*)_PyGISourceDirective_getsets;
609     REGISTER_TYPE (d, "SourceDirective", PyGISourceDirective_Type);
610
611     PyGISourceScanner_Type.tp_init = (initproc)pygi_source_scanner_init;
612     PyGISourceScanner_Type.tp_methods = (PyMethodDef*)_PyGISourceScanner_methods;
613     REGISTER_TYPE (d, "SourceScanner", PyGISourceScanner_Type);
614
615     PyGISourceSymbol_Type.tp_getset = (PyGetSetDef*)_PyGISourceSymbol_getsets;
616     REGISTER_TYPE (d, "SourceSymbol", PyGISourceSymbol_Type);
617
618     PyGISourceType_Type.tp_getset = (PyGetSetDef*)_PyGISourceType_getsets;
619     REGISTER_TYPE (d, "SourceType", PyGISourceType_Type);
620 }