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>
34 #include <sys/wait.h> /* waitpid */
37 #include "gidlparser.h"
38 #include "gidlmodule.h"
40 #include "gidlwriter.h"
41 #include "grealpath.h"
44 typedef GType (*TypeFunction
) (void);
46 static void g_igenerator_parse_macros (GIGenerator
* igenerator
);
49 g_igenerator_new (const gchar
*namespace,
50 const gchar
*shared_library
)
52 GIGenerator
*igenerator
= g_new0 (GIGenerator
, 1);
53 igenerator
->namespace = g_strdup (namespace);
54 igenerator
->shared_library
= g_strdup (shared_library
);
55 igenerator
->lower_case_namespace
=
56 g_ascii_strdown (igenerator
->namespace, -1);
57 igenerator
->module
= g_idl_module_new (namespace, shared_library
);
59 igenerator
->typedef_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
60 igenerator
->struct_or_union_or_enum_table
=
61 g_hash_table_new (g_str_hash
, g_str_equal
);
63 igenerator
->type_map
= g_hash_table_new (g_str_hash
, g_str_equal
);
64 igenerator
->type_by_lower_case_prefix
=
65 g_hash_table_new (g_str_hash
, g_str_equal
);
66 igenerator
->symbols
= g_hash_table_new (g_str_hash
, g_str_equal
);
72 g_igenerator_free (GIGenerator
*generator
)
74 g_free (generator
->namespace);
75 g_free (generator
->shared_library
);
76 g_free (generator
->lower_case_namespace
);
78 g_idl_module_free (generator
->module
);
80 g_hash_table_destroy (generator
->typedef_table
);
81 g_hash_table_destroy (generator
->struct_or_union_or_enum_table
);
82 g_hash_table_destroy (generator
->type_map
);
83 g_hash_table_destroy (generator
->type_by_lower_case_prefix
);
84 g_hash_table_destroy (generator
->symbols
);
85 g_list_foreach (generator
->filenames
, (GFunc
)g_free
, NULL
);
86 g_list_free (generator
->filenames
);
88 g_list_foreach (generator
->symbol_list
, (GFunc
)csymbol_free
, NULL
);
89 g_list_free (generator
->symbol_list
);
95 create_node_from_gtype (GType type_id
)
100 node
= (GIdlNodeType
*) g_idl_node_new (G_IDL_NODE_TYPE
);
102 fundamental
= g_type_fundamental (type_id
);
106 node
->unparsed
= g_strdup ("char*");
108 case G_TYPE_INTERFACE
:
111 node
->unparsed
= g_strdup_printf ("%s*", g_type_name (type_id
));
114 node
->unparsed
= g_strdup ("GParamSpec*");
117 if (fundamental
== G_TYPE_STRV
)
118 node
->unparsed
= g_strdup ("char*[]");
120 node
->unparsed
= g_strdup (g_type_name (type_id
));
127 static GIdlNodeType
*
128 create_node_from_ctype (CType
* ctype
)
132 node
= (GIdlNodeType
*) g_idl_node_new (G_IDL_NODE_TYPE
);
137 node
->unparsed
= g_strdup ("void");
139 case CTYPE_BASIC_TYPE
:
140 node
->unparsed
= g_strdup (ctype
->name
);
143 node
->unparsed
= g_strdup (ctype
->name
);
146 if (ctype
->name
== NULL
)
147 /* anonymous struct */
148 node
->unparsed
= g_strdup ("gpointer");
150 node
->unparsed
= g_strdup_printf ("struct %s", ctype
->name
);
153 if (ctype
->name
== NULL
)
154 /* anonymous union */
155 node
->unparsed
= g_strdup ("gpointer");
157 node
->unparsed
= g_strdup_printf ("union %s", ctype
->name
);
160 if (ctype
->name
== NULL
)
162 node
->unparsed
= g_strdup ("gint");
164 node
->unparsed
= g_strdup_printf ("enum %s", ctype
->name
);
167 if (ctype
->base_type
->type
== CTYPE_FUNCTION
)
168 /* anonymous function pointer */
169 node
->unparsed
= g_strdup ("GCallback");
172 GIdlNodeType
*gibasetype
= create_node_from_ctype (ctype
->base_type
);
173 node
->unparsed
= g_strdup_printf ("%s*", gibasetype
->unparsed
);
178 GIdlNodeType
*gibasetype
= create_node_from_ctype (ctype
->base_type
);
179 node
->unparsed
= g_strdup_printf ("%s[]", gibasetype
->unparsed
);
183 node
->unparsed
= g_strdup ("unknown");
191 str_replace (const char *str
, const char *needle
, const char *replacement
)
193 char **strings
= g_strsplit (str
, needle
, 0);
194 char *result
= g_strjoinv (replacement
, strings
);
195 g_strfreev (strings
);
200 g_igenerator_process_properties (GIGenerator
* igenerator
,
201 GIdlNodeInterface
* node
, GType type_id
)
205 GParamSpec
**properties
;
207 if (node
->node
.type
== G_IDL_NODE_OBJECT
)
209 GObjectClass
*type_class
= g_type_class_ref (type_id
);
210 properties
= g_object_class_list_properties (type_class
, &n_properties
);
212 else if (node
->node
.type
== G_IDL_NODE_INTERFACE
)
214 GTypeInterface
*iface
= g_type_default_interface_ref (type_id
);
215 properties
= g_object_interface_list_properties (iface
, &n_properties
);
219 g_assert_not_reached ();
222 for (i
= 0; i
< n_properties
; i
++)
224 GIdlNodeProperty
*giprop
;
226 /* ignore inherited properties */
227 if (properties
[i
]->owner_type
!= type_id
)
231 giprop
= (GIdlNodeProperty
*) g_idl_node_new (G_IDL_NODE_PROPERTY
);
232 giprop
->node
.name
= properties
[i
]->name
;
234 g_list_insert_sorted (node
->members
, giprop
,
235 (GCompareFunc
) g_idl_node_cmp
);
236 giprop
->type
= create_node_from_gtype (properties
[i
]->value_type
);
237 giprop
->readable
= (properties
[i
]->flags
& G_PARAM_READABLE
) != 0;
238 giprop
->writable
= (properties
[i
]->flags
& G_PARAM_WRITABLE
) != 0;
239 giprop
->construct
= (properties
[i
]->flags
& G_PARAM_CONSTRUCT
) != 0;
240 giprop
->construct_only
=
241 (properties
[i
]->flags
& G_PARAM_CONSTRUCT_ONLY
) != 0;
246 g_igenerator_process_signals (GIGenerator
* igenerator
,
247 GIdlNodeInterface
* node
, GType type_id
)
251 guint
*signal_ids
= g_signal_list_ids (type_id
, &n_signal_ids
);
253 for (i
= 0; i
< n_signal_ids
; i
++)
255 GSignalQuery signal_query
;
256 GIdlNodeSignal
*gisig
;
257 GIdlNodeParam
*giparam
;
259 g_signal_query (signal_ids
[i
], &signal_query
);
260 gisig
= (GIdlNodeSignal
*) g_idl_node_new (G_IDL_NODE_SIGNAL
);
261 gisig
->node
.name
= g_strdup (signal_query
.signal_name
);
263 g_list_insert_sorted (node
->members
, gisig
,
264 (GCompareFunc
) g_idl_node_cmp
);
267 (signal_query
.signal_flags
& G_SIGNAL_RUN_FIRST
) != 0;
268 gisig
->run_last
= (signal_query
.signal_flags
& G_SIGNAL_RUN_LAST
) != 0;
270 (signal_query
.signal_flags
& G_SIGNAL_RUN_CLEANUP
) != 0;
272 /* add sender parameter */
273 giparam
= (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
274 gisig
->parameters
= g_list_append (gisig
->parameters
, giparam
);
275 giparam
->node
.name
= g_strdup ("object");
276 giparam
->type
= create_node_from_gtype (type_id
);
278 for (j
= 0; j
< signal_query
.n_params
; j
++)
280 giparam
= (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
281 gisig
->parameters
= g_list_append (gisig
->parameters
, giparam
);
282 giparam
->node
.name
= g_strdup_printf ("p%d", j
);
283 giparam
->type
= create_node_from_gtype (signal_query
.param_types
[j
]);
285 gisig
->result
= (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
286 gisig
->result
->type
= create_node_from_gtype (signal_query
.return_type
);
291 lookup_symbol (GIGenerator
*igenerator
, const gchar
*typename
)
294 g_hash_table_lookup (igenerator
->symbols
, typename
);
298 g_printerr ("Unknown symbol: %s\n", typename
);
306 g_igenerator_create_object (GIGenerator
*igenerator
,
307 const char *symbol_name
,
309 char *lower_case_prefix
)
312 char *alt_lower_case_prefix
;
313 GIdlNodeInterface
*node
;
314 guint n_type_interfaces
;
315 GType
*type_interfaces
;
318 node
= (GIdlNodeInterface
*) g_idl_node_new (G_IDL_NODE_OBJECT
);
319 node
->node
.name
= g_strdup (g_type_name (type_id
));
320 igenerator
->module
->entries
=
321 g_list_insert_sorted (igenerator
->module
->entries
, node
,
322 (GCompareFunc
) g_idl_node_cmp
);
323 g_hash_table_insert (igenerator
->type_map
, node
->node
.name
,
325 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
326 lower_case_prefix
, node
);
327 alt_lower_case_prefix
= g_ascii_strdown (node
->node
.name
, -1);
329 if (strcmp (alt_lower_case_prefix
, lower_case_prefix
) != 0)
331 /* alternative prefix sometimes necessary, for example
334 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
335 alt_lower_case_prefix
, node
);
339 g_free (alt_lower_case_prefix
);
342 node
->gtype_name
= node
->node
.name
;
343 node
->gtype_init
= g_strdup (symbol_name
);
344 node
->parent
= g_strdup (lookup_symbol (igenerator
,
345 g_type_name (g_type_parent (type_id
))));
347 type_interfaces
= g_type_interfaces (type_id
, &n_type_interfaces
);
348 for (i
= 0; i
< n_type_interfaces
; i
++)
351 g_strdup (g_type_name (type_interfaces
[i
]));
352 /* workaround for AtkImplementorIface */
353 if (g_str_has_suffix (iface_name
, "Iface"))
355 iface_name
[strlen (iface_name
) - strlen ("Iface")] =
359 g_list_append (node
->interfaces
, iface_name
);
362 g_hash_table_insert (igenerator
->symbols
,
363 g_strdup (node
->gtype_name
),
364 /* FIXME: Strip igenerator->namespace */
365 g_strdup (node
->node
.name
));
367 g_igenerator_process_properties (igenerator
, node
, type_id
);
368 g_igenerator_process_signals (igenerator
, node
, type_id
);
372 g_igenerator_create_interface (GIGenerator
*igenerator
,
373 const char *symbol_name
,
375 char *lower_case_prefix
)
378 GIdlNodeInterface
*node
;
379 gboolean is_gobject
= FALSE
;
380 guint n_iface_prereqs
;
381 GType
*iface_prereqs
;
384 node
= (GIdlNodeInterface
*) g_idl_node_new (G_IDL_NODE_INTERFACE
);
385 node
->node
.name
= g_strdup (g_type_name (type_id
));
387 /* workaround for AtkImplementorIface */
388 if (g_str_has_suffix (node
->node
.name
, "Iface"))
390 node
->node
.name
[strlen (node
->node
.name
) -
391 strlen ("Iface")] = '\0';
393 igenerator
->module
->entries
=
394 g_list_insert_sorted (igenerator
->module
->entries
, node
,
395 (GCompareFunc
) g_idl_node_cmp
);
396 g_hash_table_insert (igenerator
->type_map
, node
->node
.name
,
398 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
399 lower_case_prefix
, node
);
400 node
->gtype_name
= node
->node
.name
;
401 node
->gtype_init
= g_strdup (symbol_name
);
404 g_type_interface_prerequisites (type_id
, &n_iface_prereqs
);
406 for (i
= 0; i
< n_iface_prereqs
; i
++)
408 if (g_type_fundamental (iface_prereqs
[i
]) == G_TYPE_OBJECT
)
412 node
->prerequisites
=
413 g_list_append (node
->prerequisites
,
414 g_strdup (g_type_name (iface_prereqs
[i
])));
418 g_igenerator_process_properties (igenerator
, node
, type_id
);
420 g_type_default_interface_ref (type_id
);
422 g_igenerator_process_signals (igenerator
, node
, type_id
);
426 g_igenerator_create_boxed (GIGenerator
*igenerator
,
427 const char *symbol_name
,
429 char *lower_case_prefix
)
431 GIdlNodeBoxed
*node
=
432 (GIdlNodeBoxed
*) g_idl_node_new (G_IDL_NODE_BOXED
);
433 node
->node
.name
= g_strdup (g_type_name (type_id
));
434 igenerator
->module
->entries
=
435 g_list_insert_sorted (igenerator
->module
->entries
, node
,
436 (GCompareFunc
) g_idl_node_cmp
);
437 g_hash_table_insert (igenerator
->type_map
, node
->node
.name
,
439 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
440 lower_case_prefix
, node
);
441 node
->gtype_name
= node
->node
.name
;
442 node
->gtype_init
= g_strdup (symbol_name
);
446 g_igenerator_create_enum (GIGenerator
*igenerator
,
447 const char *symbol_name
,
449 char *lower_case_prefix
)
453 GEnumClass
*type_class
;
455 node
= (GIdlNodeEnum
*) g_idl_node_new (G_IDL_NODE_ENUM
);
456 node
->node
.name
= g_strdup (g_type_name (type_id
));
457 igenerator
->module
->entries
=
458 g_list_insert_sorted (igenerator
->module
->entries
, node
,
459 (GCompareFunc
) g_idl_node_cmp
);
460 g_hash_table_insert (igenerator
->type_map
, node
->node
.name
,
462 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
463 lower_case_prefix
, node
);
464 node
->gtype_name
= node
->node
.name
;
465 node
->gtype_init
= g_strdup (symbol_name
);
467 type_class
= g_type_class_ref (type_id
);
469 for (i
= 0; i
< type_class
->n_values
; i
++)
471 GIdlNodeValue
*gival
=
472 (GIdlNodeValue
*) g_idl_node_new (G_IDL_NODE_VALUE
);
473 node
->values
= g_list_append (node
->values
, gival
);
475 g_strdup (type_class
->values
[i
].value_name
);
476 gival
->value
= type_class
->values
[i
].value
;
481 g_igenerator_create_flags (GIGenerator
*igenerator
,
482 const char *symbol_name
,
484 char *lower_case_prefix
)
487 GFlagsClass
*type_class
;
490 node
= (GIdlNodeEnum
*) g_idl_node_new (G_IDL_NODE_FLAGS
);
491 node
->node
.name
= g_strdup (g_type_name (type_id
));
492 igenerator
->module
->entries
=
493 g_list_insert_sorted (igenerator
->module
->entries
, node
,
494 (GCompareFunc
) g_idl_node_cmp
);
495 g_hash_table_insert (igenerator
->type_map
, node
->node
.name
,
497 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
498 lower_case_prefix
, node
);
499 node
->gtype_name
= node
->node
.name
;
500 node
->gtype_init
= g_strdup (symbol_name
);
502 type_class
= g_type_class_ref (type_id
);
504 for (i
= 0; i
< type_class
->n_values
; i
++)
506 GIdlNodeValue
*gival
=
507 (GIdlNodeValue
*) g_idl_node_new (G_IDL_NODE_VALUE
);
508 node
->values
= g_list_append (node
->values
, gival
);
510 g_strdup (type_class
->values
[i
].value_name
);
511 gival
->value
= type_class
->values
[i
].value
;
516 g_igenerator_process_module_symbol (GIGenerator
*igenerator
,
518 const gchar
*symbol_name
)
520 TypeFunction type_fun
;
522 GType type_fundamental
;
523 char *lower_case_prefix
;
525 /* ignore already processed functions */
526 if (symbol_name
== NULL
)
529 if (!g_module_symbol (module
,
531 (gpointer
*) & type_fun
))
534 type_id
= type_fun ();
535 type_fundamental
= g_type_fundamental (type_id
);
537 str_replace (g_strndup
539 strlen (symbol_name
) - strlen ("_get_type")),
542 switch (type_fundamental
)
545 g_igenerator_create_object (igenerator
, symbol_name
, type_id
,
548 case G_TYPE_INTERFACE
:
549 g_igenerator_create_interface (igenerator
, symbol_name
, type_id
,
553 g_igenerator_create_boxed (igenerator
, symbol_name
, type_id
,
557 g_igenerator_create_enum (igenerator
, symbol_name
, type_id
,
561 g_igenerator_create_flags (igenerator
, symbol_name
, type_id
,
571 g_igenerator_process_module (GIGenerator
* igenerator
,
572 const gchar
*filename
)
577 module
= g_module_open (filename
,
578 G_MODULE_BIND_LAZY
| G_MODULE_BIND_LOCAL
);
582 g_critical ("Couldn't open module: %s", filename
);
586 for (l
= igenerator
->get_type_symbols
; l
!= NULL
; l
= l
->next
)
588 if (g_igenerator_process_module_symbol (igenerator
,
589 module
, (const char *)l
->data
))
590 /* symbol found, ignore in future iterations */
596 g_igenerator_process_function_symbol (GIGenerator
* igenerator
, CSymbol
* sym
)
598 GIdlNodeFunction
*func
;
599 char *last_underscore
;
604 func
= (GIdlNodeFunction
*) g_idl_node_new (G_IDL_NODE_FUNCTION
);
606 /* check whether this is a type method */
607 last_underscore
= strrchr (sym
->ident
, '_');
609 while (last_underscore
!= NULL
)
614 prefix
= g_strndup (sym
->ident
, last_underscore
- sym
->ident
);
615 prefix
= str_replace (prefix
, "_", "");
617 node
= g_hash_table_lookup (igenerator
->type_by_lower_case_prefix
,
621 func
->node
.name
= g_strdup (last_underscore
+ 1);
623 /* ignore get_type functions in registered types */
624 if (strcmp (func
->node
.name
, "get_type") == 0)
627 if ((node
->type
== G_IDL_NODE_OBJECT
||
628 node
->type
== G_IDL_NODE_BOXED
) &&
629 g_str_has_prefix (func
->node
.name
, "new"))
630 func
->is_constructor
= TRUE
;
632 func
->is_method
= TRUE
;
633 if (g_idl_node_can_have_member (node
))
635 g_idl_node_add_member (node
, func
);
640 /* reset function attributes */
641 g_free (func
->node
.name
);
642 func
->node
.name
= NULL
;
643 func
->is_constructor
= FALSE
;
644 func
->is_method
= FALSE
;
647 else if (strcmp (igenerator
->lower_case_namespace
, prefix
) == 0)
649 func
->node
.name
= g_strdup (last_underscore
+ 1);
650 igenerator
->module
->entries
=
651 g_list_insert_sorted (igenerator
->module
->entries
, func
,
652 (GCompareFunc
) g_idl_node_cmp
);
656 g_utf8_strrchr (sym
->ident
, last_underscore
- sym
->ident
, '_');
659 /* create a namespace function if no prefix matches */
660 if (func
->node
.name
== NULL
)
662 func
->node
.name
= sym
->ident
;
663 func
->is_constructor
= FALSE
;
664 func
->is_method
= FALSE
;
665 igenerator
->module
->entries
=
666 g_list_insert_sorted (igenerator
->module
->entries
, func
,
667 (GCompareFunc
) g_idl_node_cmp
);
670 func
->symbol
= sym
->ident
;
671 func
->result
= (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
672 func
->result
->type
= create_node_from_ctype (sym
->base_type
->base_type
);
674 for (param_l
= sym
->base_type
->child_list
, i
= 1; param_l
!= NULL
;
675 param_l
= param_l
->next
, i
++)
677 CSymbol
*param_sym
= param_l
->data
;
678 GIdlNodeParam
*param
;
680 param
= (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
681 param
->type
= create_node_from_ctype (param_sym
->base_type
);
683 if (param_sym
->ident
== NULL
)
684 param
->node
.name
= g_strdup_printf ("p%d", i
);
686 param
->node
.name
= param_sym
->ident
;
688 func
->parameters
= g_list_append (func
->parameters
, param
);
691 for (l
= sym
->directives
; l
; l
= l
->next
)
693 CDirective
*directive
= (CDirective
*)l
->data
;
695 if (!strcmp (directive
->name
, "deprecated"))
696 func
->deprecated
= TRUE
;
698 g_printerr ("Unknown function directive: %s\n",
704 g_igenerator_process_unregistered_struct_typedef (GIGenerator
* igenerator
,
708 GIdlNodeStruct
*node
=
709 (GIdlNodeStruct
*) g_idl_node_new (G_IDL_NODE_STRUCT
);
711 char *lower_case_prefix
;
713 node
->node
.name
= sym
->ident
;
714 igenerator
->module
->entries
=
715 g_list_insert_sorted (igenerator
->module
->entries
, node
,
716 (GCompareFunc
) g_idl_node_cmp
);
717 lower_case_prefix
= g_ascii_strdown (sym
->ident
, -1);
718 g_hash_table_insert (igenerator
->type_map
, sym
->ident
, node
);
719 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
720 lower_case_prefix
, node
);
722 for (member_l
= struct_type
->child_list
; member_l
!= NULL
;
723 member_l
= member_l
->next
)
725 CSymbol
*member
= member_l
->data
;
726 GIdlNodeField
*gifield
=
727 (GIdlNodeField
*) g_idl_node_new (G_IDL_NODE_FIELD
);
729 node
->members
= g_list_append (node
->members
, gifield
);
730 gifield
->node
.name
= member
->ident
;
731 gifield
->type
= create_node_from_ctype (member
->base_type
);
736 g_igenerator_process_struct_typedef (GIGenerator
* igenerator
, CSymbol
* sym
)
738 CType
*struct_type
= sym
->base_type
;
739 gboolean opaque_type
= FALSE
;
742 if (struct_type
->child_list
== NULL
)
744 CSymbol
*struct_symbol
;
745 g_assert (struct_type
->name
!= NULL
);
747 g_hash_table_lookup (igenerator
->struct_or_union_or_enum_table
,
749 if (struct_symbol
!= NULL
)
751 struct_type
= struct_symbol
->base_type
;
755 if (struct_type
->child_list
== NULL
)
760 type
= g_hash_table_lookup (igenerator
->type_map
, sym
->ident
);
763 /* struct of a GTypeInstance */
765 && (type
->type
== G_IDL_NODE_OBJECT
766 || type
->type
== G_IDL_NODE_INTERFACE
))
768 GIdlNodeInterface
*node
= (GIdlNodeInterface
*) type
;
770 /* ignore first field => parent */
771 for (member_l
= struct_type
->child_list
->next
; member_l
!= NULL
;
772 member_l
= member_l
->next
)
774 CSymbol
*member
= member_l
->data
;
775 /* ignore private / reserved members */
776 if (member
->ident
[0] == '_'
777 || g_str_has_prefix (member
->ident
, "priv"))
781 GIdlNodeField
*gifield
=
782 (GIdlNodeField
*) g_idl_node_new (G_IDL_NODE_FIELD
);
783 node
->members
= g_list_append (node
->members
, gifield
);
784 gifield
->node
.name
= member
->ident
;
785 gifield
->type
= create_node_from_ctype (member
->base_type
);
788 else if (type
->type
== G_IDL_NODE_BOXED
)
790 GIdlNodeBoxed
*node
= (GIdlNodeBoxed
*) type
;
792 for (member_l
= struct_type
->child_list
; member_l
!= NULL
;
793 member_l
= member_l
->next
)
795 CSymbol
*member
= member_l
->data
;
796 GIdlNodeField
*gifield
=
797 (GIdlNodeField
*) g_idl_node_new (G_IDL_NODE_FIELD
);
798 node
->members
= g_list_append (node
->members
, gifield
);
799 gifield
->node
.name
= member
->ident
;
800 gifield
->type
= create_node_from_ctype (member
->base_type
);
804 else if (!opaque_type
805 && (g_str_has_suffix (sym
->ident
, "Class")
806 || g_str_has_suffix (sym
->ident
, "Iface")
807 || g_str_has_suffix (sym
->ident
, "Interface")))
811 GIdlNodeInterface
*node
;
813 if (g_str_has_suffix (sym
->ident
, "Interface"))
816 g_strndup (sym
->ident
,
817 strlen (sym
->ident
) - strlen ("Interface"));
822 g_strndup (sym
->ident
, strlen (sym
->ident
) - strlen ("Class"));
824 type
= g_hash_table_lookup (igenerator
->type_map
, base_name
);
826 || (type
->type
!= G_IDL_NODE_OBJECT
827 && type
->type
!= G_IDL_NODE_INTERFACE
))
829 g_igenerator_process_unregistered_struct_typedef (igenerator
, sym
,
833 node
= (GIdlNodeInterface
*) type
;
835 /* ignore first field => parent */
836 for (member_l
= struct_type
->child_list
->next
; member_l
!= NULL
;
837 member_l
= member_l
->next
)
839 CSymbol
*member
= member_l
->data
;
840 /* ignore private / reserved members */
841 if (member
->ident
[0] == '_')
845 if (member
->base_type
->type
== CTYPE_POINTER
846 && member
->base_type
->base_type
->type
== CTYPE_FUNCTION
)
848 /* ignore default handlers of signals */
849 gboolean found_signal
= FALSE
;
850 GList
*type_member_l
;
853 GIdlNodeVFunc
*givfunc
;
855 for (type_member_l
= node
->members
; type_member_l
!= NULL
;
856 type_member_l
= type_member_l
->next
)
858 GIdlNode
*type_member
= type_member_l
->data
;
859 char *normalized_name
=
860 str_replace (type_member
->name
, "-", "_");
861 if (type_member
->type
== G_IDL_NODE_SIGNAL
862 && strcmp (normalized_name
, member
->ident
) == 0)
864 GList
*vfunc_param_l
;
866 GIdlNodeSignal
*sig
= (GIdlNodeSignal
*) type_member
;
868 /* set signal parameter names */
870 member
->base_type
->base_type
->child_list
,
871 sig_param_l
= sig
->parameters
;
872 vfunc_param_l
!= NULL
&& sig_param_l
!= NULL
;
873 vfunc_param_l
= vfunc_param_l
->next
, sig_param_l
=
876 CSymbol
*vfunc_param
= vfunc_param_l
->data
;
877 GIdlNodeParam
*sig_param
= sig_param_l
->data
;
878 if (vfunc_param
->ident
!= NULL
)
880 g_free (sig_param
->node
.name
);
881 sig_param
->node
.name
=
882 g_strdup (vfunc_param
->ident
);
893 givfunc
= (GIdlNodeVFunc
*) g_idl_node_new (G_IDL_NODE_VFUNC
);
894 givfunc
->node
.name
= member
->ident
;
896 g_list_insert_sorted (node
->members
, givfunc
,
897 (GCompareFunc
) g_idl_node_cmp
);
899 (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
900 givfunc
->result
->type
=
901 create_node_from_ctype (member
->base_type
->base_type
->base_type
);
902 for (param_l
= member
->base_type
->base_type
->child_list
, i
= 1;
903 param_l
!= NULL
; param_l
= param_l
->next
, i
++)
905 CSymbol
*param_sym
= param_l
->data
;
906 GIdlNodeParam
*param
=
907 (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
908 if (param_sym
->ident
== NULL
)
910 param
->node
.name
= g_strdup_printf ("p%d", i
);
914 param
->node
.name
= param_sym
->ident
;
916 param
->type
= create_node_from_ctype (param_sym
->base_type
);
917 givfunc
->parameters
=
918 g_list_append (givfunc
->parameters
, param
);
923 else if (g_str_has_suffix (sym
->ident
, "Private"))
925 /* ignore private structs */
929 g_igenerator_process_unregistered_struct_typedef (igenerator
, sym
,
935 g_igenerator_process_union_typedef (GIGenerator
* igenerator
, CSymbol
* sym
)
937 CType
*union_type
= sym
->base_type
;
938 gboolean opaque_type
= FALSE
;
941 if (union_type
->child_list
== NULL
)
943 g_assert (union_type
->name
!= NULL
);
944 CSymbol
*union_symbol
=
945 g_hash_table_lookup (igenerator
->struct_or_union_or_enum_table
,
947 if (union_symbol
!= NULL
)
949 union_type
= union_symbol
->base_type
;
952 if (union_type
->child_list
== NULL
)
957 type
= g_hash_table_lookup (igenerator
->type_map
, sym
->ident
);
960 g_assert (type
->type
== G_IDL_NODE_BOXED
);
961 GIdlNodeBoxed
*node
= (GIdlNodeBoxed
*) type
;
963 for (member_l
= union_type
->child_list
; member_l
!= NULL
;
964 member_l
= member_l
->next
)
966 CSymbol
*member
= member_l
->data
;
967 GIdlNodeField
*gifield
=
968 (GIdlNodeField
*) g_idl_node_new (G_IDL_NODE_FIELD
);
969 node
->members
= g_list_append (node
->members
, gifield
);
970 gifield
->node
.name
= member
->ident
;
971 gifield
->type
= create_node_from_ctype (member
->base_type
);
976 GIdlNodeUnion
*node
=
977 (GIdlNodeUnion
*) g_idl_node_new (G_IDL_NODE_UNION
);
978 char *lower_case_prefix
;
981 node
->node
.name
= sym
->ident
;
982 igenerator
->module
->entries
=
983 g_list_insert_sorted (igenerator
->module
->entries
, node
,
984 (GCompareFunc
) g_idl_node_cmp
);
985 lower_case_prefix
= g_ascii_strdown (sym
->ident
, -1);
986 g_hash_table_insert (igenerator
->type_map
, sym
->ident
, node
);
987 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
988 lower_case_prefix
, node
);
990 node
->node
.name
= sym
->ident
;
991 for (member_l
= union_type
->child_list
; member_l
!= NULL
;
992 member_l
= member_l
->next
)
994 CSymbol
*member
= member_l
->data
;
995 GIdlNodeField
*gifield
=
996 (GIdlNodeField
*) g_idl_node_new (G_IDL_NODE_FIELD
);
997 node
->members
= g_list_append (node
->members
, gifield
);
998 gifield
->node
.name
= member
->ident
;
999 gifield
->type
= create_node_from_ctype (member
->base_type
);
1005 g_igenerator_process_enum_typedef (GIGenerator
* igenerator
, CSymbol
* sym
)
1010 CSymbol
*enum_symbol
;
1012 enum_type
= sym
->base_type
;
1013 if (enum_type
->child_list
== NULL
)
1015 g_assert (enum_type
->name
!= NULL
);
1017 g_hash_table_lookup (igenerator
->struct_or_union_or_enum_table
,
1019 if (enum_symbol
!= NULL
)
1021 enum_type
= enum_symbol
->base_type
;
1024 if (enum_type
->child_list
== NULL
)
1030 node
= g_hash_table_lookup (igenerator
->type_map
, sym
->ident
);
1036 node
= (GIdlNodeEnum
*) g_idl_node_new (G_IDL_NODE_ENUM
);
1037 node
->node
.name
= sym
->ident
;
1038 igenerator
->module
->entries
=
1039 g_list_insert_sorted (igenerator
->module
->entries
, node
,
1040 (GCompareFunc
) g_idl_node_cmp
);
1042 for (member_l
= enum_type
->child_list
; member_l
!= NULL
;
1043 member_l
= member_l
->next
)
1045 CSymbol
*member
= member_l
->data
;
1046 GIdlNodeValue
*gival
=
1047 (GIdlNodeValue
*) g_idl_node_new (G_IDL_NODE_VALUE
);
1048 node
->values
= g_list_append (node
->values
, gival
);
1049 gival
->node
.name
= member
->ident
;
1050 gival
->value
= member
->const_int
;
1055 g_igenerator_process_function_typedef (GIGenerator
* igenerator
,
1061 /* handle callback types */
1062 GIdlNodeFunction
*gifunc
=
1063 (GIdlNodeFunction
*) g_idl_node_new (G_IDL_NODE_CALLBACK
);
1065 gifunc
->node
.name
= sym
->ident
;
1066 igenerator
->module
->entries
=
1067 g_list_insert_sorted (igenerator
->module
->entries
, gifunc
,
1068 (GCompareFunc
) g_idl_node_cmp
);
1070 gifunc
->symbol
= sym
->ident
;
1071 gifunc
->result
= (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
1072 gifunc
->result
->type
=
1073 create_node_from_ctype (sym
->base_type
->base_type
->base_type
);
1075 for (param_l
= sym
->base_type
->base_type
->child_list
, i
= 1;
1076 param_l
!= NULL
; param_l
= param_l
->next
, i
++)
1078 CSymbol
*param_sym
= param_l
->data
;
1079 GIdlNodeParam
*param
=
1080 (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
1081 if (param_sym
->ident
== NULL
)
1083 param
->node
.name
= g_strdup_printf ("p%d", i
);
1087 param
->node
.name
= param_sym
->ident
;
1089 param
->type
= create_node_from_ctype (param_sym
->base_type
);
1090 gifunc
->parameters
= g_list_append (gifunc
->parameters
, param
);
1095 g_igenerator_process_constant (GIGenerator
* igenerator
, CSymbol
* sym
)
1097 GIdlNodeConstant
*giconst
=
1098 (GIdlNodeConstant
*) g_idl_node_new (G_IDL_NODE_CONSTANT
);
1099 giconst
->node
.name
= sym
->ident
;
1100 igenerator
->module
->entries
=
1101 g_list_insert_sorted (igenerator
->module
->entries
, giconst
,
1102 (GCompareFunc
) g_idl_node_cmp
);
1104 giconst
->type
= (GIdlNodeType
*) g_idl_node_new (G_IDL_NODE_TYPE
);
1105 if (sym
->const_int_set
)
1107 giconst
->type
->unparsed
= g_strdup ("int");
1108 giconst
->value
= g_strdup_printf ("%d", sym
->const_int
);
1110 else if (sym
->const_string
!= NULL
)
1112 giconst
->type
->unparsed
= g_strdup ("char*");
1113 giconst
->value
= sym
->const_string
;
1118 g_igenerator_process_symbols (GIGenerator
* igenerator
)
1121 /* process type symbols first to ensure complete type hashtables */
1123 for (l
= igenerator
->symbol_list
; l
!= NULL
; l
= l
->next
)
1125 CSymbol
*sym
= l
->data
;
1126 if (sym
->ident
[0] == '_')
1128 /* ignore private / reserved symbols */
1131 if (sym
->type
== CSYMBOL_TYPE_TYPEDEF
)
1133 if (sym
->base_type
->type
== CTYPE_STRUCT
)
1135 g_igenerator_process_struct_typedef (igenerator
, sym
);
1137 else if (sym
->base_type
->type
== CTYPE_UNION
)
1139 g_igenerator_process_union_typedef (igenerator
, sym
);
1141 else if (sym
->base_type
->type
== CTYPE_ENUM
)
1143 g_igenerator_process_enum_typedef (igenerator
, sym
);
1145 else if (sym
->base_type
->type
== CTYPE_POINTER
1146 && sym
->base_type
->base_type
->type
== CTYPE_FUNCTION
)
1148 g_igenerator_process_function_typedef (igenerator
, sym
);
1152 GIdlNodeStruct
*node
=
1153 (GIdlNodeStruct
*) g_idl_node_new (G_IDL_NODE_STRUCT
);
1154 char *lower_case_prefix
;
1156 node
->node
.name
= sym
->ident
;
1157 igenerator
->module
->entries
=
1158 g_list_insert_sorted (igenerator
->module
->entries
, node
,
1159 (GCompareFunc
) g_idl_node_cmp
);
1160 lower_case_prefix
= g_ascii_strdown (sym
->ident
, -1);
1161 g_hash_table_insert (igenerator
->type_map
, sym
->ident
, node
);
1162 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
1163 lower_case_prefix
, node
);
1168 for (l
= igenerator
->symbol_list
; l
!= NULL
; l
= l
->next
)
1170 CSymbol
*sym
= l
->data
;
1171 if (sym
->ident
[0] == '_')
1173 /* ignore private / reserved symbols */
1176 if (sym
->type
== CSYMBOL_TYPE_FUNCTION
)
1178 g_igenerator_process_function_symbol (igenerator
, sym
);
1180 else if (sym
->type
== CSYMBOL_TYPE_CONST
)
1182 g_igenerator_process_constant (igenerator
, sym
);
1188 g_igenerator_add_symbol (GIGenerator
* igenerator
, CSymbol
* symbol
)
1192 /* only add symbols of main file */
1193 gboolean found_filename
= FALSE
;
1195 if (igenerator
->current_filename
)
1197 for (l
= igenerator
->filenames
; l
!= NULL
; l
= l
->next
)
1199 if (strcmp (l
->data
, igenerator
->current_filename
) == 0)
1201 found_filename
= TRUE
;
1207 symbol
->directives
= g_slist_reverse (igenerator
->directives
);
1208 igenerator
->directives
= NULL
;
1210 /* that's not very optimized ! */
1211 for (l
= igenerator
->symbol_list
; l
!= NULL
; l
= l
->next
)
1213 CSymbol
*other_symbol
= (CSymbol
*)l
->data
;
1214 if (g_str_equal (other_symbol
->ident
, symbol
->ident
)
1215 && other_symbol
->type
== symbol
->type
)
1217 g_printerr ("Dropping %s duplicate\n", symbol
->ident
);
1222 if (found_filename
|| igenerator
->macro_scan
)
1224 igenerator
->symbol_list
=
1225 g_list_prepend (igenerator
->symbol_list
, symbol
);
1228 if (symbol
->type
== CSYMBOL_TYPE_TYPEDEF
)
1231 g_hash_table_insert (igenerator
->typedef_table
, symbol
->ident
, symbol
);
1233 else if (symbol
->type
== CSYMBOL_TYPE_STRUCT
1234 || symbol
->type
== CSYMBOL_TYPE_UNION
1235 || symbol
->type
== CSYMBOL_TYPE_ENUM
)
1237 g_hash_table_insert (igenerator
->struct_or_union_or_enum_table
,
1238 symbol
->ident
, symbol
);
1243 g_igenerator_is_typedef (GIGenerator
* igenerator
, const char *name
)
1245 gboolean b
= g_hash_table_lookup (igenerator
->typedef_table
, name
) != NULL
;
1250 g_igenerator_generate (GIGenerator
* igenerator
,
1251 const gchar
* filename
,
1256 for (l
= igenerator
->symbol_list
; l
!= NULL
; l
= l
->next
)
1258 CSymbol
*sym
= l
->data
;
1259 if (sym
->type
== CSYMBOL_TYPE_FUNCTION
1260 && g_str_has_suffix (sym
->ident
, "_get_type"))
1262 if (sym
->base_type
->child_list
== NULL
)
1264 // ignore get_type functions with parameters
1265 igenerator
->get_type_symbols
=
1266 g_list_prepend (igenerator
->get_type_symbols
, sym
->ident
);
1271 /* ensure to initialize GObject */
1272 g_type_class_ref (G_TYPE_OBJECT
);
1274 for (l
= libraries
; l
; l
= l
->next
)
1275 g_igenerator_process_module (igenerator
, (const gchar
*)l
->data
);
1277 g_igenerator_process_symbols (igenerator
);
1279 g_idl_writer_save_file (igenerator
->module
, filename
);
1283 eat_hspace (FILE * f
)
1290 while (c
== ' ' || c
== '\t');
1295 eat_line (FILE * f
, int c
)
1297 while (c
!= EOF
&& c
!= '\n')
1304 if (c
== ' ' || c
== '\t')
1313 read_identifier (FILE * f
, int c
, char **identifier
)
1315 GString
*id
= g_string_new ("");
1316 while (isalnum (c
) || c
== '_')
1318 g_string_append_c (id
, c
);
1321 *identifier
= g_string_free (id
, FALSE
);
1326 g_igenerator_parse_macros (GIGenerator
* igenerator
)
1328 GError
*error
= NULL
;
1329 char *tmp_name
= NULL
;
1331 fdopen (g_file_open_tmp ("gen-introspect-XXXXXX.h", &tmp_name
, &error
),
1333 g_unlink (tmp_name
);
1336 for (l
= igenerator
->filenames
; l
!= NULL
; l
= l
->next
)
1338 FILE *f
= fopen (l
->data
, "r");
1341 GString
*define_line
;
1343 gboolean error_line
= FALSE
;
1344 int c
= eat_hspace (f
);
1350 c
= eat_line (f
, c
);
1355 /* print current location */
1356 str
= g_strescape (l
->data
, "");
1357 fprintf (fmacros
, "# %d \"%s\"\n", line
, str
);
1361 c
= read_identifier (f
, c
, &str
);
1362 if (strcmp (str
, "define") != 0 || (c
!= ' ' && c
!= '\t'))
1366 c
= eat_line (f
, c
);
1372 c
= read_identifier (f
, c
, &str
);
1373 if (strlen (str
) == 0 || (c
!= ' ' && c
!= '\t' && c
!= '('))
1377 c
= eat_line (f
, c
);
1381 define_line
= g_string_new ("#define ");
1382 g_string_append (define_line
, str
);
1388 g_string_append_c (define_line
, c
);
1390 if (c
== EOF
|| c
== '\n')
1398 g_string_free (define_line
, TRUE
);
1400 c
= eat_line (f
, c
);
1405 g_assert (c
== ')');
1406 g_string_append_c (define_line
, c
);
1409 /* found function-like macro */
1410 fprintf (fmacros
, "%s\n", define_line
->str
);
1412 g_string_free (define_line
, TRUE
);
1413 /* ignore rest of line */
1414 c
= eat_line (f
, c
);
1418 if (c
!= ' ' && c
!= '\t')
1420 g_string_free (define_line
, TRUE
);
1422 c
= eat_line (f
, c
);
1426 while (c
!= EOF
&& c
!= '\n')
1428 g_string_append_c (define_line
, c
);
1435 /* fold lines when seeing backslash new-line sequence */
1440 g_string_append_c (define_line
, '\\');
1445 /* found object-like macro */
1446 fprintf (fmacros
, "%s\n", define_line
->str
);
1448 c
= eat_line (f
, c
);
1455 igenerator
->macro_scan
= TRUE
;
1458 g_igenerator_parse_file (igenerator
, fmacros
);
1461 igenerator
->macro_scan
= FALSE
;
1465 g_igenerator_add_module (GIGenerator
*igenerator
,
1470 for (l
= module
->entries
; l
; l
= l
->next
)
1472 GIdlNode
*node
= (GIdlNode
*)l
->data
;
1474 if (node
->type
== G_IDL_NODE_OBJECT
)
1476 GIdlNodeInterface
*object
= (GIdlNodeInterface
*)node
;
1478 if (strcmp(module
->name
, igenerator
->namespace) == 0)
1479 name
= g_strdup (node
->name
);
1481 name
= g_strdup_printf ("%s.%s", module
->name
, node
->name
);
1482 g_hash_table_insert (igenerator
->symbols
,
1483 g_strdup (object
->gtype_name
),
1490 g_igenerator_add_include_idl (GIGenerator
*igenerator
,
1491 const gchar
*filename
)
1496 GError
*error
= NULL
;
1498 modules
= g_idl_parse_file (filename
, &error
);
1501 g_printerr ("An error occured while parsing %s: %s\n",
1502 filename
, error
->message
);
1506 for (l
= modules
; l
; l
= l
->next
)
1508 GIdlModule
*module
= (GIdlModule
*)l
->data
;
1509 g_igenerator_add_module (igenerator
, module
);
1514 g_igenerator_start_preprocessor (GIGenerator
*igenerator
,
1517 int cpp_out
= -1, cpp_in
= -1;
1521 GError
*error
= NULL
;
1531 cpp_argv
= g_new0 (char *, g_list_length (cpp_options
) + 4);
1532 cpp_argv
[cpp_argc
++] = "cpp";
1533 cpp_argv
[cpp_argc
++] = "-C";
1535 /* Disable GCC extensions as we cannot parse them yet */
1536 cpp_argv
[cpp_argc
++] = "-U__GNUC__";
1538 for (l
= cpp_options
; l
; l
= l
->next
)
1539 cpp_argv
[cpp_argc
++] = (char*)l
->data
;
1541 cpp_argv
[cpp_argc
++] = NULL
;
1543 if (igenerator
->verbose
)
1545 GString
*args
= g_string_new ("");
1547 for (i
= 0; i
< cpp_argc
- 1; i
++)
1549 g_string_append (args
, cpp_argv
[i
]);
1550 if (i
< cpp_argc
- 2)
1551 g_string_append_c (args
, ' ');
1554 g_printf ("Executing '%s'\n", args
->str
);
1555 g_string_free (args
, FALSE
);
1557 g_spawn_async_with_pipes (NULL
, cpp_argv
, NULL
,
1558 G_SPAWN_SEARCH_PATH
| G_SPAWN_DO_NOT_REAP_CHILD
,
1559 NULL
, NULL
, &pid
, &cpp_in
, &cpp_out
, NULL
, &error
);
1564 g_error ("%s", error
->message
);
1568 f
= fdopen (cpp_in
, "w");
1570 for (l
= igenerator
->filenames
; l
!= NULL
; l
= l
->next
)
1572 if (igenerator
->verbose
)
1573 g_printf ("Pre-processing %s\n", (char*)l
->data
);
1575 fprintf (f
, "#include <%s>\n", (char *) l
->data
);
1582 tmp
= g_file_open_tmp (NULL
, &tmpname
, &error
);
1585 g_error (error
->message
);
1589 buffer
= g_malloc0 (4096 * sizeof (char));
1593 read_bytes
= read (cpp_out
, buffer
, 4096);
1594 if (read_bytes
== 0)
1596 write (tmp
, buffer
, read_bytes
);
1603 if (waitpid (pid
, &status
, 0) > 0)
1607 g_spawn_close_pid (pid
);
1608 kill (pid
, SIGKILL
);
1610 g_error ("cpp returned error code: %d\n", status
);
1617 f
= fdopen (tmp
, "r");
1620 g_error (strerror (errno
));
1634 g_igenerator_set_verbose (GIGenerator
*igenerator
,
1637 igenerator
->verbose
= verbose
;
1641 main (int argc
, char **argv
)
1643 GOptionContext
*ctx
;
1644 gchar
*namespace = NULL
;
1645 gchar
*shared_library
= NULL
;
1646 gchar
**include_idls
= NULL
;
1647 gchar
*output
= NULL
;
1648 gboolean verbose
= FALSE
;
1650 GIGenerator
*igenerator
;
1653 GList
*filenames
= NULL
;
1654 GError
*error
= NULL
;
1655 GList
*l
, *libraries
= NULL
;
1656 GList
*cpp_options
= NULL
;
1660 GOptionEntry entries
[] =
1662 { "verbose", 'v', 0, G_OPTION_ARG_NONE
, &verbose
,
1664 { "output", 'o', 0, G_OPTION_ARG_STRING
, &output
,
1665 "write output here instead of stdout", "FILE" },
1666 { "namespace", 'n', 0, G_OPTION_ARG_STRING
, &namespace,
1667 "Namespace of the module, like 'Gtk'", "NAMESPACE" },
1668 { "shared-library", 0, 0, G_OPTION_ARG_FILENAME
, &shared_library
,
1669 "Shared library which contains the symbols", "FILE" },
1670 { "include-idl", 0, 0, G_OPTION_ARG_STRING_ARRAY
, &include_idls
,
1671 "Other gidls to include", "IDL" },
1676 gopt_argv
= (char**)g_malloc (argc
* sizeof (char*));
1677 gopt_argv
[0] = argv
[0];
1679 for (i
= 1; i
< argc
; i
++)
1681 if (argv
[i
][0] == '-')
1688 cpp_options
= g_list_prepend (cpp_options
, g_strdup (argv
[i
]));
1692 if (0==strcmp("-pthread", argv
[i
]))
1695 gopt_argv
[gopt_argc
++] = argv
[i
];
1699 else if (g_str_has_suffix (argv
[i
], ".h"))
1703 if (!g_path_is_absolute (argv
[i
]))
1705 gchar
*dir
= g_get_current_dir ();
1706 filename
= g_strdup_printf ("%s/%s", dir
,
1711 filename
= g_strdup (argv
[i
]);
1713 filenames
= g_list_append (filenames
, g_realpath(filename
));
1716 else if (g_str_has_suffix (argv
[i
], ".la") ||
1717 g_str_has_suffix (argv
[i
], ".so") ||
1718 g_str_has_suffix (argv
[i
], ".dll"))
1720 libraries
= g_list_prepend (libraries
, g_strdup (argv
[i
]));
1724 gopt_argv
[gopt_argc
++] = argv
[i
];
1728 ctx
= g_option_context_new ("");
1729 g_option_context_add_main_entries (ctx
, entries
, NULL
);
1731 if (!g_option_context_parse (ctx
, &gopt_argc
, &gopt_argv
, &error
))
1733 g_printerr ("Parsing error: %s\n", error
->message
);
1734 g_option_context_free (ctx
);
1739 g_option_context_free (ctx
);
1743 g_printerr ("ERROR: namespace must be specified\n");
1747 igenerator
= g_igenerator_new (namespace, shared_library
);
1750 g_igenerator_set_verbose (igenerator
, TRUE
);
1754 g_printerr ("ERROR: Need at least one header file.\n");
1755 g_igenerator_free (igenerator
);
1758 igenerator
->filenames
= filenames
;
1759 cpp_options
= g_list_reverse (cpp_options
);
1760 libraries
= g_list_reverse (libraries
);
1764 /* initialize threading as this may be required by libraries that we'll use
1765 * libsoup-2.2 is an example of that.
1767 g_thread_init (NULL
);
1771 for (i
= 0; i
< g_strv_length (include_idls
); i
++)
1772 g_igenerator_add_include_idl (igenerator
, include_idls
[i
]);
1775 tmp
= g_igenerator_start_preprocessor (igenerator
, cpp_options
);
1778 g_error ("ERROR in pre-processor.\n");
1779 g_igenerator_free (igenerator
);
1783 if (!g_igenerator_parse_file (igenerator
, tmp
))
1786 g_igenerator_free (igenerator
);
1790 g_igenerator_parse_macros (igenerator
);
1792 g_igenerator_generate (igenerator
, output
, libraries
);
1795 g_igenerator_free (igenerator
);