4 # gtk-doc - GTK DocBook documentation generator.
5 # Copyright (C) 1998 Damon Chaplin
6 # 2007-2016 Stefan Sauer
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write to the Free Software
20 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 The scangobj tool gets information about object hierarchies and signals by
25 compiling and running a small C program. CFLAGS and LDFLAGS must be set
26 appropriately before running this script.
29 from __future__
import print_function
38 from . import common
, config
46 #include <glib-object.h>
49 QUERY_CHILD_PROPS_PROTOTYPE
= "extern GParamSpec** %s (gpointer class, guint *n_properties);"
51 QUERY_CHILD_PROPS_CODE
= """
53 properties = %s (class, &n_properties);
63 #ifdef GTK_IS_WIDGET_CLASS
66 static GType object_types[$ntypes];
69 get_object_types (void)
71 gpointer g_object_class;
75 object_types[i] = G_TYPE_INVALID;
77 /* reference the GObjectClass to initialize the param spec pool
78 * potentially needed by interfaces. See http://bugs.gnome.org/571820 */
79 g_object_class = g_type_class_ref (G_TYPE_OBJECT);
81 /* Need to make sure all the types are loaded in and initialize
82 * their signals and properties.
84 for (i=0; object_types[i]; i++) {
85 if (G_TYPE_IS_CLASSED (object_types[i]))
86 g_type_class_ref (object_types[i]);
87 if (G_TYPE_IS_INTERFACE (object_types[i]))
88 g_type_default_interface_ref (object_types[i]);
91 g_type_class_unref (g_object_class);
97 * This uses GObject type functions to output signal prototypes and the object
101 /* The output files */
102 const gchar *signals_filename = "$new_signals_filename";
103 const gchar *hierarchy_filename = "$new_hierarchy_filename";
104 const gchar *interfaces_filename = "$new_interfaces_filename";
105 const gchar *prerequisites_filename = "$new_prerequisites_filename";
106 const gchar *args_filename = "$new_args_filename";
108 static void output_signals (void);
109 static void output_object_signals (FILE *fp,
111 static void output_object_signal (FILE *fp,
112 const gchar *object_class_name,
114 static const gchar * get_type_name (GType type,
115 gboolean * is_pointer);
116 static void output_object_hierarchy (void);
117 static void output_hierarchy (FILE *fp,
121 static void output_object_interfaces (void);
122 static void output_interfaces (FILE *fp,
125 static void output_interface_prerequisites (void);
126 static void output_prerequisites (FILE *fp,
129 static void output_args (void);
130 static void output_object_args (FILE *fp, GType object_type);
133 main (int argc, char *argv[])
140 output_object_hierarchy ();
141 output_object_interfaces ();
142 output_interface_prerequisites ();
149 output_signals (void)
154 fp = fopen (signals_filename, "w");
156 g_warning ("Couldn't open output file: %s : %s", signals_filename, g_strerror(errno));
160 for (i = 0; object_types[i]; i++)
161 output_object_signals (fp, object_types[i]);
167 compare_signals (const void *a, const void *b)
169 const guint *signal_a = a;
170 const guint *signal_b = b;
172 return strcmp (g_signal_name (*signal_a), g_signal_name (*signal_b));
175 /* This outputs all the signals of one object. */
177 output_object_signals (FILE *fp, GType object_type)
179 const gchar *object_class_name;
180 guint *signals, n_signals;
183 if (G_TYPE_IS_INSTANTIATABLE (object_type) ||
184 G_TYPE_IS_INTERFACE (object_type)) {
186 object_class_name = g_type_name (object_type);
188 signals = g_signal_list_ids (object_type, &n_signals);
189 qsort (signals, n_signals, sizeof (guint), compare_signals);
191 for (sig = 0; sig < n_signals; sig++) {
192 output_object_signal (fp, object_class_name, signals[sig]);
198 /* This outputs one signal. */
200 output_object_signal (FILE *fp,
201 const gchar *object_name,
204 GSignalQuery query_info;
205 const gchar *type_name, *ret_type, *object_arg, *arg_name;
206 gchar *pos, *object_arg_lower;
210 gint param_num, widget_num, event_num, callback_num;
212 gchar signal_name[128];
215 /* g_print ("Object: %s Signal: %u\\n", object_name, signal_id);*/
218 widget_num = event_num = callback_num = 0;
220 g_signal_query (signal_id, &query_info);
222 /* Output the signal object type and the argument name. We assume the
223 * type is a pointer - I think that is OK. We remove "Gtk" or "Gnome" and
224 * convert to lower case for the argument name. */
226 sprintf (pos, "%s ", object_name);
229 /* Try to come up with a sensible variable name for the first arg
230 * It chops off 2 know prefixes :/ and makes the name lowercase
231 * It should replace lowercase -> uppercase with '_'
232 * GFileMonitor -> file_monitor
233 * GIOExtensionPoint -> extension_point
234 * GtkTreeView -> tree_view
235 * if 2nd char is upper case too
236 * search for first lower case and go back one char
238 * search for next upper case
240 if (!strncmp (object_name, "Gtk", 3))
241 object_arg = object_name + 3;
242 else if (!strncmp (object_name, "Gnome", 5))
243 object_arg = object_name + 5;
245 object_arg = object_name;
247 object_arg_lower = g_ascii_strdown (object_arg, -1);
248 sprintf (pos, "*%s\\n", object_arg_lower);
250 if (!strncmp (object_arg_lower, "widget", 6))
252 g_free(object_arg_lower);
254 /* Convert signal name to use underscores rather than dashes '-'. */
255 strncpy (signal_name, query_info.signal_name, 127);
256 signal_name[127] = '\\0';
257 for (i = 0; signal_name[i]; i++) {
258 if (signal_name[i] == '-')
259 signal_name[i] = '_';
262 /* Output the signal parameters. */
263 for (param = 0; param < query_info.n_params; param++) {
264 type_name = get_type_name (query_info.param_types[param] & ~G_SIGNAL_TYPE_STATIC_SCOPE, &is_pointer);
266 /* Most arguments to the callback are called "arg1", "arg2", etc.
267 GtkWidgets are called "widget", "widget2", ...
268 GtkCallbacks are called "callback", "callback2", ... */
269 if (!strcmp (type_name, "GtkWidget")) {
271 arg_num = &widget_num;
273 else if (!strcmp (type_name, "GtkCallback")
274 || !strcmp (type_name, "GtkCCallback")) {
275 arg_name = "callback";
276 arg_num = &callback_num;
280 arg_num = ¶m_num;
282 sprintf (pos, "%s ", type_name);
285 if (!arg_num || *arg_num == 0)
286 sprintf (pos, "%s%s\\n", is_pointer ? "*" : " ", arg_name);
288 sprintf (pos, "%s%s%i\\n", is_pointer ? "*" : " ", arg_name,
301 /* We use one-character flags for simplicity. */
302 if (query_info.signal_flags & G_SIGNAL_RUN_FIRST)
304 if (query_info.signal_flags & G_SIGNAL_RUN_LAST)
306 if (query_info.signal_flags & G_SIGNAL_RUN_CLEANUP)
308 if (query_info.signal_flags & G_SIGNAL_NO_RECURSE)
310 if (query_info.signal_flags & G_SIGNAL_DETAILED)
312 if (query_info.signal_flags & G_SIGNAL_ACTION)
314 if (query_info.signal_flags & G_SIGNAL_NO_HOOKS)
318 /* Output the return type and function name. */
319 ret_type = get_type_name (query_info.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE, &is_pointer);
322 "<SIGNAL>\\n<NAME>%s::%s</NAME>\\n<RETURNS>%s%s</RETURNS>\\n<FLAGS>%s</FLAGS>\\n%s</SIGNAL>\\n\\n",
323 object_name, query_info.signal_name, ret_type, is_pointer ? "*" : "", flags, buffer);
327 /* Returns the type name to use for a signal argument or return value, given
328 the GtkType from the signal info. It also sets is_pointer to TRUE if the
329 argument needs a '*' since it is a pointer. */
331 get_type_name (GType type, gboolean * is_pointer)
333 const gchar *type_name;
336 type_name = g_type_name (type);
350 /* These all have normal C type names so they are OK. */
354 /* A GtkString is really a gchar*. */
360 /* We use a gint for both of these. Hopefully a subtype with a decent
361 name will be registered and used instead, as GTK+ does itself. */
365 /* The boxed type shouldn't be used itself, only subtypes. Though we
366 return 'gpointer' just in case. */
370 /* A GParam is really a GParamSpec*. */
374 #if GLIB_CHECK_VERSION (2, 25, 9)
384 /* For all GObject subclasses we can use the class name with a "*",
385 e.g. 'GtkWidget *'. */
386 if (g_type_is_a (type, G_TYPE_OBJECT))
389 /* Also catch non GObject root types */
390 if (G_TYPE_IS_CLASSED (type))
393 /* All boxed subtypes will be pointers as well. */
394 /* Exception: GStrv */
395 if (g_type_is_a (type, G_TYPE_BOXED) &&
396 !g_type_is_a (type, G_TYPE_STRV))
399 /* All pointer subtypes will be pointers as well. */
400 if (g_type_is_a (type, G_TYPE_POINTER))
403 /* But enums are not */
404 if (g_type_is_a (type, G_TYPE_ENUM) ||
405 g_type_is_a (type, G_TYPE_FLAGS))
412 /* This outputs the hierarchy of all objects which have been initialized,
413 i.e. by calling their XXX_get_type() initialization function. */
415 output_object_hierarchy (void)
420 GType root_types[$ntypes] = { G_TYPE_INVALID, };
422 fp = fopen (hierarchy_filename, "w");
424 g_warning ("Couldn't open output file: %s : %s", hierarchy_filename, g_strerror(errno));
427 output_hierarchy (fp, G_TYPE_OBJECT, 0);
428 output_hierarchy (fp, G_TYPE_INTERFACE, 0);
430 for (i=0; object_types[i]; i++) {
431 root = object_types[i];
432 while ((type = g_type_parent (root))) {
435 if ((root != G_TYPE_OBJECT) && (root != G_TYPE_INTERFACE)) {
436 for (j=0; root_types[j]; j++) {
437 if (root == root_types[j]) {
438 root = G_TYPE_INVALID; break;
442 root_types[j] = root;
443 output_hierarchy (fp, root, 0);
451 /* This is called recursively to output the hierarchy of a object. */
453 output_hierarchy (FILE *fp,
464 for (i = 0; i < level; i++)
466 fprintf (fp, "%s\\n", g_type_name (type));
468 children = g_type_children (type, &n_children);
470 for (i=0; i < n_children; i++)
471 output_hierarchy (fp, children[i], level + 1);
476 static void output_object_interfaces (void)
481 fp = fopen (interfaces_filename, "w");
483 g_warning ("Couldn't open output file: %s : %s", interfaces_filename, g_strerror(errno));
486 output_interfaces (fp, G_TYPE_OBJECT);
488 for (i = 0; object_types[i]; i++) {
489 if (!g_type_parent (object_types[i]) &&
490 (object_types[i] != G_TYPE_OBJECT) &&
491 G_TYPE_IS_INSTANTIATABLE (object_types[i])) {
492 output_interfaces (fp, object_types[i]);
499 output_interfaces (FILE *fp,
503 GType *children, *interfaces;
504 guint n_children, n_interfaces;
509 interfaces = g_type_interfaces (type, &n_interfaces);
511 if (n_interfaces > 0) {
512 fprintf (fp, "%s", g_type_name (type));
513 for (i=0; i < n_interfaces; i++)
514 fprintf (fp, " %s", g_type_name (interfaces[i]));
519 children = g_type_children (type, &n_children);
521 for (i=0; i < n_children; i++)
522 output_interfaces (fp, children[i]);
527 static void output_interface_prerequisites (void)
531 fp = fopen (prerequisites_filename, "w");
533 g_warning ("Couldn't open output file: %s : %s", prerequisites_filename, g_strerror(errno));
536 output_prerequisites (fp, G_TYPE_INTERFACE);
541 output_prerequisites (FILE *fp,
544 #if GLIB_CHECK_VERSION(2,1,0)
546 GType *children, *prerequisites;
547 guint n_children, n_prerequisites;
552 prerequisites = g_type_interface_prerequisites (type, &n_prerequisites);
554 if (n_prerequisites > 0) {
555 fprintf (fp, "%s", g_type_name (type));
556 for (i=0; i < n_prerequisites; i++)
557 fprintf (fp, " %s", g_type_name (prerequisites[i]));
560 g_free (prerequisites);
562 children = g_type_children (type, &n_children);
564 for (i=0; i < n_children; i++)
565 output_prerequisites (fp, children[i]);
577 fp = fopen (args_filename, "w");
579 g_warning ("Couldn't open output file: %s : %s", args_filename, g_strerror(errno));
583 for (i = 0; object_types[i]; i++) {
584 output_object_args (fp, object_types[i]);
591 compare_param_specs (const void *a, const void *b)
593 GParamSpec *spec_a = *(GParamSpec **)a;
594 GParamSpec *spec_b = *(GParamSpec **)b;
596 return strcmp (g_param_spec_get_name (spec_a), g_param_spec_get_name (spec_b));
599 /* Its common to have unsigned properties restricted
600 * to the signed range. Therefore we make this look
601 * a bit nicer by spelling out the max constants.
604 /* Don't use "==" with floats, it might trigger a gcc warning. */
605 #define GTKDOC_COMPARE_FLOAT(x, y) (x <= y && x >= y)
608 describe_double_constant (gdouble value)
612 if (GTKDOC_COMPARE_FLOAT (value, G_MAXDOUBLE))
613 desc = g_strdup ("G_MAXDOUBLE");
614 else if (GTKDOC_COMPARE_FLOAT (value, G_MINDOUBLE))
615 desc = g_strdup ("G_MINDOUBLE");
616 else if (GTKDOC_COMPARE_FLOAT (value, -G_MAXDOUBLE))
617 desc = g_strdup ("-G_MAXDOUBLE");
618 else if (GTKDOC_COMPARE_FLOAT (value, G_MAXFLOAT))
619 desc = g_strdup ("G_MAXFLOAT");
620 else if (GTKDOC_COMPARE_FLOAT (value, G_MINFLOAT))
621 desc = g_strdup ("G_MINFLOAT");
622 else if (GTKDOC_COMPARE_FLOAT (value, -G_MAXFLOAT))
623 desc = g_strdup ("-G_MAXFLOAT");
625 /* make sure floats are output with a decimal dot irrespective of
626 * current locale. Use formatd since we want human-readable numbers
627 * and do not need the exact same bit representation when deserialising */
628 desc = g_malloc0 (G_ASCII_DTOSTR_BUF_SIZE);
629 g_ascii_formatd (desc, G_ASCII_DTOSTR_BUF_SIZE, "%g", value);
636 describe_signed_constant (gsize size, gint64 value)
642 if (sizeof (int) == 2) {
643 if (value == G_MAXINT)
644 desc = g_strdup ("G_MAXINT");
645 else if (value == G_MININT)
646 desc = g_strdup ("G_MININT");
650 if (sizeof (int) == 4) {
651 if (value == G_MAXINT)
652 desc = g_strdup ("G_MAXINT");
653 else if (value == G_MININT)
654 desc = g_strdup ("G_MININT");
656 if (value == G_MAXLONG)
657 desc = g_strdup ("G_MAXLONG");
658 else if (value == G_MINLONG)
659 desc = g_strdup ("G_MINLONG");
662 if (value == G_MAXINT64)
663 desc = g_strdup ("G_MAXINT64");
664 else if (value == G_MININT64)
665 desc = g_strdup ("G_MININT64");
671 desc = g_strdup_printf ("%" G_GINT64_FORMAT, value);
677 describe_unsigned_constant (gsize size, guint64 value)
683 if (sizeof (int) == 2) {
684 if (value == (guint64)G_MAXINT)
685 desc = g_strdup ("G_MAXINT");
686 else if (value == G_MAXUINT)
687 desc = g_strdup ("G_MAXUINT");
691 if (sizeof (int) == 4) {
692 if (value == (guint64)G_MAXINT)
693 desc = g_strdup ("G_MAXINT");
694 else if (value == G_MAXUINT)
695 desc = g_strdup ("G_MAXUINT");
697 if (value == (guint64)G_MAXLONG)
698 desc = g_strdup ("G_MAXLONG");
699 else if (value == G_MAXULONG)
700 desc = g_strdup ("G_MAXULONG");
703 if (value == G_MAXINT64)
704 desc = g_strdup ("G_MAXINT64");
705 else if (value == G_MAXUINT64)
706 desc = g_strdup ("G_MAXUINT64");
712 desc = g_strdup_printf ("%" G_GUINT64_FORMAT, value);
718 describe_type (GParamSpec *spec)
724 if (G_IS_PARAM_SPEC_CHAR (spec)) {
725 GParamSpecChar *pspec = G_PARAM_SPEC_CHAR (spec);
727 lower = describe_signed_constant (sizeof(gchar), pspec->minimum);
728 upper = describe_signed_constant (sizeof(gchar), pspec->maximum);
729 if (pspec->minimum == G_MININT8 && pspec->maximum == G_MAXINT8)
730 desc = g_strdup ("");
731 else if (pspec->minimum == G_MININT8)
732 desc = g_strdup_printf ("<= %s", upper);
733 else if (pspec->maximum == G_MAXINT8)
734 desc = g_strdup_printf (">= %s", lower);
736 desc = g_strdup_printf ("[%s,%s]", lower, upper);
740 else if (G_IS_PARAM_SPEC_UCHAR (spec)) {
741 GParamSpecUChar *pspec = G_PARAM_SPEC_UCHAR (spec);
743 lower = describe_unsigned_constant (sizeof(guchar), pspec->minimum);
744 upper = describe_unsigned_constant (sizeof(guchar), pspec->maximum);
745 if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT8)
746 desc = g_strdup ("");
747 else if (pspec->minimum == 0)
748 desc = g_strdup_printf ("<= %s", upper);
749 else if (pspec->maximum == G_MAXUINT8)
750 desc = g_strdup_printf (">= %s", lower);
752 desc = g_strdup_printf ("[%s,%s]", lower, upper);
756 else if (G_IS_PARAM_SPEC_INT (spec)) {
757 GParamSpecInt *pspec = G_PARAM_SPEC_INT (spec);
759 lower = describe_signed_constant (sizeof(gint), pspec->minimum);
760 upper = describe_signed_constant (sizeof(gint), pspec->maximum);
761 if (pspec->minimum == G_MININT && pspec->maximum == G_MAXINT)
762 desc = g_strdup ("");
763 else if (pspec->minimum == G_MININT)
764 desc = g_strdup_printf ("<= %s", upper);
765 else if (pspec->maximum == G_MAXINT)
766 desc = g_strdup_printf (">= %s", lower);
768 desc = g_strdup_printf ("[%s,%s]", lower, upper);
772 else if (G_IS_PARAM_SPEC_UINT (spec)) {
773 GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (spec);
775 lower = describe_unsigned_constant (sizeof(guint), pspec->minimum);
776 upper = describe_unsigned_constant (sizeof(guint), pspec->maximum);
777 if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT)
778 desc = g_strdup ("");
779 else if (pspec->minimum == 0)
780 desc = g_strdup_printf ("<= %s", upper);
781 else if (pspec->maximum == G_MAXUINT)
782 desc = g_strdup_printf (">= %s", lower);
784 desc = g_strdup_printf ("[%s,%s]", lower, upper);
788 else if (G_IS_PARAM_SPEC_LONG (spec)) {
789 GParamSpecLong *pspec = G_PARAM_SPEC_LONG (spec);
791 lower = describe_signed_constant (sizeof(glong), pspec->minimum);
792 upper = describe_signed_constant (sizeof(glong), pspec->maximum);
793 if (pspec->minimum == G_MINLONG && pspec->maximum == G_MAXLONG)
794 desc = g_strdup ("");
795 else if (pspec->minimum == G_MINLONG)
796 desc = g_strdup_printf ("<= %s", upper);
797 else if (pspec->maximum == G_MAXLONG)
798 desc = g_strdup_printf (">= %s", lower);
800 desc = g_strdup_printf ("[%s,%s]", lower, upper);
804 else if (G_IS_PARAM_SPEC_ULONG (spec)) {
805 GParamSpecULong *pspec = G_PARAM_SPEC_ULONG (spec);
807 lower = describe_unsigned_constant (sizeof(gulong), pspec->minimum);
808 upper = describe_unsigned_constant (sizeof(gulong), pspec->maximum);
809 if (pspec->minimum == 0 && pspec->maximum == G_MAXULONG)
810 desc = g_strdup ("");
811 else if (pspec->minimum == 0)
812 desc = g_strdup_printf ("<= %s", upper);
813 else if (pspec->maximum == G_MAXULONG)
814 desc = g_strdup_printf (">= %s", lower);
816 desc = g_strdup_printf ("[%s,%s]", lower, upper);
820 else if (G_IS_PARAM_SPEC_INT64 (spec)) {
821 GParamSpecInt64 *pspec = G_PARAM_SPEC_INT64 (spec);
823 lower = describe_signed_constant (sizeof(gint64), pspec->minimum);
824 upper = describe_signed_constant (sizeof(gint64), pspec->maximum);
825 if (pspec->minimum == G_MININT64 && pspec->maximum == G_MAXINT64)
826 desc = g_strdup ("");
827 else if (pspec->minimum == G_MININT64)
828 desc = g_strdup_printf ("<= %s", upper);
829 else if (pspec->maximum == G_MAXINT64)
830 desc = g_strdup_printf (">= %s", lower);
832 desc = g_strdup_printf ("[%s,%s]", lower, upper);
836 else if (G_IS_PARAM_SPEC_UINT64 (spec)) {
837 GParamSpecUInt64 *pspec = G_PARAM_SPEC_UINT64 (spec);
839 lower = describe_unsigned_constant (sizeof(guint64), pspec->minimum);
840 upper = describe_unsigned_constant (sizeof(guint64), pspec->maximum);
841 if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT64)
842 desc = g_strdup ("");
843 else if (pspec->minimum == 0)
844 desc = g_strdup_printf ("<= %s", upper);
845 else if (pspec->maximum == G_MAXUINT64)
846 desc = g_strdup_printf (">= %s", lower);
848 desc = g_strdup_printf ("[%s,%s]", lower, upper);
852 else if (G_IS_PARAM_SPEC_FLOAT (spec)) {
853 GParamSpecFloat *pspec = G_PARAM_SPEC_FLOAT (spec);
855 lower = describe_double_constant (pspec->minimum);
856 upper = describe_double_constant (pspec->maximum);
857 if (GTKDOC_COMPARE_FLOAT (pspec->minimum, -G_MAXFLOAT)) {
858 if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXFLOAT))
859 desc = g_strdup ("");
861 desc = g_strdup_printf ("<= %s", upper);
863 else if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXFLOAT))
864 desc = g_strdup_printf (">= %s", lower);
866 desc = g_strdup_printf ("[%s,%s]", lower, upper);
870 else if (G_IS_PARAM_SPEC_DOUBLE (spec)) {
871 GParamSpecDouble *pspec = G_PARAM_SPEC_DOUBLE (spec);
873 lower = describe_double_constant (pspec->minimum);
874 upper = describe_double_constant (pspec->maximum);
875 if (GTKDOC_COMPARE_FLOAT (pspec->minimum, -G_MAXDOUBLE)) {
876 if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXDOUBLE))
877 desc = g_strdup ("");
879 desc = g_strdup_printf ("<= %s", upper);
881 else if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXDOUBLE))
882 desc = g_strdup_printf (">= %s", lower);
884 desc = g_strdup_printf ("[%s,%s]", lower, upper);
888 #if GLIB_CHECK_VERSION (2, 12, 0)
889 else if (G_IS_PARAM_SPEC_GTYPE (spec)) {
890 GParamSpecGType *pspec = G_PARAM_SPEC_GTYPE (spec);
893 desc = g_strdup (get_type_name (pspec->is_a_type, &is_pointer));
896 #if GLIB_CHECK_VERSION (2, 25, 9)
897 else if (G_IS_PARAM_SPEC_VARIANT (spec)) {
898 GParamSpecVariant *pspec = G_PARAM_SPEC_VARIANT (spec);
901 variant_type = g_variant_type_dup_string (pspec->type);
902 desc = g_strdup_printf ("GVariant<%s>", variant_type);
903 g_free (variant_type);
907 desc = g_strdup ("");
914 describe_default (GParamSpec *spec)
918 if (G_IS_PARAM_SPEC_CHAR (spec)) {
919 GParamSpecChar *pspec = G_PARAM_SPEC_CHAR (spec);
921 desc = g_strdup_printf ("%d", pspec->default_value);
923 else if (G_IS_PARAM_SPEC_UCHAR (spec)) {
924 GParamSpecUChar *pspec = G_PARAM_SPEC_UCHAR (spec);
926 desc = g_strdup_printf ("%u", pspec->default_value);
928 else if (G_IS_PARAM_SPEC_BOOLEAN (spec)) {
929 GParamSpecBoolean *pspec = G_PARAM_SPEC_BOOLEAN (spec);
931 desc = g_strdup_printf ("%s", pspec->default_value ? "TRUE" : "FALSE");
933 else if (G_IS_PARAM_SPEC_INT (spec)) {
934 GParamSpecInt *pspec = G_PARAM_SPEC_INT (spec);
936 desc = g_strdup_printf ("%d", pspec->default_value);
938 else if (G_IS_PARAM_SPEC_UINT (spec)) {
939 GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (spec);
941 desc = g_strdup_printf ("%u", pspec->default_value);
943 else if (G_IS_PARAM_SPEC_LONG (spec)) {
944 GParamSpecLong *pspec = G_PARAM_SPEC_LONG (spec);
946 desc = g_strdup_printf ("%ld", pspec->default_value);
948 else if (G_IS_PARAM_SPEC_LONG (spec)) {
949 GParamSpecULong *pspec = G_PARAM_SPEC_ULONG (spec);
951 desc = g_strdup_printf ("%lu", pspec->default_value);
953 else if (G_IS_PARAM_SPEC_INT64 (spec)) {
954 GParamSpecInt64 *pspec = G_PARAM_SPEC_INT64 (spec);
956 desc = g_strdup_printf ("%" G_GINT64_FORMAT, pspec->default_value);
958 else if (G_IS_PARAM_SPEC_UINT64 (spec))
960 GParamSpecUInt64 *pspec = G_PARAM_SPEC_UINT64 (spec);
962 desc = g_strdup_printf ("%" G_GUINT64_FORMAT, pspec->default_value);
964 else if (G_IS_PARAM_SPEC_UNICHAR (spec)) {
965 GParamSpecUnichar *pspec = G_PARAM_SPEC_UNICHAR (spec);
967 if (g_unichar_isprint (pspec->default_value))
968 desc = g_strdup_printf ("'%c'", pspec->default_value);
970 desc = g_strdup_printf ("%u", pspec->default_value);
972 else if (G_IS_PARAM_SPEC_ENUM (spec)) {
973 GParamSpecEnum *pspec = G_PARAM_SPEC_ENUM (spec);
975 GEnumValue *value = g_enum_get_value (pspec->enum_class, pspec->default_value);
977 desc = g_strdup_printf ("%s", value->value_name);
979 desc = g_strdup_printf ("%d", pspec->default_value);
981 else if (G_IS_PARAM_SPEC_FLAGS (spec)) {
982 GParamSpecFlags *pspec = G_PARAM_SPEC_FLAGS (spec);
986 default_value = pspec->default_value;
987 acc = g_string_new ("");
989 while (default_value) {
990 GFlagsValue *value = g_flags_get_first_value (pspec->flags_class, default_value);
996 g_string_append (acc, " | ");
997 g_string_append (acc, value->value_name);
999 default_value &= ~value->value;
1002 if (default_value == 0)
1003 desc = g_string_free (acc, FALSE);
1005 desc = g_strdup_printf ("%d", pspec->default_value);
1006 g_string_free (acc, TRUE);
1009 else if (G_IS_PARAM_SPEC_FLOAT (spec)) {
1010 GParamSpecFloat *pspec = G_PARAM_SPEC_FLOAT (spec);
1012 /* make sure floats are output with a decimal dot irrespective of
1013 * current locale. Use formatd since we want human-readable numbers
1014 * and do not need the exact same bit representation when deserialising */
1015 desc = g_malloc0 (G_ASCII_DTOSTR_BUF_SIZE);
1016 g_ascii_formatd (desc, G_ASCII_DTOSTR_BUF_SIZE, "%g",
1017 pspec->default_value);
1019 else if (G_IS_PARAM_SPEC_DOUBLE (spec)) {
1020 GParamSpecDouble *pspec = G_PARAM_SPEC_DOUBLE (spec);
1022 /* make sure floats are output with a decimal dot irrespective of
1023 * current locale. Use formatd since we want human-readable numbers
1024 * and do not need the exact same bit representation when deserialising */
1025 desc = g_malloc0 (G_ASCII_DTOSTR_BUF_SIZE);
1026 g_ascii_formatd (desc, G_ASCII_DTOSTR_BUF_SIZE, "%g",
1027 pspec->default_value);
1029 else if (G_IS_PARAM_SPEC_STRING (spec)) {
1030 GParamSpecString *pspec = G_PARAM_SPEC_STRING (spec);
1032 if (pspec->default_value) {
1033 gchar *esc = g_strescape (pspec->default_value, NULL);
1034 desc = g_strdup_printf ("\\"%s\\"", esc);
1038 desc = g_strdup_printf ("NULL");
1040 #if GLIB_CHECK_VERSION (2, 25, 9)
1041 else if (G_IS_PARAM_SPEC_VARIANT (spec)) {
1042 GParamSpecVariant *pspec = G_PARAM_SPEC_VARIANT (spec);
1044 if (pspec->default_value)
1045 desc = g_variant_print (pspec->default_value, TRUE);
1047 desc = g_strdup ("NULL");
1051 desc = g_strdup ("");
1059 output_object_args (FILE *fp, GType object_type)
1062 const gchar *object_class_name;
1064 gchar flags[16], *pos;
1065 GParamSpec **properties;
1067 gboolean child_prop;
1068 gboolean style_prop;
1069 gboolean is_pointer;
1070 const gchar *type_name;
1072 gchar *default_value;
1074 if (G_TYPE_IS_OBJECT (object_type)) {
1075 class = g_type_class_peek (object_type);
1079 properties = g_object_class_list_properties (class, &n_properties);
1081 #if GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 3)
1082 else if (G_TYPE_IS_INTERFACE (object_type)) {
1083 class = g_type_default_interface_ref (object_type);
1088 properties = g_object_interface_list_properties (class, &n_properties);
1094 object_class_name = g_type_name (object_type);
1100 qsort (properties, n_properties, sizeof (GParamSpec *), compare_param_specs);
1101 for (arg = 0; arg < n_properties; arg++) {
1102 GParamSpec *spec = properties[arg];
1103 const gchar *nick, *blurb, *dot;
1105 if (spec->owner_type != object_type)
1109 /* We use one-character flags for simplicity. */
1110 if (child_prop && !style_prop)
1114 if (spec->flags & G_PARAM_READABLE)
1116 if (spec->flags & G_PARAM_WRITABLE)
1118 if (spec->flags & G_PARAM_CONSTRUCT)
1120 if (spec->flags & G_PARAM_CONSTRUCT_ONLY)
1124 nick = g_param_spec_get_nick (spec);
1125 blurb = g_param_spec_get_blurb (spec);
1129 int str_len = strlen (blurb);
1130 if (str_len > 0 && blurb[str_len - 1] != '.')
1134 type_desc = describe_type (spec);
1135 default_value = describe_default (spec);
1136 type_name = get_type_name (spec->value_type, &is_pointer);
1137 fprintf (fp, "<ARG>\\n"
1138 "<NAME>%s::%s</NAME>\\n"
1139 "<TYPE>%s%s</TYPE>\\n"
1140 "<RANGE>%s</RANGE>\\n"
1141 "<FLAGS>%s</FLAGS>\\n"
1142 "<NICK>%s</NICK>\\n"
1143 "<BLURB>%s%s</BLURB>\\n"
1144 "<DEFAULT>%s</DEFAULT>\\n"
1146 object_class_name, g_param_spec_get_name (spec), type_name,
1147 is_pointer ? "*" : "", type_desc, flags, nick ? nick : "(null)",
1148 blurb ? blurb : "(null)", dot, default_value);
1150 g_free (default_value);
1153 g_free (properties);
1155 #ifdef GTK_IS_CONTAINER_CLASS
1156 if (!child_prop && GTK_IS_CONTAINER_CLASS (class)) {
1157 properties = gtk_container_class_list_child_properties (class, &n_properties);
1163 #ifdef GTK_IS_CELL_AREA_CLASS
1164 if (!child_prop && GTK_IS_CELL_AREA_CLASS (class)) {
1165 properties = gtk_cell_area_class_list_cell_properties (class, &n_properties);
1171 #ifdef GTK_IS_WIDGET_CLASS
1172 #if GTK_CHECK_VERSION(2,1,0) && !GTK_CHECK_VERSION(3,89,2)
1173 if (!style_prop && GTK_IS_WIDGET_CLASS (class)) {
1174 properties = gtk_widget_class_list_style_properties (GTK_WIDGET_CLASS (class), &n_properties);
1192 c_file
= options
.module
+ '-scan.c'
1193 output
= open(c_file
, 'w')
1195 base_filename
= os
.path
.join(options
.output_dir
, options
.module
)
1196 old_signals_filename
= base_filename
+ '.signals'
1197 new_signals_filename
= base_filename
+ '.signals.new'
1198 old_hierarchy_filename
= base_filename
+ '.hierarchy'
1199 new_hierarchy_filename
= base_filename
+ '.hierarchy.new'
1200 old_interfaces_filename
= base_filename
+ '.interfaces'
1201 new_interfaces_filename
= base_filename
+ '.interfaces.new'
1202 old_prerequisites_filename
= base_filename
+ '.prerequisites'
1203 new_prerequisites_filename
= base_filename
+ '.prerequisites.new'
1204 old_args_filename
= base_filename
+ '.args'
1205 new_args_filename
= base_filename
+ '.args.new'
1207 # generate a C program to scan the types
1214 for line
in open(options
.types
):
1215 if line
.startswith('#include'):
1217 elif line
.startswith('%') or line
.strip() == '':
1221 get_types
+= ' object_types[i++] = ' + line
+ ' ();\n'
1222 forward_decls
+= 'extern GType ' + line
+ ' (void);\n'
1225 output
.write(COMMON_INCLUDES
)
1228 output
.write(includes
)
1230 output
.write(forward_decls
)
1232 if options
.query_child_properties
:
1233 output
.write(QUERY_CHILD_PROPS_PROTOTYPE
% options
.query_child_properties
)
1235 # substitute local vars in the template
1236 type_init_func
= options
.type_init_func
1237 output
.write(string
.Template(MAIN_CODE
).substitute(locals()))
1239 if options
.query_child_properties
:
1240 output
.write(QUERY_CHILD_PROPS_CODE
% options
.query_child_properties
)
1242 output
.write(MAIN_CODE_END
)
1246 # Compile and run our file
1247 if 'libtool' in options
.cc
:
1248 o_file
= options
.module
+ '-scan.lo'
1250 o_file
= options
.module
+ '-scan.o'
1252 x_file
= options
.module
+ '-scan' + config
.exeext
1255 if not options
.verbose
:
1256 stdout
= ">/dev/null"
1259 command
= '%s %s %s -c -o %s %s' % (options
.cc
, stdout
, options
.cflags
, o_file
, c_file
)
1260 res
= subprocess
.check_call(command
, shell
=True)
1262 logging
.warning('Compilation of scanner failed: %d', res
)
1266 command
= '%s %s %s %s -o %s' % (options
.ld
, stdout
, o_file
, options
.ldflags
, x_file
)
1267 res
= subprocess
.check_call(command
, shell
=True)
1269 logging
.warning('Linking of scanner failed: %d', res
)
1273 command
= '%s ./%s' % (options
.run
, x_file
)
1274 res
= subprocess
.check_call(command
, shell
=True)
1276 logging
.warning('Running scanner failed: %d', res
)
1279 if 'GTK_DOC_KEEP_INTERMEDIATE' not in os
.environ
:
1284 common
.UpdateFileIfChanged(old_signals_filename
, new_signals_filename
, False)
1285 common
.UpdateFileIfChanged(old_hierarchy_filename
, new_hierarchy_filename
, False)
1286 common
.UpdateFileIfChanged(old_interfaces_filename
, new_interfaces_filename
, False)
1287 common
.UpdateFileIfChanged(old_prerequisites_filename
, new_prerequisites_filename
, False)
1288 common
.UpdateFileIfChanged(old_args_filename
, new_args_filename
, False)