* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
+ * version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
-#include "sourcescanner.h"
#include <Python.h>
+#include "sourcescanner.h"
+#include "grealpath.h"
+
+#ifdef _WIN32
+#include <fcntl.h>
+#include <io.h>
+#define WIN32_LEAN_AND_MEAN
+#define STRICT
+#include <windows.h>
+#endif
+
+DL_EXPORT(void) init_giscanner(void);
#define NEW_CLASS(ctype, name, cname) \
static const PyMethodDef _Py##cname##_methods[]; \
GISourceType *type;
} PyGISourceType;
+static PyObject * pygi_source_type_new (GISourceType *type);
+
typedef struct {
PyObject_HEAD
GISourceSymbol *symbol;
/* Symbol */
+static PyObject *
+pygi_source_symbol_new (GISourceSymbol *symbol)
+{
+ PyGISourceSymbol *self;
+
+ if (symbol == NULL)
+ {
+ Py_INCREF (Py_None);
+ return Py_None;
+ }
+
+ self = (PyGISourceSymbol *)PyObject_New (PyGISourceSymbol,
+ &PyGISourceSymbol_Type);
+ self->symbol = symbol;
+ return (PyObject*)self;
+}
+
static PyObject *
symbol_get_type (PyGISourceSymbol *self,
void *context)
return PyInt_FromLong (self->symbol->type);
}
+static PyObject *
+symbol_get_line (PyGISourceSymbol *self,
+ void *context)
+{
+ return PyInt_FromLong (self->symbol->line);
+}
+
static PyObject *
symbol_get_ident (PyGISourceSymbol *self,
void *context)
{
+
+ if (!self->symbol->ident)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
return PyString_FromString (self->symbol->ident);
}
symbol_get_base_type (PyGISourceSymbol *self,
void *context)
{
- PyGISourceType *item;
- item = (PyGISourceType *)PyObject_New (PyGISourceType,
- &PyGISourceType_Type);
- item->type = self->symbol->base_type;
- return (PyObject*)item;
+ return pygi_source_type_new (self->symbol->base_type);
}
static PyObject *
symbol_get_const_int (PyGISourceSymbol *self,
void *context)
{
+ if (!self->symbol->const_int_set)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
return PyInt_FromLong (self->symbol->const_int);
}
+static PyObject *
+symbol_get_const_double (PyGISourceSymbol *self,
+ void *context)
+{
+ if (!self->symbol->const_double_set)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ return PyFloat_FromDouble (self->symbol->const_double);
+}
+
static PyObject *
symbol_get_const_string (PyGISourceSymbol *self,
void *context)
return PyString_FromString (self->symbol->const_string);
}
+static PyObject *
+symbol_get_source_filename (PyGISourceSymbol *self,
+ void *context)
+{
+ if (!self->symbol->source_filename)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ return PyString_FromString (self->symbol->source_filename);
+}
+
static const PyGetSetDef _PyGISourceSymbol_getsets[] = {
/* int ref_count; */
{ "type", (getter)symbol_get_type, NULL, NULL},
{ "ident", (getter)symbol_get_ident, NULL, NULL},
{ "base_type", (getter)symbol_get_base_type, NULL, NULL},
/* gboolean const_int_set; */
- { "const_int", (getter)symbol_get_const_int, NULL, NULL},
- { "const_string", (getter)symbol_get_const_string, NULL, NULL},
- /* GSList *directives; */
+ { "const_int", (getter)symbol_get_const_int, NULL, NULL},
+ /* gboolean const_double_set; */
+ { "const_double", (getter)symbol_get_const_double, NULL, NULL},
+ { "const_string", (getter)symbol_get_const_string, NULL, NULL},
+ { "source_filename", (getter)symbol_get_source_filename, NULL, NULL},
+ { "line", (getter)symbol_get_line, NULL, NULL},
{ 0 }
};
/* Type */
+static PyObject *
+pygi_source_type_new (GISourceType *type)
+{
+ PyGISourceType *self;
+
+ if (type == NULL)
+ {
+ Py_INCREF (Py_None);
+ return Py_None;
+ }
+
+ self = (PyGISourceType *)PyObject_New (PyGISourceType,
+ &PyGISourceType_Type);
+ self->type = type;
+ return (PyObject*)self;
+}
+
static PyObject *
type_get_type (PyGISourceType *self,
void *context)
type_get_base_type (PyGISourceType *self,
void *context)
{
- PyGISourceType *item;
- item = (PyGISourceType *)PyObject_New (PyGISourceType,
- &PyGISourceType_Type);
- item->type = self->type->base_type;
- return (PyObject*)item;
+ return pygi_source_type_new (self->type->base_type);
}
static PyObject *
type_get_child_list (PyGISourceType *self,
void *context)
{
- GList *l, *symbols;
+ GList *l;
PyObject *list;
int i = 0;
for (l = self->type->child_list; l; l = l->next)
{
- PyGISourceSymbol *item;
- item = (PyGISourceSymbol *)PyObject_New (PyGISourceSymbol,
- &PyGISourceSymbol_Type);
- item->symbol = l->data;
- PyList_SetItem (list, i++, (PyObject*)item);
+ PyObject *item = pygi_source_symbol_new (l->data);
+ PyList_SetItem (list, i++, item);
Py_INCREF (item);
}
return list;
}
+static PyObject *
+type_get_is_bitfield (PyGISourceType *self,
+ void *context)
+{
+ return PyInt_FromLong (self->type->is_bitfield);
+}
+
static const PyGetSetDef _PyGISourceType_getsets[] = {
{ "type", (getter)type_get_type, NULL, NULL},
{ "storage_class_specifier", (getter)type_get_storage_class_specifier, NULL, NULL},
{ "name", (getter)type_get_name, NULL, NULL},
{ "base_type", (getter)type_get_base_type, NULL, NULL},
{ "child_list", (getter)type_get_child_list, NULL, NULL},
+ { "is_bitfield", (getter)type_get_is_bitfield, NULL, NULL},
{ 0 }
};
return 0;
}
+static PyObject *
+pygi_source_scanner_append_filename (PyGISourceScanner *self,
+ PyObject *args)
+{
+ char *filename;
+
+ if (!PyArg_ParseTuple (args, "s:SourceScanner.append_filename", &filename))
+ return NULL;
+
+ self->scanner->filenames = g_list_append (self->scanner->filenames,
+ g_realpath (filename));
+
+ Py_INCREF (Py_None);
+ return Py_None;
+}
+
+static PyObject *
+pygi_source_scanner_parse_macros (PyGISourceScanner *self,
+ PyObject *args)
+{
+ GList *filenames;
+ int i;
+ PyObject *list;
+
+ list = PyTuple_GET_ITEM (args, 0);
+
+ if (!PyList_Check (list))
+ {
+ PyErr_SetString (PyExc_RuntimeError, "parse macro takes a list of filenames");
+ return NULL;
+ }
+
+ filenames = NULL;
+ for (i = 0; i < PyList_Size (list); ++i)
+ {
+ PyObject *obj;
+ char *filename;
+
+ obj = PyList_GetItem (list, i);
+ filename = PyString_AsString (obj);
+
+ filenames = g_list_append (filenames, filename);
+ }
+
+ gi_source_scanner_parse_macros (self->scanner, filenames);
+ g_list_free (filenames);
+
+ Py_INCREF (Py_None);
+ return Py_None;
+}
+
static PyObject *
pygi_source_scanner_parse_file (PyGISourceScanner *self,
PyObject *args)
{
int fd;
- char *filename;
FILE *fp;
- if (!PyArg_ParseTuple (args, "is:SourceScanner.__init__", &fd, &filename))
+ if (!PyArg_ParseTuple (args, "i:SourceScanner.parse_file", &fd))
return NULL;
+#ifdef _WIN32
+ /* The file descriptor passed to us is from the C library Python
+ * uses. That is msvcr71.dll at least for Python 2.5. This code, at
+ * least if compiled with mingw, uses msvcrt.dll, so we cannot use
+ * the file descriptor directly. So perform appropriate magic.
+ */
+ {
+ HMODULE msvcr71;
+ int (*p__get_osfhandle) (int);
+ HANDLE handle;
+
+ msvcr71 = GetModuleHandle ("msvcr71.dll");
+ if (!msvcr71)
+ {
+ g_print ("No msvcr71.dll loaded.\n");
+ return NULL;
+ }
+
+ p__get_osfhandle = GetProcAddress (msvcr71, "_get_osfhandle");
+ if (!p__get_osfhandle)
+ {
+ g_print ("No _get_osfhandle found in msvcr71.dll.\n");
+ return NULL;
+ }
+
+ handle = p__get_osfhandle (fd);
+ if (!p__get_osfhandle)
+ {
+ g_print ("Could not get OS handle from msvcr71 fd.\n");
+ return NULL;
+ }
+
+ fd = _open_osfhandle (handle, _O_RDONLY);
+ if (fd == -1)
+ {
+ g_print ("Could not open C fd from OS handle.\n");
+ return NULL;
+ }
+ }
+#endif
+
fp = fdopen (fd, "r");
if (!fp)
{
- PyErr_SetFromErrnoWithFilename (PyExc_OSError, filename);
+ PyErr_SetFromErrno (PyExc_OSError);
return NULL;
}
- self->scanner->filenames =
- g_list_append (self->scanner->filenames, g_strdup (filename));
- self->scanner->current_filename = g_strdup (filename);
-
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;
+
+ self->scanner->current_filename = g_strdup (filename);
+ 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));
Py_INCREF (Py_None);
return Py_None;
for (l = symbols; l; l = l->next)
{
- PyGISourceSymbol *item;
- item = (PyGISourceSymbol *)PyObject_New (PyGISourceSymbol,
- &PyGISourceSymbol_Type);
- item->symbol = l->data;
- PyList_SetItem (list, i++, (PyObject*)item);
+ PyObject *item = pygi_source_symbol_new (l->data);
+ PyList_SetItem (list, i++, item);
+ Py_INCREF (item);
+ }
+
+ Py_INCREF (list);
+ return list;
+}
+
+static PyObject *
+pygi_source_scanner_get_comments (PyGISourceScanner *self)
+{
+ GSList *l, *comments;
+ PyObject *list;
+ int i = 0;
+
+ comments = gi_source_scanner_get_comments (self->scanner);
+ list = PyList_New (g_slist_length (comments));
+
+ for (l = comments; l; l = l->next)
+ {
+ PyObject *item = PyString_FromString (l->data);
+ PyList_SetItem (list, i++, item);
Py_INCREF (item);
}
}
static const PyMethodDef _PyGISourceScanner_methods[] = {
+ { "get_comments", (PyCFunction) pygi_source_scanner_get_comments, METH_NOARGS },
{ "get_symbols", (PyCFunction) pygi_source_scanner_get_symbols, METH_NOARGS },
+ { "append_filename", (PyCFunction) pygi_source_scanner_append_filename, METH_VARARGS },
{ "parse_file", (PyCFunction) pygi_source_scanner_parse_file, METH_VARARGS },
+ { "parse_macros", (PyCFunction) pygi_source_scanner_parse_macros, 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 }
};
+static int calc_attrs_length(PyObject *attributes, int indent,
+ int self_indent)
+{
+ int attr_length = 0;
+ int i;
+
+ if (indent == -1)
+ return -1;
+
+ for (i = 0; i < PyList_Size (attributes); ++i)
+ {
+ PyObject *tuple;
+ char *attr, *value;
+ char *escaped;
+
+ tuple = PyList_GetItem (attributes, i);
+ if (PyTuple_GetItem(tuple, 1) == Py_None)
+ continue;
+
+ if (!PyArg_ParseTuple(tuple, "ss", &attr, &value))
+ return -1;
+
+ escaped = g_markup_escape_text (value, -1);
+ attr_length += 2 + strlen(attr) + strlen(escaped) + 2;
+ g_free(escaped);
+ }
+
+ return attr_length + indent + self_indent;
+}
+
+/* Hall of shame, wasted time debugging the code below
+ * 20min - Johan 2009-02-19
+ */
+static PyObject *
+pygi_collect_attributes (PyObject *self,
+ PyObject *args)
+{
+ char *tag_name;
+ PyObject *attributes;
+ int indent, indent_len, i, j, self_indent;
+ char *indent_char;
+ gboolean first;
+ GString *attr_value;
+ int len;
+
+ if (!PyArg_ParseTuple(args, "sO!isi",
+ &tag_name, &PyList_Type, &attributes,
+ &self_indent, &indent_char,
+ &indent))
+ return NULL;
+
+ if (attributes == Py_None || !PyList_Size(attributes))
+ return PyString_FromString("");
+
+ len = calc_attrs_length(attributes, indent, self_indent);
+ if (len < 0)
+ return NULL;
+ if (len > 79)
+ indent_len = self_indent + strlen(tag_name) + 1;
+ else
+ indent_len = 0;
+
+ first = TRUE;
+ attr_value = g_string_new ("");
+
+ for (i = 0; i < PyList_Size (attributes); ++i)
+ {
+ PyObject *tuple;
+ char *attr, *value, *escaped;
+
+ tuple = PyList_GetItem (attributes, i);
+
+ if (!PyTuple_Check (tuple))
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "attribute item must be a tuple");
+ return NULL;
+ }
+
+ if (!PyTuple_Size (tuple) == 2)
+ {
+ PyErr_SetString(PyExc_IndexError,
+ "attribute item must be a tuple of length 2");
+ return NULL;
+ }
+
+ if (PyTuple_GetItem(tuple, 1) == Py_None)
+ continue;
+
+ /* this leaks, but we exit after, so */
+ if (!PyArg_ParseTuple(tuple, "ss", &attr, &value))
+ return NULL;
+
+ if (indent_len && !first)
+ {
+ g_string_append_c (attr_value, '\n');
+ for (j = 0; j < indent_len; j++)
+ g_string_append_c (attr_value, ' ');
+ }
+ g_string_append_c (attr_value, ' ');
+ g_string_append (attr_value, attr);
+ g_string_append_c (attr_value, '=');
+ g_string_append_c (attr_value, '\"');
+ escaped = g_markup_escape_text (value, -1);
+ g_string_append (attr_value, escaped);
+ g_string_append_c (attr_value, '\"');
+ if (first)
+ first = FALSE;
+ }
+
+ return PyString_FromString (g_string_free (attr_value, FALSE));
+}
+
/* Module */
static const PyMethodDef pyscanner_functions[] = {
+ { "collect_attributes",
+ (PyCFunction) pygi_collect_attributes, METH_VARARGS },
{ NULL, NULL, 0, NULL }
};