1 /* GObject introspection: scanner
3 * Copyright (C) 2007-2008 Jürg Billeter
4 * Copyright (C) 2007 Johan Dahlin
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
22 * Jürg Billeter <j@bitron.ch>
31 #include <glib/gstdio.h>
32 #include <glib-object.h>
36 #include "gidlparser.h"
37 #include "gidlmodule.h"
39 #include "gidlwriter.h"
40 #include "grealpath.h"
43 #include <sys/wait.h> /* waitpid */
47 typedef GType (*TypeFunction
) (void);
49 static void g_igenerator_parse_macros (GIGenerator
* igenerator
);
52 g_igenerator_new (const gchar
*namespace,
53 const gchar
*shared_library
)
55 GIGenerator
*igenerator
= g_new0 (GIGenerator
, 1);
56 igenerator
->namespace = g_strdup (namespace);
57 igenerator
->shared_library
= g_strdup (shared_library
);
58 igenerator
->lower_case_namespace
=
59 g_ascii_strdown (igenerator
->namespace, -1);
60 igenerator
->module
= g_idl_module_new (namespace, shared_library
);
62 igenerator
->typedef_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
63 igenerator
->struct_or_union_or_enum_table
=
64 g_hash_table_new (g_str_hash
, g_str_equal
);
66 igenerator
->type_map
= g_hash_table_new (g_str_hash
, g_str_equal
);
67 igenerator
->type_by_lower_case_prefix
=
68 g_hash_table_new (g_str_hash
, g_str_equal
);
69 igenerator
->symbols
= g_hash_table_new (g_str_hash
, g_str_equal
);
75 g_igenerator_free (GIGenerator
*generator
)
77 g_free (generator
->namespace);
78 g_free (generator
->shared_library
);
79 g_free (generator
->lower_case_namespace
);
81 g_idl_module_free (generator
->module
);
83 g_hash_table_destroy (generator
->typedef_table
);
84 g_hash_table_destroy (generator
->struct_or_union_or_enum_table
);
85 g_hash_table_destroy (generator
->type_map
);
86 g_hash_table_destroy (generator
->type_by_lower_case_prefix
);
87 g_hash_table_destroy (generator
->symbols
);
88 g_list_foreach (generator
->filenames
, (GFunc
)g_free
, NULL
);
89 g_list_free (generator
->filenames
);
91 g_list_foreach (generator
->symbol_list
, (GFunc
)csymbol_free
, NULL
);
92 g_list_free (generator
->symbol_list
);
98 create_node_from_gtype (GType type_id
)
103 node
= (GIdlNodeType
*) g_idl_node_new (G_IDL_NODE_TYPE
);
105 fundamental
= g_type_fundamental (type_id
);
109 node
->unparsed
= g_strdup ("char*");
111 case G_TYPE_INTERFACE
:
114 node
->unparsed
= g_strdup_printf ("%s*", g_type_name (type_id
));
117 node
->unparsed
= g_strdup ("GParamSpec*");
120 if (fundamental
== G_TYPE_STRV
)
121 node
->unparsed
= g_strdup ("char*[]");
123 node
->unparsed
= g_strdup (g_type_name (type_id
));
130 static GIdlNodeType
*
131 create_node_from_ctype (CType
* ctype
)
135 node
= (GIdlNodeType
*) g_idl_node_new (G_IDL_NODE_TYPE
);
140 node
->unparsed
= g_strdup ("void");
142 case CTYPE_BASIC_TYPE
:
143 node
->unparsed
= g_strdup (ctype
->name
);
146 node
->unparsed
= g_strdup (ctype
->name
);
149 if (ctype
->name
== NULL
)
150 /* anonymous struct */
151 node
->unparsed
= g_strdup ("gpointer");
153 node
->unparsed
= g_strdup_printf ("struct %s", ctype
->name
);
156 if (ctype
->name
== NULL
)
157 /* anonymous union */
158 node
->unparsed
= g_strdup ("gpointer");
160 node
->unparsed
= g_strdup_printf ("union %s", ctype
->name
);
163 if (ctype
->name
== NULL
)
165 node
->unparsed
= g_strdup ("gint");
167 node
->unparsed
= g_strdup_printf ("enum %s", ctype
->name
);
170 if (ctype
->base_type
->type
== CTYPE_FUNCTION
)
171 /* anonymous function pointer */
172 node
->unparsed
= g_strdup ("GCallback");
175 GIdlNodeType
*gibasetype
= create_node_from_ctype (ctype
->base_type
);
176 node
->unparsed
= g_strdup_printf ("%s*", gibasetype
->unparsed
);
181 GIdlNodeType
*gibasetype
= create_node_from_ctype (ctype
->base_type
);
182 node
->unparsed
= g_strdup_printf ("%s[]", gibasetype
->unparsed
);
186 node
->unparsed
= g_strdup ("unknown");
194 str_replace (const char *str
, const char *needle
, const char *replacement
)
196 char **strings
= g_strsplit (str
, needle
, 0);
197 char *result
= g_strjoinv (replacement
, strings
);
198 g_strfreev (strings
);
203 g_igenerator_process_properties (GIGenerator
* igenerator
,
204 GIdlNodeInterface
* node
, GType type_id
)
208 GParamSpec
**properties
;
210 if (node
->node
.type
== G_IDL_NODE_OBJECT
)
212 GObjectClass
*type_class
= g_type_class_ref (type_id
);
213 properties
= g_object_class_list_properties (type_class
, &n_properties
);
215 else if (node
->node
.type
== G_IDL_NODE_INTERFACE
)
217 GTypeInterface
*iface
= g_type_default_interface_ref (type_id
);
218 properties
= g_object_interface_list_properties (iface
, &n_properties
);
222 g_assert_not_reached ();
225 for (i
= 0; i
< n_properties
; i
++)
227 GIdlNodeProperty
*giprop
;
229 /* ignore inherited properties */
230 if (properties
[i
]->owner_type
!= type_id
)
234 giprop
= (GIdlNodeProperty
*) g_idl_node_new (G_IDL_NODE_PROPERTY
);
235 giprop
->node
.name
= properties
[i
]->name
;
237 g_list_insert_sorted (node
->members
, giprop
,
238 (GCompareFunc
) g_idl_node_cmp
);
239 giprop
->type
= create_node_from_gtype (properties
[i
]->value_type
);
240 giprop
->readable
= (properties
[i
]->flags
& G_PARAM_READABLE
) != 0;
241 giprop
->writable
= (properties
[i
]->flags
& G_PARAM_WRITABLE
) != 0;
242 giprop
->construct
= (properties
[i
]->flags
& G_PARAM_CONSTRUCT
) != 0;
243 giprop
->construct_only
=
244 (properties
[i
]->flags
& G_PARAM_CONSTRUCT_ONLY
) != 0;
249 g_igenerator_process_signals (GIGenerator
* igenerator
,
250 GIdlNodeInterface
* node
, GType type_id
)
254 guint
*signal_ids
= g_signal_list_ids (type_id
, &n_signal_ids
);
256 for (i
= 0; i
< n_signal_ids
; i
++)
258 GSignalQuery signal_query
;
259 GIdlNodeSignal
*gisig
;
260 GIdlNodeParam
*giparam
;
262 g_signal_query (signal_ids
[i
], &signal_query
);
263 gisig
= (GIdlNodeSignal
*) g_idl_node_new (G_IDL_NODE_SIGNAL
);
264 gisig
->node
.name
= g_strdup (signal_query
.signal_name
);
266 g_list_insert_sorted (node
->members
, gisig
,
267 (GCompareFunc
) g_idl_node_cmp
);
270 (signal_query
.signal_flags
& G_SIGNAL_RUN_FIRST
) != 0;
271 gisig
->run_last
= (signal_query
.signal_flags
& G_SIGNAL_RUN_LAST
) != 0;
273 (signal_query
.signal_flags
& G_SIGNAL_RUN_CLEANUP
) != 0;
275 /* add sender parameter */
276 giparam
= (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
277 gisig
->parameters
= g_list_append (gisig
->parameters
, giparam
);
278 giparam
->node
.name
= g_strdup ("object");
279 giparam
->type
= create_node_from_gtype (type_id
);
281 for (j
= 0; j
< signal_query
.n_params
; j
++)
283 giparam
= (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
284 gisig
->parameters
= g_list_append (gisig
->parameters
, giparam
);
285 giparam
->node
.name
= g_strdup_printf ("p%d", j
);
286 giparam
->type
= create_node_from_gtype (signal_query
.param_types
[j
]);
288 gisig
->result
= (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
289 gisig
->result
->type
= create_node_from_gtype (signal_query
.return_type
);
294 lookup_symbol (GIGenerator
*igenerator
, const gchar
*typename
)
297 g_hash_table_lookup (igenerator
->symbols
, typename
);
301 g_printerr ("Unknown symbol: %s\n", typename
);
309 g_igenerator_create_object (GIGenerator
*igenerator
,
310 const char *symbol_name
,
312 char *lower_case_prefix
)
315 char *alt_lower_case_prefix
;
316 GIdlNodeInterface
*node
;
317 guint n_type_interfaces
;
318 GType
*type_interfaces
;
321 node
= (GIdlNodeInterface
*) g_idl_node_new (G_IDL_NODE_OBJECT
);
322 node
->node
.name
= g_strdup (g_type_name (type_id
));
323 igenerator
->module
->entries
=
324 g_list_insert_sorted (igenerator
->module
->entries
, node
,
325 (GCompareFunc
) g_idl_node_cmp
);
326 g_hash_table_insert (igenerator
->type_map
, node
->node
.name
,
328 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
329 lower_case_prefix
, node
);
330 alt_lower_case_prefix
= g_ascii_strdown (node
->node
.name
, -1);
332 if (strcmp (alt_lower_case_prefix
, lower_case_prefix
) != 0)
334 /* alternative prefix sometimes necessary, for example
337 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
338 alt_lower_case_prefix
, node
);
342 g_free (alt_lower_case_prefix
);
345 node
->gtype_name
= node
->node
.name
;
346 node
->gtype_init
= g_strdup (symbol_name
);
347 node
->parent
= g_strdup (lookup_symbol (igenerator
,
348 g_type_name (g_type_parent (type_id
))));
350 type_interfaces
= g_type_interfaces (type_id
, &n_type_interfaces
);
351 for (i
= 0; i
< n_type_interfaces
; i
++)
354 g_strdup (g_type_name (type_interfaces
[i
]));
355 /* workaround for AtkImplementorIface */
356 if (g_str_has_suffix (iface_name
, "Iface"))
358 iface_name
[strlen (iface_name
) - strlen ("Iface")] =
362 g_list_append (node
->interfaces
, iface_name
);
365 g_hash_table_insert (igenerator
->symbols
,
366 g_strdup (node
->gtype_name
),
367 /* FIXME: Strip igenerator->namespace */
368 g_strdup (node
->node
.name
));
370 g_igenerator_process_properties (igenerator
, node
, type_id
);
371 g_igenerator_process_signals (igenerator
, node
, type_id
);
375 g_igenerator_create_interface (GIGenerator
*igenerator
,
376 const char *symbol_name
,
378 char *lower_case_prefix
)
381 GIdlNodeInterface
*node
;
382 gboolean is_gobject
= FALSE
;
383 guint n_iface_prereqs
;
384 GType
*iface_prereqs
;
387 node
= (GIdlNodeInterface
*) g_idl_node_new (G_IDL_NODE_INTERFACE
);
388 node
->node
.name
= g_strdup (g_type_name (type_id
));
390 /* workaround for AtkImplementorIface */
391 if (g_str_has_suffix (node
->node
.name
, "Iface"))
393 node
->node
.name
[strlen (node
->node
.name
) -
394 strlen ("Iface")] = '\0';
396 igenerator
->module
->entries
=
397 g_list_insert_sorted (igenerator
->module
->entries
, node
,
398 (GCompareFunc
) g_idl_node_cmp
);
399 g_hash_table_insert (igenerator
->type_map
, node
->node
.name
,
401 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
402 lower_case_prefix
, node
);
403 node
->gtype_name
= node
->node
.name
;
404 node
->gtype_init
= g_strdup (symbol_name
);
407 g_type_interface_prerequisites (type_id
, &n_iface_prereqs
);
409 for (i
= 0; i
< n_iface_prereqs
; i
++)
411 if (g_type_fundamental (iface_prereqs
[i
]) == G_TYPE_OBJECT
)
415 node
->prerequisites
=
416 g_list_append (node
->prerequisites
,
417 g_strdup (g_type_name (iface_prereqs
[i
])));
421 g_igenerator_process_properties (igenerator
, node
, type_id
);
423 g_type_default_interface_ref (type_id
);
425 g_igenerator_process_signals (igenerator
, node
, type_id
);
429 g_igenerator_create_boxed (GIGenerator
*igenerator
,
430 const char *symbol_name
,
432 char *lower_case_prefix
)
434 GIdlNodeBoxed
*node
=
435 (GIdlNodeBoxed
*) g_idl_node_new (G_IDL_NODE_BOXED
);
436 node
->node
.name
= g_strdup (g_type_name (type_id
));
437 igenerator
->module
->entries
=
438 g_list_insert_sorted (igenerator
->module
->entries
, node
,
439 (GCompareFunc
) g_idl_node_cmp
);
440 g_hash_table_insert (igenerator
->type_map
, node
->node
.name
,
442 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
443 lower_case_prefix
, node
);
444 node
->gtype_name
= node
->node
.name
;
445 node
->gtype_init
= g_strdup (symbol_name
);
449 g_igenerator_create_enum (GIGenerator
*igenerator
,
450 const char *symbol_name
,
452 char *lower_case_prefix
)
456 GEnumClass
*type_class
;
458 node
= (GIdlNodeEnum
*) g_idl_node_new (G_IDL_NODE_ENUM
);
459 node
->node
.name
= g_strdup (g_type_name (type_id
));
460 igenerator
->module
->entries
=
461 g_list_insert_sorted (igenerator
->module
->entries
, node
,
462 (GCompareFunc
) g_idl_node_cmp
);
463 g_hash_table_insert (igenerator
->type_map
, node
->node
.name
,
465 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
466 lower_case_prefix
, node
);
467 node
->gtype_name
= node
->node
.name
;
468 node
->gtype_init
= g_strdup (symbol_name
);
470 type_class
= g_type_class_ref (type_id
);
472 for (i
= 0; i
< type_class
->n_values
; i
++)
474 GIdlNodeValue
*gival
=
475 (GIdlNodeValue
*) g_idl_node_new (G_IDL_NODE_VALUE
);
476 node
->values
= g_list_append (node
->values
, gival
);
478 g_strdup (type_class
->values
[i
].value_name
);
479 gival
->value
= type_class
->values
[i
].value
;
484 g_igenerator_create_flags (GIGenerator
*igenerator
,
485 const char *symbol_name
,
487 char *lower_case_prefix
)
490 GFlagsClass
*type_class
;
493 node
= (GIdlNodeEnum
*) g_idl_node_new (G_IDL_NODE_FLAGS
);
494 node
->node
.name
= g_strdup (g_type_name (type_id
));
495 igenerator
->module
->entries
=
496 g_list_insert_sorted (igenerator
->module
->entries
, node
,
497 (GCompareFunc
) g_idl_node_cmp
);
498 g_hash_table_insert (igenerator
->type_map
, node
->node
.name
,
500 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
501 lower_case_prefix
, node
);
502 node
->gtype_name
= node
->node
.name
;
503 node
->gtype_init
= g_strdup (symbol_name
);
505 type_class
= g_type_class_ref (type_id
);
507 for (i
= 0; i
< type_class
->n_values
; i
++)
509 GIdlNodeValue
*gival
=
510 (GIdlNodeValue
*) g_idl_node_new (G_IDL_NODE_VALUE
);
511 node
->values
= g_list_append (node
->values
, gival
);
513 g_strdup (type_class
->values
[i
].value_name
);
514 gival
->value
= type_class
->values
[i
].value
;
519 g_igenerator_process_module_symbol (GIGenerator
*igenerator
,
521 const gchar
*symbol_name
)
523 TypeFunction type_fun
;
525 GType type_fundamental
;
526 char *lower_case_prefix
;
528 /* ignore already processed functions */
529 if (symbol_name
== NULL
)
532 if (!g_module_symbol (module
,
534 (gpointer
*) & type_fun
))
537 type_id
= type_fun ();
538 type_fundamental
= g_type_fundamental (type_id
);
540 str_replace (g_strndup
542 strlen (symbol_name
) - strlen ("_get_type")),
545 switch (type_fundamental
)
548 g_igenerator_create_object (igenerator
, symbol_name
, type_id
,
551 case G_TYPE_INTERFACE
:
552 g_igenerator_create_interface (igenerator
, symbol_name
, type_id
,
556 g_igenerator_create_boxed (igenerator
, symbol_name
, type_id
,
560 g_igenerator_create_enum (igenerator
, symbol_name
, type_id
,
564 g_igenerator_create_flags (igenerator
, symbol_name
, type_id
,
574 g_igenerator_process_module (GIGenerator
* igenerator
,
575 const gchar
*filename
)
580 module
= g_module_open (filename
,
581 G_MODULE_BIND_LAZY
| G_MODULE_BIND_LOCAL
);
585 g_critical ("Couldn't open module: %s", filename
);
589 for (l
= igenerator
->get_type_symbols
; l
!= NULL
; l
= l
->next
)
591 if (g_igenerator_process_module_symbol (igenerator
,
592 module
, (const char *)l
->data
))
593 /* symbol found, ignore in future iterations */
599 g_igenerator_process_function_symbol (GIGenerator
* igenerator
, CSymbol
* sym
)
601 GIdlNodeFunction
*func
;
602 char *last_underscore
;
607 func
= (GIdlNodeFunction
*) g_idl_node_new (G_IDL_NODE_FUNCTION
);
609 /* check whether this is a type method */
610 last_underscore
= strrchr (sym
->ident
, '_');
612 while (last_underscore
!= NULL
)
617 prefix
= g_strndup (sym
->ident
, last_underscore
- sym
->ident
);
618 prefix
= str_replace (prefix
, "_", "");
620 node
= g_hash_table_lookup (igenerator
->type_by_lower_case_prefix
,
624 func
->node
.name
= g_strdup (last_underscore
+ 1);
626 /* ignore get_type functions in registered types */
627 if (strcmp (func
->node
.name
, "get_type") == 0)
630 if ((node
->type
== G_IDL_NODE_OBJECT
||
631 node
->type
== G_IDL_NODE_BOXED
) &&
632 g_str_has_prefix (func
->node
.name
, "new"))
633 func
->is_constructor
= TRUE
;
635 func
->is_method
= TRUE
;
636 if (g_idl_node_can_have_member (node
))
638 g_idl_node_add_member (node
, func
);
643 /* reset function attributes */
644 g_free (func
->node
.name
);
645 func
->node
.name
= NULL
;
646 func
->is_constructor
= FALSE
;
647 func
->is_method
= FALSE
;
650 else if (strcmp (igenerator
->lower_case_namespace
, prefix
) == 0)
652 func
->node
.name
= g_strdup (last_underscore
+ 1);
653 igenerator
->module
->entries
=
654 g_list_insert_sorted (igenerator
->module
->entries
, func
,
655 (GCompareFunc
) g_idl_node_cmp
);
659 g_utf8_strrchr (sym
->ident
, last_underscore
- sym
->ident
, '_');
662 /* create a namespace function if no prefix matches */
663 if (func
->node
.name
== NULL
)
665 func
->node
.name
= sym
->ident
;
666 func
->is_constructor
= FALSE
;
667 func
->is_method
= FALSE
;
668 igenerator
->module
->entries
=
669 g_list_insert_sorted (igenerator
->module
->entries
, func
,
670 (GCompareFunc
) g_idl_node_cmp
);
673 func
->symbol
= sym
->ident
;
674 func
->result
= (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
675 func
->result
->type
= create_node_from_ctype (sym
->base_type
->base_type
);
677 for (param_l
= sym
->base_type
->child_list
, i
= 1; param_l
!= NULL
;
678 param_l
= param_l
->next
, i
++)
680 CSymbol
*param_sym
= param_l
->data
;
681 GIdlNodeParam
*param
;
683 param
= (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
684 param
->type
= create_node_from_ctype (param_sym
->base_type
);
686 if (param_sym
->ident
== NULL
)
687 param
->node
.name
= g_strdup_printf ("p%d", i
);
689 param
->node
.name
= param_sym
->ident
;
691 func
->parameters
= g_list_append (func
->parameters
, param
);
694 for (l
= sym
->directives
; l
; l
= l
->next
)
696 CDirective
*directive
= (CDirective
*)l
->data
;
698 if (!strcmp (directive
->name
, "deprecated"))
699 func
->deprecated
= TRUE
;
701 g_printerr ("Unknown function directive: %s\n",
707 g_igenerator_process_unregistered_struct_typedef (GIGenerator
* igenerator
,
711 GIdlNodeStruct
*node
=
712 (GIdlNodeStruct
*) g_idl_node_new (G_IDL_NODE_STRUCT
);
714 char *lower_case_prefix
;
716 node
->node
.name
= sym
->ident
;
717 igenerator
->module
->entries
=
718 g_list_insert_sorted (igenerator
->module
->entries
, node
,
719 (GCompareFunc
) g_idl_node_cmp
);
720 lower_case_prefix
= g_ascii_strdown (sym
->ident
, -1);
721 g_hash_table_insert (igenerator
->type_map
, sym
->ident
, node
);
722 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
723 lower_case_prefix
, node
);
725 for (member_l
= struct_type
->child_list
; member_l
!= NULL
;
726 member_l
= member_l
->next
)
728 CSymbol
*member
= member_l
->data
;
729 GIdlNodeField
*gifield
=
730 (GIdlNodeField
*) g_idl_node_new (G_IDL_NODE_FIELD
);
732 node
->members
= g_list_append (node
->members
, gifield
);
733 gifield
->node
.name
= member
->ident
;
734 gifield
->type
= create_node_from_ctype (member
->base_type
);
739 g_igenerator_process_struct_typedef (GIGenerator
* igenerator
, CSymbol
* sym
)
741 CType
*struct_type
= sym
->base_type
;
742 gboolean opaque_type
= FALSE
;
745 if (struct_type
->child_list
== NULL
)
747 CSymbol
*struct_symbol
;
748 g_assert (struct_type
->name
!= NULL
);
750 g_hash_table_lookup (igenerator
->struct_or_union_or_enum_table
,
752 if (struct_symbol
!= NULL
)
754 struct_type
= struct_symbol
->base_type
;
758 if (struct_type
->child_list
== NULL
)
763 type
= g_hash_table_lookup (igenerator
->type_map
, sym
->ident
);
766 /* struct of a GTypeInstance */
768 && (type
->type
== G_IDL_NODE_OBJECT
769 || type
->type
== G_IDL_NODE_INTERFACE
))
771 GIdlNodeInterface
*node
= (GIdlNodeInterface
*) type
;
773 /* ignore first field => parent */
774 for (member_l
= struct_type
->child_list
->next
; member_l
!= NULL
;
775 member_l
= member_l
->next
)
777 CSymbol
*member
= member_l
->data
;
778 /* ignore private / reserved members */
779 if (member
->ident
[0] == '_'
780 || g_str_has_prefix (member
->ident
, "priv"))
784 GIdlNodeField
*gifield
=
785 (GIdlNodeField
*) g_idl_node_new (G_IDL_NODE_FIELD
);
786 node
->members
= g_list_append (node
->members
, gifield
);
787 gifield
->node
.name
= member
->ident
;
788 gifield
->type
= create_node_from_ctype (member
->base_type
);
791 else if (type
->type
== G_IDL_NODE_BOXED
)
793 GIdlNodeBoxed
*node
= (GIdlNodeBoxed
*) type
;
795 for (member_l
= struct_type
->child_list
; member_l
!= NULL
;
796 member_l
= member_l
->next
)
798 CSymbol
*member
= member_l
->data
;
799 GIdlNodeField
*gifield
=
800 (GIdlNodeField
*) g_idl_node_new (G_IDL_NODE_FIELD
);
801 node
->members
= g_list_append (node
->members
, gifield
);
802 gifield
->node
.name
= member
->ident
;
803 gifield
->type
= create_node_from_ctype (member
->base_type
);
807 else if (!opaque_type
808 && (g_str_has_suffix (sym
->ident
, "Class")
809 || g_str_has_suffix (sym
->ident
, "Iface")
810 || g_str_has_suffix (sym
->ident
, "Interface")))
814 GIdlNodeInterface
*node
;
816 if (g_str_has_suffix (sym
->ident
, "Interface"))
819 g_strndup (sym
->ident
,
820 strlen (sym
->ident
) - strlen ("Interface"));
825 g_strndup (sym
->ident
, strlen (sym
->ident
) - strlen ("Class"));
827 type
= g_hash_table_lookup (igenerator
->type_map
, base_name
);
829 || (type
->type
!= G_IDL_NODE_OBJECT
830 && type
->type
!= G_IDL_NODE_INTERFACE
))
832 g_igenerator_process_unregistered_struct_typedef (igenerator
, sym
,
836 node
= (GIdlNodeInterface
*) type
;
838 /* ignore first field => parent */
839 for (member_l
= struct_type
->child_list
->next
; member_l
!= NULL
;
840 member_l
= member_l
->next
)
842 CSymbol
*member
= member_l
->data
;
843 /* ignore private / reserved members */
844 if (member
->ident
[0] == '_')
848 if (member
->base_type
->type
== CTYPE_POINTER
849 && member
->base_type
->base_type
->type
== CTYPE_FUNCTION
)
851 /* ignore default handlers of signals */
852 gboolean found_signal
= FALSE
;
853 GList
*type_member_l
;
856 GIdlNodeVFunc
*givfunc
;
858 for (type_member_l
= node
->members
; type_member_l
!= NULL
;
859 type_member_l
= type_member_l
->next
)
861 GIdlNode
*type_member
= type_member_l
->data
;
862 char *normalized_name
=
863 str_replace (type_member
->name
, "-", "_");
864 if (type_member
->type
== G_IDL_NODE_SIGNAL
865 && strcmp (normalized_name
, member
->ident
) == 0)
867 GList
*vfunc_param_l
;
869 GIdlNodeSignal
*sig
= (GIdlNodeSignal
*) type_member
;
871 /* set signal parameter names */
873 member
->base_type
->base_type
->child_list
,
874 sig_param_l
= sig
->parameters
;
875 vfunc_param_l
!= NULL
&& sig_param_l
!= NULL
;
876 vfunc_param_l
= vfunc_param_l
->next
, sig_param_l
=
879 CSymbol
*vfunc_param
= vfunc_param_l
->data
;
880 GIdlNodeParam
*sig_param
= sig_param_l
->data
;
881 if (vfunc_param
->ident
!= NULL
)
883 g_free (sig_param
->node
.name
);
884 sig_param
->node
.name
=
885 g_strdup (vfunc_param
->ident
);
896 givfunc
= (GIdlNodeVFunc
*) g_idl_node_new (G_IDL_NODE_VFUNC
);
897 givfunc
->node
.name
= member
->ident
;
899 g_list_insert_sorted (node
->members
, givfunc
,
900 (GCompareFunc
) g_idl_node_cmp
);
902 (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
903 givfunc
->result
->type
=
904 create_node_from_ctype (member
->base_type
->base_type
->base_type
);
905 for (param_l
= member
->base_type
->base_type
->child_list
, i
= 1;
906 param_l
!= NULL
; param_l
= param_l
->next
, i
++)
908 CSymbol
*param_sym
= param_l
->data
;
909 GIdlNodeParam
*param
=
910 (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
911 if (param_sym
->ident
== NULL
)
913 param
->node
.name
= g_strdup_printf ("p%d", i
);
917 param
->node
.name
= param_sym
->ident
;
919 param
->type
= create_node_from_ctype (param_sym
->base_type
);
920 givfunc
->parameters
=
921 g_list_append (givfunc
->parameters
, param
);
926 else if (g_str_has_suffix (sym
->ident
, "Private"))
928 /* ignore private structs */
932 g_igenerator_process_unregistered_struct_typedef (igenerator
, sym
,
938 g_igenerator_process_union_typedef (GIGenerator
* igenerator
, CSymbol
* sym
)
940 CType
*union_type
= sym
->base_type
;
941 gboolean opaque_type
= FALSE
;
944 if (union_type
->child_list
== NULL
)
946 g_assert (union_type
->name
!= NULL
);
947 CSymbol
*union_symbol
=
948 g_hash_table_lookup (igenerator
->struct_or_union_or_enum_table
,
950 if (union_symbol
!= NULL
)
952 union_type
= union_symbol
->base_type
;
955 if (union_type
->child_list
== NULL
)
960 type
= g_hash_table_lookup (igenerator
->type_map
, sym
->ident
);
963 g_assert (type
->type
== G_IDL_NODE_BOXED
);
964 GIdlNodeBoxed
*node
= (GIdlNodeBoxed
*) type
;
966 for (member_l
= union_type
->child_list
; member_l
!= NULL
;
967 member_l
= member_l
->next
)
969 CSymbol
*member
= member_l
->data
;
970 GIdlNodeField
*gifield
=
971 (GIdlNodeField
*) g_idl_node_new (G_IDL_NODE_FIELD
);
972 node
->members
= g_list_append (node
->members
, gifield
);
973 gifield
->node
.name
= member
->ident
;
974 gifield
->type
= create_node_from_ctype (member
->base_type
);
979 GIdlNodeUnion
*node
=
980 (GIdlNodeUnion
*) g_idl_node_new (G_IDL_NODE_UNION
);
981 char *lower_case_prefix
;
984 node
->node
.name
= sym
->ident
;
985 igenerator
->module
->entries
=
986 g_list_insert_sorted (igenerator
->module
->entries
, node
,
987 (GCompareFunc
) g_idl_node_cmp
);
988 lower_case_prefix
= g_ascii_strdown (sym
->ident
, -1);
989 g_hash_table_insert (igenerator
->type_map
, sym
->ident
, node
);
990 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
991 lower_case_prefix
, node
);
993 node
->node
.name
= sym
->ident
;
994 for (member_l
= union_type
->child_list
; member_l
!= NULL
;
995 member_l
= member_l
->next
)
997 CSymbol
*member
= member_l
->data
;
998 GIdlNodeField
*gifield
=
999 (GIdlNodeField
*) g_idl_node_new (G_IDL_NODE_FIELD
);
1000 node
->members
= g_list_append (node
->members
, gifield
);
1001 gifield
->node
.name
= member
->ident
;
1002 gifield
->type
= create_node_from_ctype (member
->base_type
);
1008 g_igenerator_process_enum_typedef (GIGenerator
* igenerator
, CSymbol
* sym
)
1013 CSymbol
*enum_symbol
;
1015 enum_type
= sym
->base_type
;
1016 if (enum_type
->child_list
== NULL
)
1018 g_assert (enum_type
->name
!= NULL
);
1020 g_hash_table_lookup (igenerator
->struct_or_union_or_enum_table
,
1022 if (enum_symbol
!= NULL
)
1024 enum_type
= enum_symbol
->base_type
;
1027 if (enum_type
->child_list
== NULL
)
1033 node
= g_hash_table_lookup (igenerator
->type_map
, sym
->ident
);
1039 node
= (GIdlNodeEnum
*) g_idl_node_new (G_IDL_NODE_ENUM
);
1040 node
->node
.name
= sym
->ident
;
1041 igenerator
->module
->entries
=
1042 g_list_insert_sorted (igenerator
->module
->entries
, node
,
1043 (GCompareFunc
) g_idl_node_cmp
);
1045 for (member_l
= enum_type
->child_list
; member_l
!= NULL
;
1046 member_l
= member_l
->next
)
1048 CSymbol
*member
= member_l
->data
;
1049 GIdlNodeValue
*gival
=
1050 (GIdlNodeValue
*) g_idl_node_new (G_IDL_NODE_VALUE
);
1051 node
->values
= g_list_append (node
->values
, gival
);
1052 gival
->node
.name
= member
->ident
;
1053 gival
->value
= member
->const_int
;
1058 g_igenerator_process_function_typedef (GIGenerator
* igenerator
,
1064 /* handle callback types */
1065 GIdlNodeFunction
*gifunc
=
1066 (GIdlNodeFunction
*) g_idl_node_new (G_IDL_NODE_CALLBACK
);
1068 gifunc
->node
.name
= sym
->ident
;
1069 igenerator
->module
->entries
=
1070 g_list_insert_sorted (igenerator
->module
->entries
, gifunc
,
1071 (GCompareFunc
) g_idl_node_cmp
);
1073 gifunc
->symbol
= sym
->ident
;
1074 gifunc
->result
= (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
1075 gifunc
->result
->type
=
1076 create_node_from_ctype (sym
->base_type
->base_type
->base_type
);
1078 for (param_l
= sym
->base_type
->base_type
->child_list
, i
= 1;
1079 param_l
!= NULL
; param_l
= param_l
->next
, i
++)
1081 CSymbol
*param_sym
= param_l
->data
;
1082 GIdlNodeParam
*param
=
1083 (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
1084 if (param_sym
->ident
== NULL
)
1086 param
->node
.name
= g_strdup_printf ("p%d", i
);
1090 param
->node
.name
= param_sym
->ident
;
1092 param
->type
= create_node_from_ctype (param_sym
->base_type
);
1093 gifunc
->parameters
= g_list_append (gifunc
->parameters
, param
);
1098 g_igenerator_process_constant (GIGenerator
* igenerator
, CSymbol
* sym
)
1100 GIdlNodeConstant
*giconst
=
1101 (GIdlNodeConstant
*) g_idl_node_new (G_IDL_NODE_CONSTANT
);
1102 giconst
->node
.name
= sym
->ident
;
1103 igenerator
->module
->entries
=
1104 g_list_insert_sorted (igenerator
->module
->entries
, giconst
,
1105 (GCompareFunc
) g_idl_node_cmp
);
1107 giconst
->type
= (GIdlNodeType
*) g_idl_node_new (G_IDL_NODE_TYPE
);
1108 if (sym
->const_int_set
)
1110 giconst
->type
->unparsed
= g_strdup ("int");
1111 giconst
->value
= g_strdup_printf ("%d", sym
->const_int
);
1113 else if (sym
->const_string
!= NULL
)
1115 giconst
->type
->unparsed
= g_strdup ("char*");
1116 giconst
->value
= sym
->const_string
;
1121 g_igenerator_process_symbols (GIGenerator
* igenerator
)
1124 /* process type symbols first to ensure complete type hashtables */
1126 for (l
= igenerator
->symbol_list
; l
!= NULL
; l
= l
->next
)
1128 CSymbol
*sym
= l
->data
;
1129 if (sym
->ident
[0] == '_')
1131 /* ignore private / reserved symbols */
1134 if (sym
->type
== CSYMBOL_TYPE_TYPEDEF
)
1136 if (sym
->base_type
->type
== CTYPE_STRUCT
)
1138 g_igenerator_process_struct_typedef (igenerator
, sym
);
1140 else if (sym
->base_type
->type
== CTYPE_UNION
)
1142 g_igenerator_process_union_typedef (igenerator
, sym
);
1144 else if (sym
->base_type
->type
== CTYPE_ENUM
)
1146 g_igenerator_process_enum_typedef (igenerator
, sym
);
1148 else if (sym
->base_type
->type
== CTYPE_POINTER
1149 && sym
->base_type
->base_type
->type
== CTYPE_FUNCTION
)
1151 g_igenerator_process_function_typedef (igenerator
, sym
);
1155 GIdlNodeStruct
*node
=
1156 (GIdlNodeStruct
*) g_idl_node_new (G_IDL_NODE_STRUCT
);
1157 char *lower_case_prefix
;
1159 node
->node
.name
= sym
->ident
;
1160 igenerator
->module
->entries
=
1161 g_list_insert_sorted (igenerator
->module
->entries
, node
,
1162 (GCompareFunc
) g_idl_node_cmp
);
1163 lower_case_prefix
= g_ascii_strdown (sym
->ident
, -1);
1164 g_hash_table_insert (igenerator
->type_map
, sym
->ident
, node
);
1165 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
1166 lower_case_prefix
, node
);
1171 for (l
= igenerator
->symbol_list
; l
!= NULL
; l
= l
->next
)
1173 CSymbol
*sym
= l
->data
;
1174 if (sym
->ident
[0] == '_')
1176 /* ignore private / reserved symbols */
1179 if (sym
->type
== CSYMBOL_TYPE_FUNCTION
)
1181 g_igenerator_process_function_symbol (igenerator
, sym
);
1183 else if (sym
->type
== CSYMBOL_TYPE_CONST
)
1185 g_igenerator_process_constant (igenerator
, sym
);
1191 g_igenerator_add_symbol (GIGenerator
* igenerator
, CSymbol
* symbol
)
1195 /* only add symbols of main file */
1196 gboolean found_filename
= FALSE
;
1198 if (igenerator
->current_filename
)
1200 for (l
= igenerator
->filenames
; l
!= NULL
; l
= l
->next
)
1202 if (strcmp (l
->data
, igenerator
->current_filename
) == 0)
1204 found_filename
= TRUE
;
1210 symbol
->directives
= g_slist_reverse (igenerator
->directives
);
1211 igenerator
->directives
= NULL
;
1213 /* that's not very optimized ! */
1214 for (l
= igenerator
->symbol_list
; l
!= NULL
; l
= l
->next
)
1216 CSymbol
*other_symbol
= (CSymbol
*)l
->data
;
1217 if (g_str_equal (other_symbol
->ident
, symbol
->ident
)
1218 && other_symbol
->type
== symbol
->type
)
1220 g_printerr ("Dropping %s duplicate\n", symbol
->ident
);
1225 if (found_filename
|| igenerator
->macro_scan
)
1227 igenerator
->symbol_list
=
1228 g_list_prepend (igenerator
->symbol_list
, symbol
);
1231 if (symbol
->type
== CSYMBOL_TYPE_TYPEDEF
)
1234 g_hash_table_insert (igenerator
->typedef_table
, symbol
->ident
, symbol
);
1236 else if (symbol
->type
== CSYMBOL_TYPE_STRUCT
1237 || symbol
->type
== CSYMBOL_TYPE_UNION
1238 || symbol
->type
== CSYMBOL_TYPE_ENUM
)
1240 g_hash_table_insert (igenerator
->struct_or_union_or_enum_table
,
1241 symbol
->ident
, symbol
);
1246 g_igenerator_is_typedef (GIGenerator
* igenerator
, const char *name
)
1248 gboolean b
= g_hash_table_lookup (igenerator
->typedef_table
, name
) != NULL
;
1253 g_igenerator_generate (GIGenerator
* igenerator
,
1254 const gchar
* filename
,
1259 for (l
= igenerator
->symbol_list
; l
!= NULL
; l
= l
->next
)
1261 CSymbol
*sym
= l
->data
;
1262 if (sym
->type
== CSYMBOL_TYPE_FUNCTION
1263 && g_str_has_suffix (sym
->ident
, "_get_type"))
1265 if (sym
->base_type
->child_list
== NULL
)
1267 // ignore get_type functions with parameters
1268 igenerator
->get_type_symbols
=
1269 g_list_prepend (igenerator
->get_type_symbols
, sym
->ident
);
1274 /* ensure to initialize GObject */
1275 g_type_class_ref (G_TYPE_OBJECT
);
1277 for (l
= libraries
; l
; l
= l
->next
)
1278 g_igenerator_process_module (igenerator
, (const gchar
*)l
->data
);
1280 g_igenerator_process_symbols (igenerator
);
1282 g_idl_writer_save_file (igenerator
->module
, filename
);
1286 eat_hspace (FILE * f
)
1293 while (c
== ' ' || c
== '\t');
1298 eat_line (FILE * f
, int c
)
1300 while (c
!= EOF
&& c
!= '\n')
1307 if (c
== ' ' || c
== '\t')
1316 read_identifier (FILE * f
, int c
, char **identifier
)
1318 GString
*id
= g_string_new ("");
1319 while (isalnum (c
) || c
== '_')
1321 g_string_append_c (id
, c
);
1324 *identifier
= g_string_free (id
, FALSE
);
1329 g_igenerator_parse_macros (GIGenerator
* igenerator
)
1331 GError
*error
= NULL
;
1332 char *tmp_name
= NULL
;
1334 fdopen (g_file_open_tmp ("gen-introspect-XXXXXX.h", &tmp_name
, &error
),
1336 g_unlink (tmp_name
);
1339 for (l
= igenerator
->filenames
; l
!= NULL
; l
= l
->next
)
1341 FILE *f
= fopen (l
->data
, "r");
1344 GString
*define_line
;
1346 gboolean error_line
= FALSE
;
1347 int c
= eat_hspace (f
);
1353 c
= eat_line (f
, c
);
1358 /* print current location */
1359 str
= g_strescape (l
->data
, "");
1360 fprintf (fmacros
, "# %d \"%s\"\n", line
, str
);
1364 c
= read_identifier (f
, c
, &str
);
1365 if (strcmp (str
, "define") != 0 || (c
!= ' ' && c
!= '\t'))
1369 c
= eat_line (f
, c
);
1375 c
= read_identifier (f
, c
, &str
);
1376 if (strlen (str
) == 0 || (c
!= ' ' && c
!= '\t' && c
!= '('))
1380 c
= eat_line (f
, c
);
1384 define_line
= g_string_new ("#define ");
1385 g_string_append (define_line
, str
);
1391 g_string_append_c (define_line
, c
);
1393 if (c
== EOF
|| c
== '\n')
1401 g_string_free (define_line
, TRUE
);
1403 c
= eat_line (f
, c
);
1408 g_assert (c
== ')');
1409 g_string_append_c (define_line
, c
);
1412 /* found function-like macro */
1413 fprintf (fmacros
, "%s\n", define_line
->str
);
1415 g_string_free (define_line
, TRUE
);
1416 /* ignore rest of line */
1417 c
= eat_line (f
, c
);
1421 if (c
!= ' ' && c
!= '\t')
1423 g_string_free (define_line
, TRUE
);
1425 c
= eat_line (f
, c
);
1429 while (c
!= EOF
&& c
!= '\n')
1431 g_string_append_c (define_line
, c
);
1438 /* fold lines when seeing backslash new-line sequence */
1443 g_string_append_c (define_line
, '\\');
1448 /* found object-like macro */
1449 fprintf (fmacros
, "%s\n", define_line
->str
);
1451 c
= eat_line (f
, c
);
1458 igenerator
->macro_scan
= TRUE
;
1461 g_igenerator_parse_file (igenerator
, fmacros
);
1464 igenerator
->macro_scan
= FALSE
;
1468 g_igenerator_add_module (GIGenerator
*igenerator
,
1473 for (l
= module
->entries
; l
; l
= l
->next
)
1475 GIdlNode
*node
= (GIdlNode
*)l
->data
;
1477 if (node
->type
== G_IDL_NODE_OBJECT
)
1479 GIdlNodeInterface
*object
= (GIdlNodeInterface
*)node
;
1481 if (strcmp(module
->name
, igenerator
->namespace) == 0)
1482 name
= g_strdup (node
->name
);
1484 name
= g_strdup_printf ("%s.%s", module
->name
, node
->name
);
1485 g_hash_table_insert (igenerator
->symbols
,
1486 g_strdup (object
->gtype_name
),
1493 g_igenerator_add_include_idl (GIGenerator
*igenerator
,
1494 const gchar
*filename
)
1499 GError
*error
= NULL
;
1501 modules
= g_idl_parse_file (filename
, &error
);
1504 g_printerr ("An error occurred while parsing %s: %s\n",
1505 filename
, error
->message
);
1509 for (l
= modules
; l
; l
= l
->next
)
1511 GIdlModule
*module
= (GIdlModule
*)l
->data
;
1512 g_igenerator_add_module (igenerator
, module
);
1517 g_igenerator_start_preprocessor (GIGenerator
*igenerator
,
1520 int cpp_out
= -1, cpp_in
= -1;
1524 GError
*error
= NULL
;
1534 cpp_argv
= g_new0 (char *, g_list_length (cpp_options
) + 5);
1535 cpp_argv
[cpp_argc
++] = "cpp";
1536 cpp_argv
[cpp_argc
++] = "-C";
1538 /* Disable GCC extensions as we cannot parse them yet */
1539 cpp_argv
[cpp_argc
++] = "-U__GNUC__";
1541 /* Help system headers cope with the lack of __GNUC__ by pretending to be lint */
1542 cpp_argv
[cpp_argc
++] = "-Dlint";
1544 for (l
= cpp_options
; l
; l
= l
->next
)
1545 cpp_argv
[cpp_argc
++] = (char*)l
->data
;
1547 cpp_argv
[cpp_argc
++] = NULL
;
1549 if (igenerator
->verbose
)
1551 GString
*args
= g_string_new ("");
1553 for (i
= 0; i
< cpp_argc
- 1; i
++)
1555 g_string_append (args
, cpp_argv
[i
]);
1556 if (i
< cpp_argc
- 2)
1557 g_string_append_c (args
, ' ');
1560 g_printf ("Executing '%s'\n", args
->str
);
1561 g_string_free (args
, FALSE
);
1563 g_spawn_async_with_pipes (NULL
, cpp_argv
, NULL
,
1564 G_SPAWN_SEARCH_PATH
| G_SPAWN_DO_NOT_REAP_CHILD
,
1565 NULL
, NULL
, &pid
, &cpp_in
, &cpp_out
, NULL
, &error
);
1570 g_error ("%s", error
->message
);
1574 f
= fdopen (cpp_in
, "w");
1576 for (l
= igenerator
->filenames
; l
!= NULL
; l
= l
->next
)
1578 if (igenerator
->verbose
)
1579 g_printf ("Pre-processing %s\n", (char*)l
->data
);
1581 fprintf (f
, "#include <%s>\n", (char *) l
->data
);
1588 tmp
= g_file_open_tmp (NULL
, &tmpname
, &error
);
1591 g_error ("%s", error
->message
);
1595 buffer
= g_malloc0 (4096 * sizeof (char));
1599 read_bytes
= read (cpp_out
, buffer
, 4096);
1600 if (read_bytes
== 0)
1602 write (tmp
, buffer
, read_bytes
);
1610 if (waitpid (pid
, &status
, 0) > 0)
1612 /* We don't want to include <windows.h> as it clashes horribly
1613 * with token names from scannerparser.h. So just declare
1614 * WaitForSingleObject, GetExitCodeProcess and INFINITE here.
1616 extern unsigned long __stdcall
WaitForSingleObject(void*, int);
1617 extern int __stdcall
GetExitCodeProcess(void*, int*);
1618 #define INFINITE 0xffffffff
1620 WaitForSingleObject (pid
, INFINITE
);
1622 if (GetExitCodeProcess (pid
, &status
))
1627 g_spawn_close_pid (pid
);
1629 kill (pid
, SIGKILL
);
1632 g_error ("cpp returned error code: %d\n", status
);
1639 f
= fdopen (tmp
, "r");
1642 g_error ("%s", strerror (errno
));
1656 g_igenerator_set_verbose (GIGenerator
*igenerator
,
1659 igenerator
->verbose
= verbose
;
1663 main (int argc
, char **argv
)
1665 GOptionContext
*ctx
;
1666 gchar
*namespace = NULL
;
1667 gchar
*shared_library
= NULL
;
1668 gchar
**include_idls
= NULL
;
1669 gchar
*output
= NULL
;
1670 gboolean verbose
= FALSE
;
1672 GIGenerator
*igenerator
;
1675 GList
*filenames
= NULL
;
1676 GError
*error
= NULL
;
1677 GList
*l
, *libraries
= NULL
;
1678 GList
*cpp_options
= NULL
;
1682 GOptionEntry entries
[] =
1684 { "verbose", 'v', 0, G_OPTION_ARG_NONE
, &verbose
,
1686 { "output", 'o', 0, G_OPTION_ARG_STRING
, &output
,
1687 "write output here instead of stdout", "FILE" },
1688 { "namespace", 'n', 0, G_OPTION_ARG_STRING
, &namespace,
1689 "Namespace of the module, like 'Gtk'", "NAMESPACE" },
1690 { "shared-library", 0, 0, G_OPTION_ARG_FILENAME
, &shared_library
,
1691 "Shared library which contains the symbols", "FILE" },
1692 { "include-idl", 0, 0, G_OPTION_ARG_STRING_ARRAY
, &include_idls
,
1693 "Other gidls to include", "IDL" },
1698 gopt_argv
= (char**)g_malloc (argc
* sizeof (char*));
1699 gopt_argv
[0] = argv
[0];
1701 for (i
= 1; i
< argc
; i
++)
1703 if (argv
[i
][0] == '-')
1710 cpp_options
= g_list_prepend (cpp_options
, g_strdup (argv
[i
]));
1714 if (0==strcmp("-pthread", argv
[i
]))
1717 gopt_argv
[gopt_argc
++] = argv
[i
];
1721 else if (g_str_has_suffix (argv
[i
], ".h"))
1725 if (!g_path_is_absolute (argv
[i
]))
1727 gchar
*dir
= g_get_current_dir ();
1728 filename
= g_strdup_printf ("%s/%s", dir
,
1733 filename
= g_strdup (argv
[i
]);
1735 filenames
= g_list_append (filenames
, g_realpath(filename
));
1738 else if (g_str_has_suffix (argv
[i
], ".la") ||
1739 g_str_has_suffix (argv
[i
], ".so") ||
1740 g_str_has_suffix (argv
[i
], ".dll"))
1742 libraries
= g_list_prepend (libraries
, g_strdup (argv
[i
]));
1746 gopt_argv
[gopt_argc
++] = argv
[i
];
1750 ctx
= g_option_context_new ("");
1751 g_option_context_add_main_entries (ctx
, entries
, NULL
);
1753 if (!g_option_context_parse (ctx
, &gopt_argc
, &gopt_argv
, &error
))
1755 g_printerr ("Parsing error: %s\n", error
->message
);
1756 g_option_context_free (ctx
);
1761 g_option_context_free (ctx
);
1765 g_printerr ("ERROR: namespace must be specified\n");
1769 igenerator
= g_igenerator_new (namespace, shared_library
);
1772 g_igenerator_set_verbose (igenerator
, TRUE
);
1776 g_printerr ("ERROR: Need at least one header file.\n");
1777 g_igenerator_free (igenerator
);
1780 igenerator
->filenames
= filenames
;
1781 cpp_options
= g_list_reverse (cpp_options
);
1782 libraries
= g_list_reverse (libraries
);
1786 for (i
= 0; i
< g_strv_length (include_idls
); i
++)
1787 g_igenerator_add_include_idl (igenerator
, include_idls
[i
]);
1790 tmp
= g_igenerator_start_preprocessor (igenerator
, cpp_options
);
1793 g_error ("ERROR in pre-processor.\n");
1794 g_igenerator_free (igenerator
);
1798 if (!g_igenerator_parse_file (igenerator
, tmp
))
1801 g_igenerator_free (igenerator
);
1805 g_igenerator_parse_macros (igenerator
);
1807 g_igenerator_generate (igenerator
, output
, libraries
);
1810 g_igenerator_free (igenerator
);