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>
30 #include <glib/gstdio.h>
31 #include <glib-object.h>
33 #include <sys/wait.h> /* waitpid */
36 #include "gidlparser.h"
37 #include "gidlmodule.h"
39 #include "gidlwriter.h"
40 #include "grealpath.h"
43 typedef GType (*TypeFunction
) (void);
45 static void g_igenerator_parse_macros (GIGenerator
* igenerator
);
48 g_igenerator_new (const gchar
*namespace,
49 const gchar
*shared_library
)
51 GIGenerator
*igenerator
= g_new0 (GIGenerator
, 1);
52 igenerator
->namespace = g_strdup (namespace);
53 igenerator
->shared_library
= g_strdup (shared_library
);
54 igenerator
->lower_case_namespace
=
55 g_ascii_strdown (igenerator
->namespace, -1);
56 igenerator
->module
= g_idl_module_new (namespace, shared_library
);
58 igenerator
->typedef_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
59 igenerator
->struct_or_union_or_enum_table
=
60 g_hash_table_new (g_str_hash
, g_str_equal
);
62 igenerator
->type_map
= g_hash_table_new (g_str_hash
, g_str_equal
);
63 igenerator
->type_by_lower_case_prefix
=
64 g_hash_table_new (g_str_hash
, g_str_equal
);
65 igenerator
->symbols
= g_hash_table_new (g_str_hash
, g_str_equal
);
71 g_igenerator_free (GIGenerator
*generator
)
73 g_free (generator
->namespace);
74 g_free (generator
->shared_library
);
75 g_free (generator
->lower_case_namespace
);
77 g_idl_module_free (generator
->module
);
79 g_hash_table_destroy (generator
->typedef_table
);
80 g_hash_table_destroy (generator
->struct_or_union_or_enum_table
);
81 g_hash_table_destroy (generator
->type_map
);
82 g_hash_table_destroy (generator
->type_by_lower_case_prefix
);
83 g_hash_table_destroy (generator
->symbols
);
84 g_list_foreach (generator
->filenames
, (GFunc
)g_free
, NULL
);
85 g_list_free (generator
->filenames
);
87 g_list_foreach (generator
->symbol_list
, (GFunc
)csymbol_free
, NULL
);
88 g_list_free (generator
->symbol_list
);
94 create_node_from_gtype (GType type_id
)
99 node
= (GIdlNodeType
*) g_idl_node_new (G_IDL_NODE_TYPE
);
101 fundamental
= g_type_fundamental (type_id
);
105 node
->unparsed
= g_strdup ("char*");
107 case G_TYPE_INTERFACE
:
110 node
->unparsed
= g_strdup_printf ("%s*", g_type_name (type_id
));
113 node
->unparsed
= g_strdup ("GParamSpec*");
116 if (fundamental
== G_TYPE_STRV
)
117 node
->unparsed
= g_strdup ("char*[]");
119 node
->unparsed
= g_strdup (g_type_name (type_id
));
126 static GIdlNodeType
*
127 create_node_from_ctype (CType
* ctype
)
131 node
= (GIdlNodeType
*) g_idl_node_new (G_IDL_NODE_TYPE
);
136 node
->unparsed
= g_strdup ("void");
138 case CTYPE_BASIC_TYPE
:
139 node
->unparsed
= g_strdup (ctype
->name
);
142 node
->unparsed
= g_strdup (ctype
->name
);
145 if (ctype
->name
== NULL
)
146 /* anonymous struct */
147 node
->unparsed
= g_strdup ("gpointer");
149 node
->unparsed
= g_strdup_printf ("struct %s", ctype
->name
);
152 if (ctype
->name
== NULL
)
153 /* anonymous union */
154 node
->unparsed
= g_strdup ("gpointer");
156 node
->unparsed
= g_strdup_printf ("union %s", ctype
->name
);
159 if (ctype
->name
== NULL
)
161 node
->unparsed
= g_strdup ("gint");
163 node
->unparsed
= g_strdup_printf ("enum %s", ctype
->name
);
166 if (ctype
->base_type
->type
== CTYPE_FUNCTION
)
167 /* anonymous function pointer */
168 node
->unparsed
= g_strdup ("GCallback");
171 GIdlNodeType
*gibasetype
= create_node_from_ctype (ctype
->base_type
);
172 node
->unparsed
= g_strdup_printf ("%s*", gibasetype
->unparsed
);
177 GIdlNodeType
*gibasetype
= create_node_from_ctype (ctype
->base_type
);
178 node
->unparsed
= g_strdup_printf ("%s[]", gibasetype
->unparsed
);
182 node
->unparsed
= g_strdup ("unknown");
190 str_replace (const char *str
, const char *needle
, const char *replacement
)
192 char **strings
= g_strsplit (str
, needle
, 0);
193 char *result
= g_strjoinv (replacement
, strings
);
194 g_strfreev (strings
);
199 g_igenerator_process_properties (GIGenerator
* igenerator
,
200 GIdlNodeInterface
* node
, GType type_id
)
204 GParamSpec
**properties
;
206 if (node
->node
.type
== G_IDL_NODE_OBJECT
)
208 GObjectClass
*type_class
= g_type_class_ref (type_id
);
209 properties
= g_object_class_list_properties (type_class
, &n_properties
);
211 else if (node
->node
.type
== G_IDL_NODE_INTERFACE
)
213 GTypeInterface
*iface
= g_type_default_interface_ref (type_id
);
214 properties
= g_object_interface_list_properties (iface
, &n_properties
);
218 g_assert_not_reached ();
221 for (i
= 0; i
< n_properties
; i
++)
223 GIdlNodeProperty
*giprop
;
225 /* ignore inherited properties */
226 if (properties
[i
]->owner_type
!= type_id
)
230 giprop
= (GIdlNodeProperty
*) g_idl_node_new (G_IDL_NODE_PROPERTY
);
231 giprop
->node
.name
= properties
[i
]->name
;
233 g_list_insert_sorted (node
->members
, giprop
,
234 (GCompareFunc
) g_idl_node_cmp
);
235 giprop
->type
= create_node_from_gtype (properties
[i
]->value_type
);
236 giprop
->readable
= (properties
[i
]->flags
& G_PARAM_READABLE
) != 0;
237 giprop
->writable
= (properties
[i
]->flags
& G_PARAM_WRITABLE
) != 0;
238 giprop
->construct
= (properties
[i
]->flags
& G_PARAM_CONSTRUCT
) != 0;
239 giprop
->construct_only
=
240 (properties
[i
]->flags
& G_PARAM_CONSTRUCT_ONLY
) != 0;
245 g_igenerator_process_signals (GIGenerator
* igenerator
,
246 GIdlNodeInterface
* node
, GType type_id
)
250 guint
*signal_ids
= g_signal_list_ids (type_id
, &n_signal_ids
);
252 for (i
= 0; i
< n_signal_ids
; i
++)
254 GSignalQuery signal_query
;
255 GIdlNodeSignal
*gisig
;
256 GIdlNodeParam
*giparam
;
258 g_signal_query (signal_ids
[i
], &signal_query
);
259 gisig
= (GIdlNodeSignal
*) g_idl_node_new (G_IDL_NODE_SIGNAL
);
260 gisig
->node
.name
= g_strdup (signal_query
.signal_name
);
262 g_list_insert_sorted (node
->members
, gisig
,
263 (GCompareFunc
) g_idl_node_cmp
);
266 (signal_query
.signal_flags
& G_SIGNAL_RUN_FIRST
) != 0;
267 gisig
->run_last
= (signal_query
.signal_flags
& G_SIGNAL_RUN_LAST
) != 0;
269 (signal_query
.signal_flags
& G_SIGNAL_RUN_CLEANUP
) != 0;
271 /* add sender parameter */
272 giparam
= (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
273 gisig
->parameters
= g_list_append (gisig
->parameters
, giparam
);
274 giparam
->node
.name
= g_strdup ("object");
275 giparam
->type
= create_node_from_gtype (type_id
);
277 for (j
= 0; j
< signal_query
.n_params
; j
++)
279 giparam
= (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
280 gisig
->parameters
= g_list_append (gisig
->parameters
, giparam
);
281 giparam
->node
.name
= g_strdup_printf ("p%d", j
);
282 giparam
->type
= create_node_from_gtype (signal_query
.param_types
[j
]);
284 gisig
->result
= (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
285 gisig
->result
->type
= create_node_from_gtype (signal_query
.return_type
);
290 lookup_symbol (GIGenerator
*igenerator
, const gchar
*typename
)
293 g_hash_table_lookup (igenerator
->symbols
, typename
);
297 g_printerr ("Unknown symbol: %s\n", typename
);
305 g_igenerator_create_object (GIGenerator
*igenerator
,
306 const char *symbol_name
,
308 char *lower_case_prefix
)
311 char *alt_lower_case_prefix
;
312 GIdlNodeInterface
*node
;
313 guint n_type_interfaces
;
314 GType
*type_interfaces
;
317 node
= (GIdlNodeInterface
*) g_idl_node_new (G_IDL_NODE_OBJECT
);
318 node
->node
.name
= g_strdup (g_type_name (type_id
));
319 igenerator
->module
->entries
=
320 g_list_insert_sorted (igenerator
->module
->entries
, node
,
321 (GCompareFunc
) g_idl_node_cmp
);
322 g_hash_table_insert (igenerator
->type_map
, node
->node
.name
,
324 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
325 lower_case_prefix
, node
);
326 alt_lower_case_prefix
= g_ascii_strdown (node
->node
.name
, -1);
328 if (strcmp (alt_lower_case_prefix
, lower_case_prefix
) != 0)
330 /* alternative prefix sometimes necessary, for example
333 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
334 alt_lower_case_prefix
, node
);
338 g_free (alt_lower_case_prefix
);
341 node
->gtype_name
= node
->node
.name
;
342 node
->gtype_init
= g_strdup (symbol_name
);
343 node
->parent
= g_strdup (lookup_symbol (igenerator
,
344 g_type_name (g_type_parent (type_id
))));
346 type_interfaces
= g_type_interfaces (type_id
, &n_type_interfaces
);
347 for (i
= 0; i
< n_type_interfaces
; i
++)
350 g_strdup (g_type_name (type_interfaces
[i
]));
351 /* workaround for AtkImplementorIface */
352 if (g_str_has_suffix (iface_name
, "Iface"))
354 iface_name
[strlen (iface_name
) - strlen ("Iface")] =
358 g_list_append (node
->interfaces
, iface_name
);
361 g_hash_table_insert (igenerator
->symbols
,
362 g_strdup (node
->gtype_name
),
363 /* FIXME: Strip igenerator->namespace */
364 g_strdup (node
->node
.name
));
366 g_igenerator_process_properties (igenerator
, node
, type_id
);
367 g_igenerator_process_signals (igenerator
, node
, type_id
);
371 g_igenerator_create_interface (GIGenerator
*igenerator
,
372 const char *symbol_name
,
374 char *lower_case_prefix
)
377 GIdlNodeInterface
*node
;
378 gboolean is_gobject
= FALSE
;
379 guint n_iface_prereqs
;
380 GType
*iface_prereqs
;
383 node
= (GIdlNodeInterface
*) g_idl_node_new (G_IDL_NODE_INTERFACE
);
384 node
->node
.name
= g_strdup (g_type_name (type_id
));
386 /* workaround for AtkImplementorIface */
387 if (g_str_has_suffix (node
->node
.name
, "Iface"))
389 node
->node
.name
[strlen (node
->node
.name
) -
390 strlen ("Iface")] = '\0';
392 igenerator
->module
->entries
=
393 g_list_insert_sorted (igenerator
->module
->entries
, node
,
394 (GCompareFunc
) g_idl_node_cmp
);
395 g_hash_table_insert (igenerator
->type_map
, node
->node
.name
,
397 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
398 lower_case_prefix
, node
);
399 node
->gtype_name
= node
->node
.name
;
400 node
->gtype_init
= g_strdup (symbol_name
);
403 g_type_interface_prerequisites (type_id
, &n_iface_prereqs
);
405 for (i
= 0; i
< n_iface_prereqs
; i
++)
407 if (g_type_fundamental (iface_prereqs
[i
]) == G_TYPE_OBJECT
)
411 node
->prerequisites
=
412 g_list_append (node
->prerequisites
,
413 g_strdup (g_type_name (iface_prereqs
[i
])));
417 g_igenerator_process_properties (igenerator
, node
, type_id
);
419 g_type_default_interface_ref (type_id
);
421 g_igenerator_process_signals (igenerator
, node
, type_id
);
425 g_igenerator_create_boxed (GIGenerator
*igenerator
,
426 const char *symbol_name
,
428 char *lower_case_prefix
)
430 GIdlNodeBoxed
*node
=
431 (GIdlNodeBoxed
*) g_idl_node_new (G_IDL_NODE_BOXED
);
432 node
->node
.name
= g_strdup (g_type_name (type_id
));
433 igenerator
->module
->entries
=
434 g_list_insert_sorted (igenerator
->module
->entries
, node
,
435 (GCompareFunc
) g_idl_node_cmp
);
436 g_hash_table_insert (igenerator
->type_map
, node
->node
.name
,
438 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
439 lower_case_prefix
, node
);
440 node
->gtype_name
= node
->node
.name
;
441 node
->gtype_init
= g_strdup (symbol_name
);
445 g_igenerator_create_enum (GIGenerator
*igenerator
,
446 const char *symbol_name
,
448 char *lower_case_prefix
)
452 GEnumClass
*type_class
;
454 node
= (GIdlNodeEnum
*) g_idl_node_new (G_IDL_NODE_ENUM
);
455 node
->node
.name
= g_strdup (g_type_name (type_id
));
456 igenerator
->module
->entries
=
457 g_list_insert_sorted (igenerator
->module
->entries
, node
,
458 (GCompareFunc
) g_idl_node_cmp
);
459 g_hash_table_insert (igenerator
->type_map
, node
->node
.name
,
461 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
462 lower_case_prefix
, node
);
463 node
->gtype_name
= node
->node
.name
;
464 node
->gtype_init
= g_strdup (symbol_name
);
466 type_class
= g_type_class_ref (type_id
);
468 for (i
= 0; i
< type_class
->n_values
; i
++)
470 GIdlNodeValue
*gival
=
471 (GIdlNodeValue
*) g_idl_node_new (G_IDL_NODE_VALUE
);
472 node
->values
= g_list_append (node
->values
, gival
);
474 g_strdup (type_class
->values
[i
].value_name
);
475 gival
->value
= type_class
->values
[i
].value
;
480 g_igenerator_create_flags (GIGenerator
*igenerator
,
481 const char *symbol_name
,
483 char *lower_case_prefix
)
486 GFlagsClass
*type_class
;
489 node
= (GIdlNodeEnum
*) g_idl_node_new (G_IDL_NODE_FLAGS
);
490 node
->node
.name
= g_strdup (g_type_name (type_id
));
491 igenerator
->module
->entries
=
492 g_list_insert_sorted (igenerator
->module
->entries
, node
,
493 (GCompareFunc
) g_idl_node_cmp
);
494 g_hash_table_insert (igenerator
->type_map
, node
->node
.name
,
496 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
497 lower_case_prefix
, node
);
498 node
->gtype_name
= node
->node
.name
;
499 node
->gtype_init
= g_strdup (symbol_name
);
501 type_class
= g_type_class_ref (type_id
);
503 for (i
= 0; i
< type_class
->n_values
; i
++)
505 GIdlNodeValue
*gival
=
506 (GIdlNodeValue
*) g_idl_node_new (G_IDL_NODE_VALUE
);
507 node
->values
= g_list_append (node
->values
, gival
);
509 g_strdup (type_class
->values
[i
].value_name
);
510 gival
->value
= type_class
->values
[i
].value
;
515 g_igenerator_process_module_symbol (GIGenerator
*igenerator
,
517 const gchar
*symbol_name
)
519 TypeFunction type_fun
;
521 GType type_fundamental
;
522 char *lower_case_prefix
;
524 /* ignore already processed functions */
525 if (symbol_name
== NULL
)
528 if (!g_module_symbol (module
,
530 (gpointer
*) & type_fun
))
533 type_id
= type_fun ();
534 type_fundamental
= g_type_fundamental (type_id
);
536 str_replace (g_strndup
538 strlen (symbol_name
) - strlen ("_get_type")),
541 switch (type_fundamental
)
544 g_igenerator_create_object (igenerator
, symbol_name
, type_id
,
547 case G_TYPE_INTERFACE
:
548 g_igenerator_create_interface (igenerator
, symbol_name
, type_id
,
552 g_igenerator_create_boxed (igenerator
, symbol_name
, type_id
,
556 g_igenerator_create_enum (igenerator
, symbol_name
, type_id
,
560 g_igenerator_create_flags (igenerator
, symbol_name
, type_id
,
570 g_igenerator_process_module (GIGenerator
* igenerator
,
571 const gchar
*filename
)
576 module
= g_module_open (filename
,
577 G_MODULE_BIND_LAZY
| G_MODULE_BIND_LOCAL
);
581 g_critical ("Couldn't open module: %s", filename
);
585 for (l
= igenerator
->get_type_symbols
; l
!= NULL
; l
= l
->next
)
587 if (g_igenerator_process_module_symbol (igenerator
,
588 module
, (const char *)l
->data
))
589 /* symbol found, ignore in future iterations */
595 g_igenerator_process_function_symbol (GIGenerator
* igenerator
, CSymbol
* sym
)
597 GIdlNodeFunction
*func
;
598 char *last_underscore
;
603 func
= (GIdlNodeFunction
*) g_idl_node_new (G_IDL_NODE_FUNCTION
);
605 /* check whether this is a type method */
606 last_underscore
= strrchr (sym
->ident
, '_');
608 while (last_underscore
!= NULL
)
613 prefix
= g_strndup (sym
->ident
, last_underscore
- sym
->ident
);
614 prefix
= str_replace (prefix
, "_", "");
616 node
= g_hash_table_lookup (igenerator
->type_by_lower_case_prefix
,
620 func
->node
.name
= g_strdup (last_underscore
+ 1);
622 /* ignore get_type functions in registered types */
623 if (strcmp (func
->node
.name
, "get_type") == 0)
626 if ((node
->type
== G_IDL_NODE_OBJECT
||
627 node
->type
== G_IDL_NODE_BOXED
) &&
628 g_str_has_prefix (func
->node
.name
, "new"))
629 func
->is_constructor
= TRUE
;
631 func
->is_method
= TRUE
;
632 if (g_idl_node_can_have_member (node
))
634 g_idl_node_add_member (node
, func
);
639 /* reset function attributes */
640 g_free (func
->node
.name
);
641 func
->node
.name
= NULL
;
642 func
->is_constructor
= FALSE
;
643 func
->is_method
= FALSE
;
646 else if (strcmp (igenerator
->lower_case_namespace
, prefix
) == 0)
648 func
->node
.name
= g_strdup (last_underscore
+ 1);
649 igenerator
->module
->entries
=
650 g_list_insert_sorted (igenerator
->module
->entries
, func
,
651 (GCompareFunc
) g_idl_node_cmp
);
655 g_utf8_strrchr (sym
->ident
, last_underscore
- sym
->ident
, '_');
658 /* create a namespace function if no prefix matches */
659 if (func
->node
.name
== NULL
)
661 func
->node
.name
= sym
->ident
;
662 func
->is_constructor
= FALSE
;
663 func
->is_method
= FALSE
;
664 igenerator
->module
->entries
=
665 g_list_insert_sorted (igenerator
->module
->entries
, func
,
666 (GCompareFunc
) g_idl_node_cmp
);
669 func
->symbol
= sym
->ident
;
670 func
->result
= (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
671 func
->result
->type
= create_node_from_ctype (sym
->base_type
->base_type
);
673 for (param_l
= sym
->base_type
->child_list
, i
= 1; param_l
!= NULL
;
674 param_l
= param_l
->next
, i
++)
676 CSymbol
*param_sym
= param_l
->data
;
677 GIdlNodeParam
*param
;
679 param
= (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
680 param
->type
= create_node_from_ctype (param_sym
->base_type
);
682 if (param_sym
->ident
== NULL
)
683 param
->node
.name
= g_strdup_printf ("p%d", i
);
685 param
->node
.name
= param_sym
->ident
;
687 func
->parameters
= g_list_append (func
->parameters
, param
);
690 for (l
= sym
->directives
; l
; l
= l
->next
)
692 CDirective
*directive
= (CDirective
*)l
->data
;
694 if (!strcmp (directive
->name
, "deprecated"))
695 func
->deprecated
= TRUE
;
697 g_printerr ("Unknown function directive: %s\n",
703 g_igenerator_process_unregistered_struct_typedef (GIGenerator
* igenerator
,
707 GIdlNodeStruct
*node
=
708 (GIdlNodeStruct
*) g_idl_node_new (G_IDL_NODE_STRUCT
);
710 char *lower_case_prefix
;
712 node
->node
.name
= sym
->ident
;
713 igenerator
->module
->entries
=
714 g_list_insert_sorted (igenerator
->module
->entries
, node
,
715 (GCompareFunc
) g_idl_node_cmp
);
716 lower_case_prefix
= g_ascii_strdown (sym
->ident
, -1);
717 g_hash_table_insert (igenerator
->type_map
, sym
->ident
, node
);
718 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
719 lower_case_prefix
, node
);
721 for (member_l
= struct_type
->child_list
; member_l
!= NULL
;
722 member_l
= member_l
->next
)
724 CSymbol
*member
= member_l
->data
;
725 GIdlNodeField
*gifield
=
726 (GIdlNodeField
*) g_idl_node_new (G_IDL_NODE_FIELD
);
728 node
->members
= g_list_append (node
->members
, gifield
);
729 gifield
->node
.name
= member
->ident
;
730 gifield
->type
= create_node_from_ctype (member
->base_type
);
735 g_igenerator_process_struct_typedef (GIGenerator
* igenerator
, CSymbol
* sym
)
737 CType
*struct_type
= sym
->base_type
;
738 gboolean opaque_type
= FALSE
;
741 if (struct_type
->child_list
== NULL
)
743 CSymbol
*struct_symbol
;
744 g_assert (struct_type
->name
!= NULL
);
746 g_hash_table_lookup (igenerator
->struct_or_union_or_enum_table
,
748 if (struct_symbol
!= NULL
)
750 struct_type
= struct_symbol
->base_type
;
754 if (struct_type
->child_list
== NULL
)
759 type
= g_hash_table_lookup (igenerator
->type_map
, sym
->ident
);
762 /* struct of a GTypeInstance */
764 && (type
->type
== G_IDL_NODE_OBJECT
765 || type
->type
== G_IDL_NODE_INTERFACE
))
767 GIdlNodeInterface
*node
= (GIdlNodeInterface
*) type
;
769 /* ignore first field => parent */
770 for (member_l
= struct_type
->child_list
->next
; member_l
!= NULL
;
771 member_l
= member_l
->next
)
773 CSymbol
*member
= member_l
->data
;
774 /* ignore private / reserved members */
775 if (member
->ident
[0] == '_'
776 || g_str_has_prefix (member
->ident
, "priv"))
780 GIdlNodeField
*gifield
=
781 (GIdlNodeField
*) g_idl_node_new (G_IDL_NODE_FIELD
);
782 node
->members
= g_list_append (node
->members
, gifield
);
783 gifield
->node
.name
= member
->ident
;
784 gifield
->type
= create_node_from_ctype (member
->base_type
);
787 else if (type
->type
== G_IDL_NODE_BOXED
)
789 GIdlNodeBoxed
*node
= (GIdlNodeBoxed
*) type
;
791 for (member_l
= struct_type
->child_list
; member_l
!= NULL
;
792 member_l
= member_l
->next
)
794 CSymbol
*member
= member_l
->data
;
795 GIdlNodeField
*gifield
=
796 (GIdlNodeField
*) g_idl_node_new (G_IDL_NODE_FIELD
);
797 node
->members
= g_list_append (node
->members
, gifield
);
798 gifield
->node
.name
= member
->ident
;
799 gifield
->type
= create_node_from_ctype (member
->base_type
);
803 else if (!opaque_type
804 && (g_str_has_suffix (sym
->ident
, "Class")
805 || g_str_has_suffix (sym
->ident
, "Iface")
806 || g_str_has_suffix (sym
->ident
, "Interface")))
810 GIdlNodeInterface
*node
;
812 if (g_str_has_suffix (sym
->ident
, "Interface"))
815 g_strndup (sym
->ident
,
816 strlen (sym
->ident
) - strlen ("Interface"));
821 g_strndup (sym
->ident
, strlen (sym
->ident
) - strlen ("Class"));
823 type
= g_hash_table_lookup (igenerator
->type_map
, base_name
);
825 || (type
->type
!= G_IDL_NODE_OBJECT
826 && type
->type
!= G_IDL_NODE_INTERFACE
))
828 g_igenerator_process_unregistered_struct_typedef (igenerator
, sym
,
832 node
= (GIdlNodeInterface
*) type
;
834 /* ignore first field => parent */
835 for (member_l
= struct_type
->child_list
->next
; member_l
!= NULL
;
836 member_l
= member_l
->next
)
838 CSymbol
*member
= member_l
->data
;
839 /* ignore private / reserved members */
840 if (member
->ident
[0] == '_')
844 if (member
->base_type
->type
== CTYPE_POINTER
845 && member
->base_type
->base_type
->type
== CTYPE_FUNCTION
)
847 /* ignore default handlers of signals */
848 gboolean found_signal
= FALSE
;
849 GList
*type_member_l
;
852 GIdlNodeVFunc
*givfunc
;
854 for (type_member_l
= node
->members
; type_member_l
!= NULL
;
855 type_member_l
= type_member_l
->next
)
857 GIdlNode
*type_member
= type_member_l
->data
;
858 char *normalized_name
=
859 str_replace (type_member
->name
, "-", "_");
860 if (type_member
->type
== G_IDL_NODE_SIGNAL
861 && strcmp (normalized_name
, member
->ident
) == 0)
863 GList
*vfunc_param_l
;
865 GIdlNodeSignal
*sig
= (GIdlNodeSignal
*) type_member
;
867 /* set signal parameter names */
869 member
->base_type
->base_type
->child_list
,
870 sig_param_l
= sig
->parameters
;
871 vfunc_param_l
!= NULL
&& sig_param_l
!= NULL
;
872 vfunc_param_l
= vfunc_param_l
->next
, sig_param_l
=
875 CSymbol
*vfunc_param
= vfunc_param_l
->data
;
876 GIdlNodeParam
*sig_param
= sig_param_l
->data
;
877 if (vfunc_param
->ident
!= NULL
)
879 g_free (sig_param
->node
.name
);
880 sig_param
->node
.name
=
881 g_strdup (vfunc_param
->ident
);
892 givfunc
= (GIdlNodeVFunc
*) g_idl_node_new (G_IDL_NODE_VFUNC
);
893 givfunc
->node
.name
= member
->ident
;
895 g_list_insert_sorted (node
->members
, givfunc
,
896 (GCompareFunc
) g_idl_node_cmp
);
898 (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
899 givfunc
->result
->type
=
900 create_node_from_ctype (member
->base_type
->base_type
->base_type
);
901 for (param_l
= member
->base_type
->base_type
->child_list
, i
= 1;
902 param_l
!= NULL
; param_l
= param_l
->next
, i
++)
904 CSymbol
*param_sym
= param_l
->data
;
905 GIdlNodeParam
*param
=
906 (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
907 if (param_sym
->ident
== NULL
)
909 param
->node
.name
= g_strdup_printf ("p%d", i
);
913 param
->node
.name
= param_sym
->ident
;
915 param
->type
= create_node_from_ctype (param_sym
->base_type
);
916 givfunc
->parameters
=
917 g_list_append (givfunc
->parameters
, param
);
922 else if (g_str_has_suffix (sym
->ident
, "Private"))
924 /* ignore private structs */
928 g_igenerator_process_unregistered_struct_typedef (igenerator
, sym
,
934 g_igenerator_process_union_typedef (GIGenerator
* igenerator
, CSymbol
* sym
)
936 CType
*union_type
= sym
->base_type
;
937 gboolean opaque_type
= FALSE
;
940 if (union_type
->child_list
== NULL
)
942 g_assert (union_type
->name
!= NULL
);
943 CSymbol
*union_symbol
=
944 g_hash_table_lookup (igenerator
->struct_or_union_or_enum_table
,
946 if (union_symbol
!= NULL
)
948 union_type
= union_symbol
->base_type
;
951 if (union_type
->child_list
== NULL
)
956 type
= g_hash_table_lookup (igenerator
->type_map
, sym
->ident
);
959 g_assert (type
->type
== G_IDL_NODE_BOXED
);
960 GIdlNodeBoxed
*node
= (GIdlNodeBoxed
*) type
;
962 for (member_l
= union_type
->child_list
; member_l
!= NULL
;
963 member_l
= member_l
->next
)
965 CSymbol
*member
= member_l
->data
;
966 GIdlNodeField
*gifield
=
967 (GIdlNodeField
*) g_idl_node_new (G_IDL_NODE_FIELD
);
968 node
->members
= g_list_append (node
->members
, gifield
);
969 gifield
->node
.name
= member
->ident
;
970 gifield
->type
= create_node_from_ctype (member
->base_type
);
975 GIdlNodeUnion
*node
=
976 (GIdlNodeUnion
*) g_idl_node_new (G_IDL_NODE_UNION
);
977 char *lower_case_prefix
;
980 node
->node
.name
= sym
->ident
;
981 igenerator
->module
->entries
=
982 g_list_insert_sorted (igenerator
->module
->entries
, node
,
983 (GCompareFunc
) g_idl_node_cmp
);
984 lower_case_prefix
= g_ascii_strdown (sym
->ident
, -1);
985 g_hash_table_insert (igenerator
->type_map
, sym
->ident
, node
);
986 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
987 lower_case_prefix
, node
);
989 node
->node
.name
= sym
->ident
;
990 for (member_l
= union_type
->child_list
; member_l
!= NULL
;
991 member_l
= member_l
->next
)
993 CSymbol
*member
= member_l
->data
;
994 GIdlNodeField
*gifield
=
995 (GIdlNodeField
*) g_idl_node_new (G_IDL_NODE_FIELD
);
996 node
->members
= g_list_append (node
->members
, gifield
);
997 gifield
->node
.name
= member
->ident
;
998 gifield
->type
= create_node_from_ctype (member
->base_type
);
1004 g_igenerator_process_enum_typedef (GIGenerator
* igenerator
, CSymbol
* sym
)
1009 CSymbol
*enum_symbol
;
1011 enum_type
= sym
->base_type
;
1012 if (enum_type
->child_list
== NULL
)
1014 g_assert (enum_type
->name
!= NULL
);
1016 g_hash_table_lookup (igenerator
->struct_or_union_or_enum_table
,
1018 if (enum_symbol
!= NULL
)
1020 enum_type
= enum_symbol
->base_type
;
1023 if (enum_type
->child_list
== NULL
)
1029 node
= g_hash_table_lookup (igenerator
->type_map
, sym
->ident
);
1035 node
= (GIdlNodeEnum
*) g_idl_node_new (G_IDL_NODE_ENUM
);
1036 node
->node
.name
= sym
->ident
;
1037 igenerator
->module
->entries
=
1038 g_list_insert_sorted (igenerator
->module
->entries
, node
,
1039 (GCompareFunc
) g_idl_node_cmp
);
1041 for (member_l
= enum_type
->child_list
; member_l
!= NULL
;
1042 member_l
= member_l
->next
)
1044 CSymbol
*member
= member_l
->data
;
1045 GIdlNodeValue
*gival
=
1046 (GIdlNodeValue
*) g_idl_node_new (G_IDL_NODE_VALUE
);
1047 node
->values
= g_list_append (node
->values
, gival
);
1048 gival
->node
.name
= member
->ident
;
1049 gival
->value
= member
->const_int
;
1054 g_igenerator_process_function_typedef (GIGenerator
* igenerator
,
1060 /* handle callback types */
1061 GIdlNodeFunction
*gifunc
=
1062 (GIdlNodeFunction
*) g_idl_node_new (G_IDL_NODE_CALLBACK
);
1064 gifunc
->node
.name
= sym
->ident
;
1065 igenerator
->module
->entries
=
1066 g_list_insert_sorted (igenerator
->module
->entries
, gifunc
,
1067 (GCompareFunc
) g_idl_node_cmp
);
1069 gifunc
->symbol
= sym
->ident
;
1070 gifunc
->result
= (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
1071 gifunc
->result
->type
=
1072 create_node_from_ctype (sym
->base_type
->base_type
->base_type
);
1074 for (param_l
= sym
->base_type
->base_type
->child_list
, i
= 1;
1075 param_l
!= NULL
; param_l
= param_l
->next
, i
++)
1077 CSymbol
*param_sym
= param_l
->data
;
1078 GIdlNodeParam
*param
=
1079 (GIdlNodeParam
*) g_idl_node_new (G_IDL_NODE_PARAM
);
1080 if (param_sym
->ident
== NULL
)
1082 param
->node
.name
= g_strdup_printf ("p%d", i
);
1086 param
->node
.name
= param_sym
->ident
;
1088 param
->type
= create_node_from_ctype (param_sym
->base_type
);
1089 gifunc
->parameters
= g_list_append (gifunc
->parameters
, param
);
1094 g_igenerator_process_constant (GIGenerator
* igenerator
, CSymbol
* sym
)
1096 GIdlNodeConstant
*giconst
=
1097 (GIdlNodeConstant
*) g_idl_node_new (G_IDL_NODE_CONSTANT
);
1098 giconst
->node
.name
= sym
->ident
;
1099 igenerator
->module
->entries
=
1100 g_list_insert_sorted (igenerator
->module
->entries
, giconst
,
1101 (GCompareFunc
) g_idl_node_cmp
);
1103 giconst
->type
= (GIdlNodeType
*) g_idl_node_new (G_IDL_NODE_TYPE
);
1104 if (sym
->const_int_set
)
1106 giconst
->type
->unparsed
= g_strdup ("int");
1107 giconst
->value
= g_strdup_printf ("%d", sym
->const_int
);
1109 else if (sym
->const_string
!= NULL
)
1111 giconst
->type
->unparsed
= g_strdup ("char*");
1112 giconst
->value
= sym
->const_string
;
1117 g_igenerator_process_symbols (GIGenerator
* igenerator
)
1120 /* process type symbols first to ensure complete type hashtables */
1122 for (l
= igenerator
->symbol_list
; l
!= NULL
; l
= l
->next
)
1124 CSymbol
*sym
= l
->data
;
1125 if (sym
->ident
[0] == '_')
1127 /* ignore private / reserved symbols */
1130 if (sym
->type
== CSYMBOL_TYPE_TYPEDEF
)
1132 if (sym
->base_type
->type
== CTYPE_STRUCT
)
1134 g_igenerator_process_struct_typedef (igenerator
, sym
);
1136 else if (sym
->base_type
->type
== CTYPE_UNION
)
1138 g_igenerator_process_union_typedef (igenerator
, sym
);
1140 else if (sym
->base_type
->type
== CTYPE_ENUM
)
1142 g_igenerator_process_enum_typedef (igenerator
, sym
);
1144 else if (sym
->base_type
->type
== CTYPE_POINTER
1145 && sym
->base_type
->base_type
->type
== CTYPE_FUNCTION
)
1147 g_igenerator_process_function_typedef (igenerator
, sym
);
1151 GIdlNodeStruct
*node
=
1152 (GIdlNodeStruct
*) g_idl_node_new (G_IDL_NODE_STRUCT
);
1153 char *lower_case_prefix
;
1155 node
->node
.name
= sym
->ident
;
1156 igenerator
->module
->entries
=
1157 g_list_insert_sorted (igenerator
->module
->entries
, node
,
1158 (GCompareFunc
) g_idl_node_cmp
);
1159 lower_case_prefix
= g_ascii_strdown (sym
->ident
, -1);
1160 g_hash_table_insert (igenerator
->type_map
, sym
->ident
, node
);
1161 g_hash_table_insert (igenerator
->type_by_lower_case_prefix
,
1162 lower_case_prefix
, node
);
1167 for (l
= igenerator
->symbol_list
; l
!= NULL
; l
= l
->next
)
1169 CSymbol
*sym
= l
->data
;
1170 if (sym
->ident
[0] == '_')
1172 /* ignore private / reserved symbols */
1175 if (sym
->type
== CSYMBOL_TYPE_FUNCTION
)
1177 g_igenerator_process_function_symbol (igenerator
, sym
);
1179 else if (sym
->type
== CSYMBOL_TYPE_CONST
)
1181 g_igenerator_process_constant (igenerator
, sym
);
1187 g_igenerator_add_symbol (GIGenerator
* igenerator
, CSymbol
* symbol
)
1191 /* only add symbols of main file */
1192 gboolean found_filename
= FALSE
;
1194 if (igenerator
->current_filename
)
1196 for (l
= igenerator
->filenames
; l
!= NULL
; l
= l
->next
)
1198 if (strcmp (l
->data
, igenerator
->current_filename
) == 0)
1200 found_filename
= TRUE
;
1206 symbol
->directives
= g_slist_reverse (igenerator
->directives
);
1207 igenerator
->directives
= NULL
;
1209 /* that's not very optimized ! */
1210 for (l
= igenerator
->symbol_list
; l
!= NULL
; l
= l
->next
)
1212 CSymbol
*other_symbol
= (CSymbol
*)l
->data
;
1213 if (g_str_equal (other_symbol
->ident
, symbol
->ident
)
1214 && other_symbol
->type
== symbol
->type
)
1216 g_printerr ("Dropping %s duplicate\n", symbol
->ident
);
1221 if (found_filename
|| igenerator
->macro_scan
)
1223 igenerator
->symbol_list
=
1224 g_list_prepend (igenerator
->symbol_list
, symbol
);
1227 if (symbol
->type
== CSYMBOL_TYPE_TYPEDEF
)
1230 g_hash_table_insert (igenerator
->typedef_table
, symbol
->ident
, symbol
);
1232 else if (symbol
->type
== CSYMBOL_TYPE_STRUCT
1233 || symbol
->type
== CSYMBOL_TYPE_UNION
1234 || symbol
->type
== CSYMBOL_TYPE_ENUM
)
1236 g_hash_table_insert (igenerator
->struct_or_union_or_enum_table
,
1237 symbol
->ident
, symbol
);
1242 g_igenerator_is_typedef (GIGenerator
* igenerator
, const char *name
)
1244 gboolean b
= g_hash_table_lookup (igenerator
->typedef_table
, name
) != NULL
;
1249 g_igenerator_generate (GIGenerator
* igenerator
,
1250 const gchar
* filename
,
1255 for (l
= igenerator
->symbol_list
; l
!= NULL
; l
= l
->next
)
1257 CSymbol
*sym
= l
->data
;
1258 if (sym
->type
== CSYMBOL_TYPE_FUNCTION
1259 && g_str_has_suffix (sym
->ident
, "_get_type"))
1261 if (sym
->base_type
->child_list
== NULL
)
1263 // ignore get_type functions with parameters
1264 igenerator
->get_type_symbols
=
1265 g_list_prepend (igenerator
->get_type_symbols
, sym
->ident
);
1270 /* ensure to initialize GObject */
1271 g_type_class_ref (G_TYPE_OBJECT
);
1273 for (l
= libraries
; l
; l
= l
->next
)
1274 g_igenerator_process_module (igenerator
, (const gchar
*)l
->data
);
1276 g_igenerator_process_symbols (igenerator
);
1278 g_idl_writer_save_file (igenerator
->module
, filename
);
1282 eat_hspace (FILE * f
)
1289 while (c
== ' ' || c
== '\t');
1294 eat_line (FILE * f
, int c
)
1296 while (c
!= EOF
&& c
!= '\n')
1303 if (c
== ' ' || c
== '\t')
1312 read_identifier (FILE * f
, int c
, char **identifier
)
1314 GString
*id
= g_string_new ("");
1315 while (isalnum (c
) || c
== '_')
1317 g_string_append_c (id
, c
);
1320 *identifier
= g_string_free (id
, FALSE
);
1325 g_igenerator_parse_macros (GIGenerator
* igenerator
)
1327 GError
*error
= NULL
;
1328 char *tmp_name
= NULL
;
1330 fdopen (g_file_open_tmp ("gen-introspect-XXXXXX.h", &tmp_name
, &error
),
1332 g_unlink (tmp_name
);
1335 for (l
= igenerator
->filenames
; l
!= NULL
; l
= l
->next
)
1337 FILE *f
= fopen (l
->data
, "r");
1340 GString
*define_line
;
1342 gboolean error_line
= FALSE
;
1343 int c
= eat_hspace (f
);
1349 c
= eat_line (f
, c
);
1354 /* print current location */
1355 str
= g_strescape (l
->data
, "");
1356 fprintf (fmacros
, "# %d \"%s\"\n", line
, str
);
1360 c
= read_identifier (f
, c
, &str
);
1361 if (strcmp (str
, "define") != 0 || (c
!= ' ' && c
!= '\t'))
1365 c
= eat_line (f
, c
);
1371 c
= read_identifier (f
, c
, &str
);
1372 if (strlen (str
) == 0 || (c
!= ' ' && c
!= '\t' && c
!= '('))
1376 c
= eat_line (f
, c
);
1380 define_line
= g_string_new ("#define ");
1381 g_string_append (define_line
, str
);
1387 g_string_append_c (define_line
, c
);
1389 if (c
== EOF
|| c
== '\n')
1397 g_string_free (define_line
, TRUE
);
1399 c
= eat_line (f
, c
);
1404 g_assert (c
== ')');
1405 g_string_append_c (define_line
, c
);
1408 /* found function-like macro */
1409 fprintf (fmacros
, "%s\n", define_line
->str
);
1411 g_string_free (define_line
, TRUE
);
1412 /* ignore rest of line */
1413 c
= eat_line (f
, c
);
1417 if (c
!= ' ' && c
!= '\t')
1419 g_string_free (define_line
, TRUE
);
1421 c
= eat_line (f
, c
);
1425 while (c
!= EOF
&& c
!= '\n')
1427 g_string_append_c (define_line
, c
);
1434 /* fold lines when seeing backslash new-line sequence */
1439 g_string_append_c (define_line
, '\\');
1444 /* found object-like macro */
1445 fprintf (fmacros
, "%s\n", define_line
->str
);
1447 c
= eat_line (f
, c
);
1454 igenerator
->macro_scan
= TRUE
;
1457 g_igenerator_parse_file (igenerator
, fmacros
);
1460 igenerator
->macro_scan
= FALSE
;
1464 g_igenerator_add_module (GIGenerator
*igenerator
,
1469 for (l
= module
->entries
; l
; l
= l
->next
)
1471 GIdlNode
*node
= (GIdlNode
*)l
->data
;
1473 if (node
->type
== G_IDL_NODE_OBJECT
)
1475 GIdlNodeInterface
*object
= (GIdlNodeInterface
*)node
;
1477 if (strcmp(module
->name
, igenerator
->namespace) == 0)
1478 name
= g_strdup (node
->name
);
1480 name
= g_strdup_printf ("%s.%s", module
->name
, node
->name
);
1481 g_hash_table_insert (igenerator
->symbols
,
1482 g_strdup (object
->gtype_name
),
1489 g_igenerator_add_include_idl (GIGenerator
*igenerator
,
1490 const gchar
*filename
)
1495 GError
*error
= NULL
;
1497 modules
= g_idl_parse_file (filename
, &error
);
1500 g_printerr ("An error occured while parsing %s: %s\n",
1501 filename
, error
->message
);
1505 for (l
= modules
; l
; l
= l
->next
)
1507 GIdlModule
*module
= (GIdlModule
*)l
->data
;
1508 g_igenerator_add_module (igenerator
, module
);
1513 g_igenerator_start_preprocessor (GIGenerator
*igenerator
,
1516 int cpp_out
= -1, cpp_in
= -1;
1520 GError
*error
= NULL
;
1530 cpp_argv
= g_new0 (char *, g_list_length (cpp_options
) + 4);
1531 cpp_argv
[cpp_argc
++] = "cpp";
1532 cpp_argv
[cpp_argc
++] = "-C";
1534 /* Disable GCC extensions as we cannot parse them yet */
1535 cpp_argv
[cpp_argc
++] = "-U__GNUC__";
1537 for (l
= cpp_options
; l
; l
= l
->next
)
1538 cpp_argv
[cpp_argc
++] = (char*)l
->data
;
1540 cpp_argv
[cpp_argc
++] = NULL
;
1542 if (igenerator
->verbose
)
1544 GString
*args
= g_string_new ("");
1546 for (i
= 0; i
< cpp_argc
- 1; i
++)
1548 g_string_append (args
, cpp_argv
[i
]);
1549 if (i
< cpp_argc
- 2)
1550 g_string_append_c (args
, ' ');
1553 g_printf ("Executing '%s'\n", args
->str
);
1554 g_string_free (args
, FALSE
);
1556 g_spawn_async_with_pipes (NULL
, cpp_argv
, NULL
,
1557 G_SPAWN_SEARCH_PATH
| G_SPAWN_DO_NOT_REAP_CHILD
,
1558 NULL
, NULL
, &pid
, &cpp_in
, &cpp_out
, NULL
, &error
);
1563 g_error ("%s", error
->message
);
1567 f
= fdopen (cpp_in
, "w");
1569 for (l
= igenerator
->filenames
; l
!= NULL
; l
= l
->next
)
1571 if (igenerator
->verbose
)
1572 g_printf ("Pre-processing %s\n", (char*)l
->data
);
1574 fprintf (f
, "#include <%s>\n", (char *) l
->data
);
1581 tmp
= g_file_open_tmp (NULL
, &tmpname
, &error
);
1584 g_error (error
->message
);
1588 buffer
= g_malloc0 (4096 * sizeof (char));
1592 read_bytes
= read (cpp_out
, buffer
, 4096);
1593 if (read_bytes
== 0)
1595 write (tmp
, buffer
, read_bytes
);
1602 if (waitpid (pid
, &status
, 0) > 0)
1606 g_spawn_close_pid (pid
);
1607 kill (pid
, SIGKILL
);
1609 g_error ("cpp returned error code: %d\n", status
);
1616 f
= fdopen (tmp
, "r");
1619 g_error (strerror (errno
));
1633 g_igenerator_set_verbose (GIGenerator
*igenerator
,
1636 igenerator
->verbose
= verbose
;
1640 main (int argc
, char **argv
)
1642 GOptionContext
*ctx
;
1643 gchar
*namespace = NULL
;
1644 gchar
*shared_library
= NULL
;
1645 gchar
**include_idls
= NULL
;
1646 gchar
*output
= NULL
;
1647 gboolean verbose
= FALSE
;
1649 GIGenerator
*igenerator
;
1652 GList
*filenames
= NULL
;
1653 GError
*error
= NULL
;
1654 GList
*l
, *libraries
= NULL
;
1655 GList
*cpp_options
= NULL
;
1659 GOptionEntry entries
[] =
1661 { "verbose", 'v', 0, G_OPTION_ARG_NONE
, &verbose
,
1663 { "output", 'o', 0, G_OPTION_ARG_STRING
, &output
,
1664 "write output here instead of stdout", "FILE" },
1665 { "namespace", 'n', 0, G_OPTION_ARG_STRING
, &namespace,
1666 "Namespace of the module, like 'Gtk'", "NAMESPACE" },
1667 { "shared-library", 0, 0, G_OPTION_ARG_FILENAME
, &shared_library
,
1668 "Shared library which contains the symbols", "FILE" },
1669 { "include-idl", 0, 0, G_OPTION_ARG_STRING_ARRAY
, &include_idls
,
1670 "Other gidls to include", "IDL" },
1675 gopt_argv
= (char**)g_malloc (argc
* sizeof (char*));
1676 gopt_argv
[0] = argv
[0];
1678 for (i
= 1; i
< argc
; i
++)
1680 if (argv
[i
][0] == '-')
1687 cpp_options
= g_list_prepend (cpp_options
, g_strdup (argv
[i
]));
1691 if (0==strcmp("-pthread", argv
[i
]))
1694 gopt_argv
[gopt_argc
++] = argv
[i
];
1698 else if (g_str_has_suffix (argv
[i
], ".h"))
1702 if (!g_path_is_absolute (argv
[i
]))
1704 gchar
*dir
= g_get_current_dir ();
1705 filename
= g_strdup_printf ("%s/%s", dir
,
1710 filename
= g_strdup (argv
[i
]);
1712 filenames
= g_list_append (filenames
, g_realpath(filename
));
1715 else if (g_str_has_suffix (argv
[i
], ".la") ||
1716 g_str_has_suffix (argv
[i
], ".so") ||
1717 g_str_has_suffix (argv
[i
], ".dll"))
1719 libraries
= g_list_prepend (libraries
, g_strdup (argv
[i
]));
1723 gopt_argv
[gopt_argc
++] = argv
[i
];
1727 ctx
= g_option_context_new ("");
1728 g_option_context_add_main_entries (ctx
, entries
, NULL
);
1730 if (!g_option_context_parse (ctx
, &gopt_argc
, &gopt_argv
, &error
))
1732 g_printerr ("Parsing error: %s\n", error
->message
);
1733 g_option_context_free (ctx
);
1738 g_option_context_free (ctx
);
1742 g_printerr ("ERROR: namespace must be specified\n");
1746 igenerator
= g_igenerator_new (namespace, shared_library
);
1749 g_igenerator_set_verbose (igenerator
, TRUE
);
1753 g_printerr ("ERROR: Need at least one header file.\n");
1754 g_igenerator_free (igenerator
);
1757 igenerator
->filenames
= filenames
;
1758 cpp_options
= g_list_reverse (cpp_options
);
1759 libraries
= g_list_reverse (libraries
);
1763 /* initialize threading as this may be required by libraries that we'll use
1764 * libsoup-2.2 is an example of that.
1766 g_thread_init (NULL
);
1770 for (i
= 0; i
< g_strv_length (include_idls
); i
++)
1771 g_igenerator_add_include_idl (igenerator
, include_idls
[i
]);
1774 tmp
= g_igenerator_start_preprocessor (igenerator
, cpp_options
);
1777 g_error ("ERROR in pre-processor.\n");
1778 g_igenerator_free (igenerator
);
1782 if (!g_igenerator_parse_file (igenerator
, tmp
))
1785 g_igenerator_free (igenerator
);
1789 g_igenerator_parse_macros (igenerator
);
1791 g_igenerator_generate (igenerator
, output
, libraries
);
1794 g_igenerator_free (igenerator
);