4 # gtk-doc - GTK DocBook documentation generator.
5 # Copyright (C) 1998 Damon Chaplin
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 # This gets information about object heirarchies and signals
24 # by compiling a small C program. CFLAGS and LDFLAGS must be
25 # set appropriately before running this script.
27 # NOTE: the lookup_signal_arg_names() function contains the argument names of
28 # standard GTK signal handlers. This may need to be updated for new
29 # GTK signals or Gnome widget signals.
30 # FIXME: this is only needed for undocumented signals, we should remove
31 # the list as its totally undermaintained anyway
35 push @INC, '@PACKAGE_DATA_DIR@';
36 require "gtkdoc-common.pl";
40 # name of documentation module
45 my $TYPE_INIT_FUNC="g_type_init(); g_type_class_ref(G_TYPE_OBJECT)";
46 my $QUERY_CHILD_PROPERTIES;
48 # --nogtkinit is deprecated, as it is the default now anyway.
49 %optctl = (module => \$MODULE,
50 types => \$TYPES_FILE,
51 nogtkinit => \$NO_GTK_INIT,
52 'type-init-func' => \$TYPE_INIT_FUNC,
53 'query-child-properties' => \$QUERY_CHILD_PROPERTIES,
54 'output-dir' => \$OUTPUT_DIR,
55 'version' => \$PRINT_VERSION,
56 'help' => \$PRINT_HELP);
58 GetOptions(\%optctl, "module=s", "types:s", "output-dir:s", "nogtkinit", "type-init-func:s", "query-child-properties:s", "version", "help");
61 # Do nothing. This just avoids a warning.
62 # the option is not used anymore
76 gtkdoc-scangobj version @VERSION@ - introspect g-objects
78 --module=MODULE_NAME Name of the doc module being parsed
79 --types=FILE The name of the file to store the types in
80 --type-init-func=FUNC The init function to call instead of g_type_init()
81 --query-child-properties=FUNC A function that returns a list of child
82 properties for a class
83 --output-dir=DIRNAME The directory where the results are stored
84 --version Print the version of this program
85 --help Print this help
90 $OUTPUT_DIR = $OUTPUT_DIR ? $OUTPUT_DIR : ".";
92 $TYPES_FILE = $TYPES_FILE ? $TYPES_FILE : "$OUTPUT_DIR/$MODULE.types";
94 open (TYPES, $TYPES_FILE) || die "Cannot open $TYPES_FILE: $!\n";
95 open (OUTPUT, ">$MODULE-scan.c") || die "Cannot open $MODULE-scan.c: $!\n";
97 my $old_signals_filename = "$OUTPUT_DIR/$MODULE.signals";
98 my $new_signals_filename = "$OUTPUT_DIR/$MODULE.signals.new";
99 my $old_hierarchy_filename = "$OUTPUT_DIR/$MODULE.hierarchy";
100 my $new_hierarchy_filename = "$OUTPUT_DIR/$MODULE.hierarchy.new";
101 my $old_interfaces_filename = "$OUTPUT_DIR/$MODULE.interfaces";
102 my $new_interfaces_filename = "$OUTPUT_DIR/$MODULE.interfaces.new";
103 my $old_prerequisites_filename = "$OUTPUT_DIR/$MODULE.prerequisites";
104 my $new_prerequisites_filename = "$OUTPUT_DIR/$MODULE.prerequisites.new";
105 my $old_args_filename = "$OUTPUT_DIR/$MODULE.args";
106 my $new_args_filename = "$OUTPUT_DIR/$MODULE.args.new";
108 # write a C program to scan the types
116 } elsif (/^gnome_keyring_item_info_get_type$/) {
117 # HACK: This isn't really a GObject type so skip it.
129 $ntypes = @types + 1;
136 #include <glib-object.h>
141 print OUTPUT $includes;
144 print OUTPUT "extern GType $_ (void);\n";
148 if ($QUERY_CHILD_PROPERTIES) {
150 extern GParamSpec** $QUERY_CHILD_PROPERTIES (gpointer class, guint *n_properties);
156 #ifdef GTK_IS_WIDGET_CLASS
159 GType object_types[$ntypes];
162 get_object_types (void)
164 gpointer g_object_class;
169 print OUTPUT " object_types[i++] = $_ ();\n";
175 /* reference the GObjectClass to initialize the param spec pool
176 * potentially needed by interfaces. See http://bugs.gnome.org/571820 */
177 g_object_class = g_type_class_ref (G_TYPE_OBJECT);
179 /* Need to make sure all the types are loaded in and initialize
180 * their signals and properties.
182 for (i=0; object_types[i]; i++)
184 if (G_TYPE_IS_CLASSED (object_types[i]))
185 g_type_class_ref (object_types[i]);
186 if (G_TYPE_IS_INTERFACE (object_types[i]))
187 g_type_default_interface_ref (object_types[i]);
190 g_type_class_unref (g_object_class);
196 * This uses GObject type functions to output signal prototypes and the object
200 /* The output files */
201 const gchar *signals_filename = "$new_signals_filename";
202 const gchar *hierarchy_filename = "$new_hierarchy_filename";
203 const gchar *interfaces_filename = "$new_interfaces_filename";
204 const gchar *prerequisites_filename = "$new_prerequisites_filename";
205 const gchar *args_filename = "$new_args_filename";
208 static void output_signals (void);
209 static void output_object_signals (FILE *fp,
211 static void output_object_signal (FILE *fp,
212 const gchar *object_class_name,
214 static const gchar * get_type_name (GType type,
215 gboolean * is_pointer);
216 static const gchar * get_gdk_event (const gchar * signal_name);
217 static const gchar ** lookup_signal_arg_names (const gchar * type,
218 const gchar * signal_name);
220 static void output_object_hierarchy (void);
221 static void output_hierarchy (FILE *fp,
225 static void output_object_interfaces (void);
226 static void output_interfaces (FILE *fp,
229 static void output_interface_prerequisites (void);
230 static void output_prerequisites (FILE *fp,
233 static void output_args (void);
234 static void output_object_args (FILE *fp, GType object_type);
237 main (int argc, char *argv[])
244 output_object_hierarchy ();
245 output_object_interfaces ();
246 output_interface_prerequisites ();
254 output_signals (void)
259 fp = fopen (signals_filename, "w");
262 g_warning ("Couldn't open output file: %s : %s", signals_filename, g_strerror(errno));
266 for (i = 0; object_types[i]; i++)
267 output_object_signals (fp, object_types[i]);
273 compare_signals (const void *a, const void *b)
275 const guint *signal_a = a;
276 const guint *signal_b = b;
278 return strcmp (g_signal_name (*signal_a), g_signal_name (*signal_b));
281 /* This outputs all the signals of one object. */
283 output_object_signals (FILE *fp, GType object_type)
285 const gchar *object_class_name;
286 guint *signals, n_signals;
289 if (G_TYPE_IS_INSTANTIATABLE (object_type) ||
290 G_TYPE_IS_INTERFACE (object_type))
293 object_class_name = g_type_name (object_type);
295 signals = g_signal_list_ids (object_type, &n_signals);
296 qsort (signals, n_signals, sizeof (guint), compare_signals);
298 for (sig = 0; sig < n_signals; sig++)
300 output_object_signal (fp, object_class_name, signals[sig]);
307 /* This outputs one signal. */
309 output_object_signal (FILE *fp,
310 const gchar *object_name,
313 GSignalQuery query_info;
314 const gchar *type_name, *ret_type, *object_arg, *arg_name;
315 gchar *pos, *object_arg_lower;
319 const gchar **arg_names;
320 gint param_num, widget_num, event_num, callback_num;
322 gchar signal_name[128];
325 /* g_print ("Object: %s Signal: %u\\n", object_name, signal_id);*/
328 widget_num = event_num = callback_num = 0;
330 g_signal_query (signal_id, &query_info);
332 /* Output the signal object type and the argument name. We assume the
333 type is a pointer - I think that is OK. We remove "Gtk" or "Gnome" and
334 convert to lower case for the argument name. */
336 sprintf (pos, "%s ", object_name);
339 /* Try to come up with a sensible variable name for the first arg
340 * I chops off 2 know prefixes :/ and makes the name lowercase
341 * It should replace lowercase -> uppercase with '_'
342 * GFileMonitor -> file_monitor
343 * GIOExtensionPoint -> extension_point
344 * GtkTreeView -> tree_view
345 * if 2nd char is upper case too
346 * search for first lower case and go back one char
348 * search for next upper case
350 if (!strncmp (object_name, "Gtk", 3))
351 object_arg = object_name + 3;
352 else if (!strncmp (object_name, "Gnome", 5))
353 object_arg = object_name + 5;
355 object_arg = object_name;
357 object_arg_lower = g_ascii_strdown (object_arg, -1);
358 sprintf (pos, "*%s\\n", object_arg_lower);
360 if (!strncmp (object_arg_lower, "widget", 6))
362 g_free(object_arg_lower);
364 /* Convert signal name to use underscores rather than dashes '-'. */
365 strncpy (signal_name, query_info.signal_name, 127);
366 signal_name[127] = '\\0';
367 for (i = 0; signal_name[i]; i++)
369 if (signal_name[i] == '-')
370 signal_name[i] = '_';
373 /* Output the signal parameters. */
374 arg_names = lookup_signal_arg_names (object_name, signal_name);
376 for (param = 0; param < query_info.n_params; param++)
380 sprintf (pos, "%s\\n", arg_names[param]);
385 type_name = get_type_name (query_info.param_types[param] & ~G_SIGNAL_TYPE_STATIC_SCOPE, &is_pointer);
387 /* Most arguments to the callback are called "arg1", "arg2", etc.
388 GdkWidgets are called "widget", "widget2", ...
389 GdkEvents are called "event", "event2", ...
390 GtkCallbacks are called "callback", "callback2", ... */
391 if (!strcmp (type_name, "GtkWidget"))
394 arg_num = &widget_num;
396 else if (!strcmp (type_name, "GdkEvent"))
398 type_name = get_gdk_event (signal_name);
400 arg_num = &event_num;
403 else if (!strcmp (type_name, "GtkCallback")
404 || !strcmp (type_name, "GtkCCallback"))
406 arg_name = "callback";
407 arg_num = &callback_num;
412 arg_num = ¶m_num;
414 sprintf (pos, "%s ", type_name);
417 if (!arg_num || *arg_num == 0)
418 sprintf (pos, "%s%s\\n", is_pointer ? "*" : " ", arg_name);
420 sprintf (pos, "%s%s%i\\n", is_pointer ? "*" : " ", arg_name,
435 /* We use one-character flags for simplicity. */
436 if (query_info.signal_flags & G_SIGNAL_RUN_FIRST)
438 if (query_info.signal_flags & G_SIGNAL_RUN_LAST)
440 if (query_info.signal_flags & G_SIGNAL_RUN_CLEANUP)
442 if (query_info.signal_flags & G_SIGNAL_NO_RECURSE)
444 if (query_info.signal_flags & G_SIGNAL_DETAILED)
446 if (query_info.signal_flags & G_SIGNAL_ACTION)
448 if (query_info.signal_flags & G_SIGNAL_NO_HOOKS)
452 /* Output the return type and function name. */
453 ret_type = get_type_name (query_info.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE, &is_pointer);
456 "<SIGNAL>\\n<NAME>%s::%s</NAME>\\n<RETURNS>%s%s</RETURNS>\\n<FLAGS>%s</FLAGS>\\n%s</SIGNAL>\\n\\n",
457 object_name, query_info.signal_name, ret_type, is_pointer ? "*" : "", flags, buffer);
461 /* Returns the type name to use for a signal argument or return value, given
462 the GtkType from the signal info. It also sets is_pointer to TRUE if the
463 argument needs a '*' since it is a pointer. */
465 get_type_name (GType type, gboolean * is_pointer)
467 const gchar *type_name;
470 type_name = g_type_name (type);
484 /* These all have normal C type names so they are OK. */
488 /* A GtkString is really a gchar*. */
494 /* We use a gint for both of these. Hopefully a subtype with a decent
495 name will be registered and used instead, as GTK+ does itself. */
499 /* The boxed type shouldn't be used itself, only subtypes. Though we
500 return 'gpointer' just in case. */
504 /* A GParam is really a GParamSpec*. */
508 #if GLIB_CHECK_VERSION (2, 25, 9)
518 /* For all GObject subclasses we can use the class name with a "*",
519 e.g. 'GtkWidget *'. */
520 if (g_type_is_a (type, G_TYPE_OBJECT))
523 /* Also catch non GObject root types */
524 if (G_TYPE_IS_CLASSED (type))
527 /* All boxed subtypes will be pointers as well. */
528 if (g_type_is_a (type, G_TYPE_BOXED))
531 /* All pointer subtypes will be pointers as well. */
532 if (g_type_is_a (type, G_TYPE_POINTER))
535 /* But enums are not */
536 if (g_type_is_a (type, G_TYPE_ENUM) ||
537 g_type_is_a (type, G_TYPE_FLAGS))
545 get_gdk_event (const gchar * signal_name)
547 static const gchar *GbGDKEvents[] =
549 "button_press_event", "GdkEventButton",
550 "button_release_event", "GdkEventButton",
551 "motion_notify_event", "GdkEventMotion",
552 "delete_event", "GdkEvent",
553 "destroy_event", "GdkEvent",
554 "expose_event", "GdkEventExpose",
555 "key_press_event", "GdkEventKey",
556 "key_release_event", "GdkEventKey",
557 "enter_notify_event", "GdkEventCrossing",
558 "leave_notify_event", "GdkEventCrossing",
559 "configure_event", "GdkEventConfigure",
560 "focus_in_event", "GdkEventFocus",
561 "focus_out_event", "GdkEventFocus",
562 "map_event", "GdkEvent",
563 "unmap_event", "GdkEvent",
564 "property_notify_event", "GdkEventProperty",
565 "selection_clear_event", "GdkEventSelection",
566 "selection_request_event", "GdkEventSelection",
567 "selection_notify_event", "GdkEventSelection",
568 "proximity_in_event", "GdkEventProximity",
569 "proximity_out_event", "GdkEventProximity",
570 "drag_begin_event", "GdkEventDragBegin",
571 "drag_request_event", "GdkEventDragRequest",
572 "drag_end_event", "GdkEventDragRequest",
573 "drop_enter_event", "GdkEventDropEnter",
574 "drop_leave_event", "GdkEventDropLeave",
575 "drop_data_available_event", "GdkEventDropDataAvailable",
576 "other_event", "GdkEventOther",
577 "client_event", "GdkEventClient",
578 "no_expose_event", "GdkEventNoExpose",
579 "visibility_notify_event", "GdkEventVisibility",
580 "window_state_event", "GdkEventWindowState",
581 "scroll_event", "GdkEventScroll",
587 for (i = 0; GbGDKEvents[i]; i += 2)
589 if (!strcmp (signal_name, GbGDKEvents[i]))
590 return GbGDKEvents[i + 1];
596 /* This returns argument names to use for some known GTK signals.
597 It is passed a widget name, e.g. 'GtkCList' and a signal name, e.g.
598 'select_row' and it returns a pointer to an array of argument types and
600 static const gchar **
601 lookup_signal_arg_names (const gchar * type, const gchar * signal_name)
603 /* Each arg array starts with the object type name and the signal name,
604 and then signal arguments follow. */
605 static const gchar *GbArgTable[][16] =
607 {"GtkCList", "select_row",
610 "GdkEventButton *event"},
611 {"GtkCList", "unselect_row",
614 "GdkEventButton *event"},
615 {"GtkCList", "click_column",
618 {"GtkCList", "resize_column",
622 {"GtkCList", "extend_selection",
623 "GtkScrollType scroll_type",
625 "gboolean auto_start_selection"},
626 {"GtkCList", "scroll_vertical",
627 "GtkScrollType scroll_type",
629 {"GtkCList", "scroll_horizontal",
630 "GtkScrollType scroll_type",
633 {"GtkCTree", "tree_select_row",
634 "GtkCTreeNode *node",
636 {"GtkCTree", "tree_unselect_row",
637 "GtkCTreeNode *node",
639 {"GtkCTree", "tree_expand",
640 "GtkCTreeNode *node"},
641 {"GtkCTree", "tree_collapse",
642 "GtkCTreeNode *node"},
643 {"GtkCTree", "tree_move",
644 "GtkCTreeNode *node",
645 "GtkCTreeNode *new_parent",
646 "GtkCTreeNode *new_sibling"},
647 {"GtkCTree", "change_focus_row_expansion",
648 "GtkCTreeExpansionType expansion"},
650 {"GtkEditable", "insert_text",
652 "gint new_text_length",
654 {"GtkEditable", "delete_text",
657 {"GtkEditable", "set_editable",
658 "gboolean is_editable"},
659 {"GtkEditable", "move_cursor",
662 {"GtkEditable", "move_word",
664 {"GtkEditable", "move_page",
667 {"GtkEditable", "move_to_row",
669 {"GtkEditable", "move_to_column",
672 {"GtkEditable", "kill_char",
674 {"GtkEditable", "kill_word",
676 {"GtkEditable", "kill_line",
680 {"GtkInputDialog", "enable_device",
681 "GdkDevice *deviceid"},
682 {"GtkInputDialog", "disable_device",
683 "GdkDevice *deviceid"},
685 {"GtkListItem", "extend_selection",
686 "GtkScrollType scroll_type",
688 "gboolean auto_start_selection"},
689 {"GtkListItem", "scroll_vertical",
690 "GtkScrollType scroll_type",
692 {"GtkListItem", "scroll_horizontal",
693 "GtkScrollType scroll_type",
696 {"GtkMenuShell", "move_current",
697 "GtkMenuDirectionType direction"},
698 {"GtkMenuShell", "activate_current",
699 "gboolean force_hide"},
702 {"GtkNotebook", "switch_page",
703 "GtkNotebookPage *page",
705 {"GtkStatusbar", "text_pushed",
708 {"GtkStatusbar", "text_popped",
711 {"GtkTipsQuery", "widget_entered",
714 "gchar *tip_private"},
715 {"GtkTipsQuery", "widget_selected",
718 "gchar *tip_private",
719 "GdkEventButton *event"},
720 {"GtkToolbar", "orientation_changed",
721 "GtkOrientation orientation"},
722 {"GtkToolbar", "style_changed",
723 "GtkToolbarStyle style"},
724 {"GtkWidget", "draw",
725 "GdkRectangle *area"},
726 {"GtkWidget", "size_request",
727 "GtkRequisition *requisition"},
728 {"GtkWidget", "size_allocate",
729 "GtkAllocation *allocation"},
730 {"GtkWidget", "state_changed",
731 "GtkStateType state"},
732 {"GtkWidget", "style_set",
733 "GtkStyle *previous_style"},
735 {"GtkWidget", "install_accelerator",
736 "gchar *signal_name",
740 {"GtkWidget", "add_accelerator",
741 "guint accel_signal_id",
742 "GtkAccelGroup *accel_group",
744 "GdkModifierType accel_mods",
745 "GtkAccelFlags accel_flags"},
747 {"GtkWidget", "parent_set",
748 "GtkObject *old_parent"},
750 {"GtkWidget", "remove_accelerator",
751 "GtkAccelGroup *accel_group",
753 "GdkModifierType accel_mods"},
754 {"GtkWidget", "debug_msg",
756 {"GtkWindow", "move_resize",
761 {"GtkWindow", "set_focus",
762 "GtkWidget *widget"},
764 {"GtkWidget", "selection_get",
765 "GtkSelectionData *data",
768 {"GtkWidget", "selection_received",
769 "GtkSelectionData *data",
772 {"GtkWidget", "drag_begin",
773 "GdkDragContext *drag_context"},
774 {"GtkWidget", "drag_end",
775 "GdkDragContext *drag_context"},
776 {"GtkWidget", "drag_data_delete",
777 "GdkDragContext *drag_context"},
778 {"GtkWidget", "drag_leave",
779 "GdkDragContext *drag_context",
781 {"GtkWidget", "drag_motion",
782 "GdkDragContext *drag_context",
786 {"GtkWidget", "drag_drop",
787 "GdkDragContext *drag_context",
791 {"GtkWidget", "drag_data_get",
792 "GdkDragContext *drag_context",
793 "GtkSelectionData *data",
796 {"GtkWidget", "drag_data_received",
797 "GdkDragContext *drag_context",
800 "GtkSelectionData *data",
809 for (i = 0; GbArgTable[i][0]; i++)
812 if (!strcmp (type, GbArgTable[i][0])
813 && !strcmp (signal_name, GbArgTable[i][1]))
814 return &GbArgTable[i][2];
820 /* This outputs the hierarchy of all objects which have been initialized,
821 i.e. by calling their XXX_get_type() initialization function. */
823 output_object_hierarchy (void)
828 fp = fopen (hierarchy_filename, "w");
831 g_warning ("Couldn't open output file: %s : %s", hierarchy_filename, g_strerror(errno));
834 output_hierarchy (fp, G_TYPE_OBJECT, 0);
835 output_hierarchy (fp, G_TYPE_INTERFACE, 0);
837 for (i=0; object_types[i]; i++) {
838 if (!g_type_parent (object_types[i]) &&
839 (object_types[i] != G_TYPE_OBJECT) &&
840 (object_types[i] != G_TYPE_INTERFACE)
842 output_hierarchy (fp, object_types[i], 0);
849 /* This is called recursively to output the hierarchy of a widget. */
851 output_hierarchy (FILE *fp,
862 for (i = 0; i < level; i++)
864 fprintf (fp, "%s\\n", g_type_name (type));
866 children = g_type_children (type, &n_children);
868 for (i=0; i < n_children; i++)
869 output_hierarchy (fp, children[i], level + 1);
874 static void output_object_interfaces (void)
879 fp = fopen (interfaces_filename, "w");
882 g_warning ("Couldn't open output file: %s : %s", interfaces_filename, g_strerror(errno));
885 output_interfaces (fp, G_TYPE_OBJECT);
887 for (i = 0; object_types[i]; i++)
889 if (!g_type_parent (object_types[i]) &&
890 (object_types[i] != G_TYPE_OBJECT) &&
891 G_TYPE_IS_INSTANTIATABLE (object_types[i]))
893 output_interfaces (fp, object_types[i]);
900 output_interfaces (FILE *fp,
904 GType *children, *interfaces;
905 guint n_children, n_interfaces;
910 interfaces = g_type_interfaces (type, &n_interfaces);
912 if (n_interfaces > 0)
914 fprintf (fp, "%s", g_type_name (type));
915 for (i=0; i < n_interfaces; i++)
916 fprintf (fp, " %s", g_type_name (interfaces[i]));
921 children = g_type_children (type, &n_children);
923 for (i=0; i < n_children; i++)
924 output_interfaces (fp, children[i]);
929 static void output_interface_prerequisites (void)
933 fp = fopen (prerequisites_filename, "w");
936 g_warning ("Couldn't open output file: %s : %s", prerequisites_filename, g_strerror(errno));
939 output_prerequisites (fp, G_TYPE_INTERFACE);
944 output_prerequisites (FILE *fp,
947 #if GLIB_CHECK_VERSION(2,1,0)
949 GType *children, *prerequisites;
950 guint n_children, n_prerequisites;
955 prerequisites = g_type_interface_prerequisites (type, &n_prerequisites);
957 if (n_prerequisites > 0)
959 fprintf (fp, "%s", g_type_name (type));
960 for (i=0; i < n_prerequisites; i++)
961 fprintf (fp, " %s", g_type_name (prerequisites[i]));
964 g_free (prerequisites);
966 children = g_type_children (type, &n_children);
968 for (i=0; i < n_children; i++)
969 output_prerequisites (fp, children[i]);
981 fp = fopen (args_filename, "w");
984 g_warning ("Couldn't open output file: %s : %s", args_filename, g_strerror(errno));
988 for (i = 0; object_types[i]; i++) {
989 output_object_args (fp, object_types[i]);
996 compare_param_specs (const void *a, const void *b)
998 GParamSpec *spec_a = *(GParamSpec **)a;
999 GParamSpec *spec_b = *(GParamSpec **)b;
1001 return strcmp (g_param_spec_get_name (spec_a), g_param_spec_get_name (spec_b));
1004 /* Its common to have unsigned properties restricted
1005 * to the signed range. Therefore we make this look
1006 * a bit nicer by spelling out the max constants.
1009 /* Don't use "==" with floats, it might trigger a gcc warning. */
1010 #define GTKDOC_COMPARE_FLOAT(x, y) (x <= y && x >= y)
1013 describe_double_constant (gdouble value)
1017 if (GTKDOC_COMPARE_FLOAT (value, G_MAXDOUBLE))
1018 desc = g_strdup ("G_MAXDOUBLE");
1019 else if (GTKDOC_COMPARE_FLOAT (value, G_MINDOUBLE))
1020 desc = g_strdup ("G_MINDOUBLE");
1021 else if (GTKDOC_COMPARE_FLOAT (value, -G_MAXDOUBLE))
1022 desc = g_strdup ("-G_MAXDOUBLE");
1023 else if (GTKDOC_COMPARE_FLOAT (value, G_MAXFLOAT))
1024 desc = g_strdup ("G_MAXFLOAT");
1025 else if (GTKDOC_COMPARE_FLOAT (value, G_MINFLOAT))
1026 desc = g_strdup ("G_MINFLOAT");
1027 else if (GTKDOC_COMPARE_FLOAT (value, -G_MAXFLOAT))
1028 desc = g_strdup ("-G_MAXFLOAT");
1030 desc = g_strdup_printf ("%lg", value);
1036 describe_signed_constant (gsize size, gint64 value)
1042 if (sizeof (int) == 2) {
1043 if (value == G_MAXINT)
1044 desc = g_strdup ("G_MAXINT");
1045 else if (value == G_MININT)
1046 desc = g_strdup ("G_MININT");
1047 else if (value == (gint64)G_MAXUINT)
1048 desc = g_strdup ("G_MAXUINT");
1052 if (sizeof (int) == 4) {
1053 if (value == G_MAXINT)
1054 desc = g_strdup ("G_MAXINT");
1055 else if (value == G_MININT)
1056 desc = g_strdup ("G_MININT");
1057 else if (value == (gint64)G_MAXUINT)
1058 desc = g_strdup ("G_MAXUINT");
1060 if (value == G_MAXLONG)
1061 desc = g_strdup ("G_MAXLONG");
1062 else if (value == G_MINLONG)
1063 desc = g_strdup ("G_MINLONG");
1064 else if (value == (gint64)G_MAXULONG)
1065 desc = g_strdup ("G_MAXULONG");
1068 if (value == G_MAXINT64)
1069 desc = g_strdup ("G_MAXINT64");
1070 else if (value == G_MININT64)
1071 desc = g_strdup ("G_MININT64");
1077 desc = g_strdup_printf ("%" G_GINT64_FORMAT, value);
1083 describe_unsigned_constant (gsize size, guint64 value)
1089 if (sizeof (int) == 2) {
1090 if (value == (guint64)G_MAXINT)
1091 desc = g_strdup ("G_MAXINT");
1092 else if (value == G_MAXUINT)
1093 desc = g_strdup ("G_MAXUINT");
1097 if (sizeof (int) == 4) {
1098 if (value == (guint64)G_MAXINT)
1099 desc = g_strdup ("G_MAXINT");
1100 else if (value == G_MAXUINT)
1101 desc = g_strdup ("G_MAXUINT");
1103 if (value == (guint64)G_MAXLONG)
1104 desc = g_strdup ("G_MAXLONG");
1105 else if (value == G_MAXULONG)
1106 desc = g_strdup ("G_MAXULONG");
1109 if (value == G_MAXINT64)
1110 desc = g_strdup ("G_MAXINT64");
1111 else if (value == G_MAXUINT64)
1112 desc = g_strdup ("G_MAXUINT64");
1118 desc = g_strdup_printf ("%" G_GUINT64_FORMAT, value);
1124 describe_type (GParamSpec *spec)
1130 if (G_IS_PARAM_SPEC_CHAR (spec))
1132 GParamSpecChar *pspec = G_PARAM_SPEC_CHAR (spec);
1134 lower = describe_signed_constant (sizeof(gchar), pspec->minimum);
1135 upper = describe_signed_constant (sizeof(gchar), pspec->maximum);
1136 if (pspec->minimum == G_MININT8 && pspec->maximum == G_MAXINT8)
1137 desc = g_strdup ("");
1138 else if (pspec->minimum == G_MININT8)
1139 desc = g_strdup_printf ("<= %s", upper);
1140 else if (pspec->maximum == G_MAXINT8)
1141 desc = g_strdup_printf (">= %s", lower);
1143 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1147 else if (G_IS_PARAM_SPEC_UCHAR (spec))
1149 GParamSpecUChar *pspec = G_PARAM_SPEC_UCHAR (spec);
1151 lower = describe_unsigned_constant (sizeof(guchar), pspec->minimum);
1152 upper = describe_unsigned_constant (sizeof(guchar), pspec->maximum);
1153 if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT8)
1154 desc = g_strdup ("");
1155 else if (pspec->minimum == 0)
1156 desc = g_strdup_printf ("<= %s", upper);
1157 else if (pspec->maximum == G_MAXUINT8)
1158 desc = g_strdup_printf (">= %s", lower);
1160 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1164 else if (G_IS_PARAM_SPEC_INT (spec))
1166 GParamSpecInt *pspec = G_PARAM_SPEC_INT (spec);
1168 lower = describe_signed_constant (sizeof(gint), pspec->minimum);
1169 upper = describe_signed_constant (sizeof(gint), pspec->maximum);
1170 if (pspec->minimum == G_MININT && pspec->maximum == G_MAXINT)
1171 desc = g_strdup ("");
1172 else if (pspec->minimum == G_MININT)
1173 desc = g_strdup_printf ("<= %s", upper);
1174 else if (pspec->maximum == G_MAXINT)
1175 desc = g_strdup_printf (">= %s", lower);
1177 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1181 else if (G_IS_PARAM_SPEC_UINT (spec))
1183 GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (spec);
1185 lower = describe_unsigned_constant (sizeof(guint), pspec->minimum);
1186 upper = describe_unsigned_constant (sizeof(guint), pspec->maximum);
1187 if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT)
1188 desc = g_strdup ("");
1189 else if (pspec->minimum == 0)
1190 desc = g_strdup_printf ("<= %s", upper);
1191 else if (pspec->maximum == G_MAXUINT)
1192 desc = g_strdup_printf (">= %s", lower);
1194 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1198 else if (G_IS_PARAM_SPEC_LONG (spec))
1200 GParamSpecLong *pspec = G_PARAM_SPEC_LONG (spec);
1202 lower = describe_signed_constant (sizeof(glong), pspec->minimum);
1203 upper = describe_signed_constant (sizeof(glong), pspec->maximum);
1204 if (pspec->minimum == G_MINLONG && pspec->maximum == G_MAXLONG)
1205 desc = g_strdup ("");
1206 else if (pspec->minimum == G_MINLONG)
1207 desc = g_strdup_printf ("<= %s", upper);
1208 else if (pspec->maximum == G_MAXLONG)
1209 desc = g_strdup_printf (">= %s", lower);
1211 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1215 else if (G_IS_PARAM_SPEC_ULONG (spec))
1217 GParamSpecULong *pspec = G_PARAM_SPEC_ULONG (spec);
1219 lower = describe_unsigned_constant (sizeof(gulong), pspec->minimum);
1220 upper = describe_unsigned_constant (sizeof(gulong), pspec->maximum);
1221 if (pspec->minimum == 0 && pspec->maximum == G_MAXULONG)
1222 desc = g_strdup ("");
1223 else if (pspec->minimum == 0)
1224 desc = g_strdup_printf ("<= %s", upper);
1225 else if (pspec->maximum == G_MAXULONG)
1226 desc = g_strdup_printf (">= %s", lower);
1228 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1232 else if (G_IS_PARAM_SPEC_INT64 (spec))
1234 GParamSpecInt64 *pspec = G_PARAM_SPEC_INT64 (spec);
1236 lower = describe_signed_constant (sizeof(gint64), pspec->minimum);
1237 upper = describe_signed_constant (sizeof(gint64), pspec->maximum);
1238 if (pspec->minimum == G_MININT64 && pspec->maximum == G_MAXINT64)
1239 desc = g_strdup ("");
1240 else if (pspec->minimum == G_MININT64)
1241 desc = g_strdup_printf ("<= %s", upper);
1242 else if (pspec->maximum == G_MAXINT64)
1243 desc = g_strdup_printf (">= %s", lower);
1245 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1249 else if (G_IS_PARAM_SPEC_UINT64 (spec))
1251 GParamSpecUInt64 *pspec = G_PARAM_SPEC_UINT64 (spec);
1253 lower = describe_unsigned_constant (sizeof(guint64), pspec->minimum);
1254 upper = describe_unsigned_constant (sizeof(guint64), pspec->maximum);
1255 if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT64)
1256 desc = g_strdup ("");
1257 else if (pspec->minimum == 0)
1258 desc = g_strdup_printf ("<= %s", upper);
1259 else if (pspec->maximum == G_MAXUINT64)
1260 desc = g_strdup_printf (">= %s", lower);
1262 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1266 else if (G_IS_PARAM_SPEC_FLOAT (spec))
1268 GParamSpecFloat *pspec = G_PARAM_SPEC_FLOAT (spec);
1270 lower = describe_double_constant (pspec->minimum);
1271 upper = describe_double_constant (pspec->maximum);
1272 if (GTKDOC_COMPARE_FLOAT (pspec->minimum, -G_MAXFLOAT))
1274 if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXFLOAT))
1275 desc = g_strdup ("");
1277 desc = g_strdup_printf ("<= %s", upper);
1279 else if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXFLOAT))
1280 desc = g_strdup_printf (">= %s", lower);
1282 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1286 else if (G_IS_PARAM_SPEC_DOUBLE (spec))
1288 GParamSpecDouble *pspec = G_PARAM_SPEC_DOUBLE (spec);
1290 lower = describe_double_constant (pspec->minimum);
1291 upper = describe_double_constant (pspec->maximum);
1292 if (GTKDOC_COMPARE_FLOAT (pspec->minimum, -G_MAXDOUBLE))
1294 if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXDOUBLE))
1295 desc = g_strdup ("");
1297 desc = g_strdup_printf ("<= %s", upper);
1299 else if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXDOUBLE))
1300 desc = g_strdup_printf (">= %s", lower);
1302 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1306 #if GLIB_CHECK_VERSION (2, 12, 0)
1307 else if (G_IS_PARAM_SPEC_GTYPE (spec))
1309 GParamSpecGType *pspec = G_PARAM_SPEC_GTYPE (spec);
1310 gboolean is_pointer;
1312 desc = g_strdup (get_type_name (pspec->is_a_type, &is_pointer));
1315 #if GLIB_CHECK_VERSION (2, 25, 9)
1316 else if (G_IS_PARAM_SPEC_VARIANT (spec))
1318 GParamSpecVariant *pspec = G_PARAM_SPEC_VARIANT (spec);
1319 gchar *variant_type;
1321 variant_type = g_variant_type_dup_string (pspec->type);
1322 desc = g_strdup_printf ("GVariant<%s>", variant_type);
1323 g_free (variant_type);
1328 desc = g_strdup ("");
1335 describe_default (GParamSpec *spec)
1339 if (G_IS_PARAM_SPEC_CHAR (spec))
1341 GParamSpecChar *pspec = G_PARAM_SPEC_CHAR (spec);
1343 desc = g_strdup_printf ("%d", pspec->default_value);
1345 else if (G_IS_PARAM_SPEC_UCHAR (spec))
1347 GParamSpecUChar *pspec = G_PARAM_SPEC_UCHAR (spec);
1349 desc = g_strdup_printf ("%u", pspec->default_value);
1351 else if (G_IS_PARAM_SPEC_BOOLEAN (spec))
1353 GParamSpecBoolean *pspec = G_PARAM_SPEC_BOOLEAN (spec);
1355 desc = g_strdup_printf ("%s", pspec->default_value ? "TRUE" : "FALSE");
1357 else if (G_IS_PARAM_SPEC_INT (spec))
1359 GParamSpecInt *pspec = G_PARAM_SPEC_INT (spec);
1361 desc = g_strdup_printf ("%d", pspec->default_value);
1363 else if (G_IS_PARAM_SPEC_UINT (spec))
1365 GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (spec);
1367 desc = g_strdup_printf ("%u", pspec->default_value);
1369 else if (G_IS_PARAM_SPEC_LONG (spec))
1371 GParamSpecLong *pspec = G_PARAM_SPEC_LONG (spec);
1373 desc = g_strdup_printf ("%ld", pspec->default_value);
1375 else if (G_IS_PARAM_SPEC_LONG (spec))
1377 GParamSpecULong *pspec = G_PARAM_SPEC_ULONG (spec);
1379 desc = g_strdup_printf ("%lu", pspec->default_value);
1381 else if (G_IS_PARAM_SPEC_INT64 (spec))
1383 GParamSpecInt64 *pspec = G_PARAM_SPEC_INT64 (spec);
1385 desc = g_strdup_printf ("%" G_GINT64_FORMAT, pspec->default_value);
1387 else if (G_IS_PARAM_SPEC_UINT64 (spec))
1389 GParamSpecUInt64 *pspec = G_PARAM_SPEC_UINT64 (spec);
1391 desc = g_strdup_printf ("%" G_GUINT64_FORMAT, pspec->default_value);
1393 else if (G_IS_PARAM_SPEC_UNICHAR (spec))
1395 GParamSpecUnichar *pspec = G_PARAM_SPEC_UNICHAR (spec);
1397 if (g_unichar_isprint (pspec->default_value))
1398 desc = g_strdup_printf ("'%c'", pspec->default_value);
1400 desc = g_strdup_printf ("%u", pspec->default_value);
1402 else if (G_IS_PARAM_SPEC_ENUM (spec))
1404 GParamSpecEnum *pspec = G_PARAM_SPEC_ENUM (spec);
1406 GEnumValue *value = g_enum_get_value (pspec->enum_class, pspec->default_value);
1408 desc = g_strdup_printf ("%s", value->value_name);
1410 desc = g_strdup_printf ("%d", pspec->default_value);
1412 else if (G_IS_PARAM_SPEC_FLAGS (spec))
1414 GParamSpecFlags *pspec = G_PARAM_SPEC_FLAGS (spec);
1415 guint default_value;
1418 default_value = pspec->default_value;
1419 acc = g_string_new ("");
1421 while (default_value)
1423 GFlagsValue *value = g_flags_get_first_value (pspec->flags_class, default_value);
1429 g_string_append (acc, "|");
1430 g_string_append (acc, value->value_name);
1432 default_value &= ~value->value;
1435 if (default_value == 0)
1436 desc = g_string_free (acc, FALSE);
1439 desc = g_strdup_printf ("%d", pspec->default_value);
1440 g_string_free (acc, TRUE);
1443 else if (G_IS_PARAM_SPEC_FLOAT (spec))
1445 GParamSpecFloat *pspec = G_PARAM_SPEC_FLOAT (spec);
1447 desc = g_strdup_printf ("%g", pspec->default_value);
1449 else if (G_IS_PARAM_SPEC_DOUBLE (spec))
1451 GParamSpecDouble *pspec = G_PARAM_SPEC_DOUBLE (spec);
1453 desc = g_strdup_printf ("%lg", pspec->default_value);
1455 else if (G_IS_PARAM_SPEC_STRING (spec))
1457 GParamSpecString *pspec = G_PARAM_SPEC_STRING (spec);
1459 if (pspec->default_value)
1461 gchar *esc = g_strescape (pspec->default_value, NULL);
1463 desc = g_strdup_printf ("\\"%s\\"", esc);
1468 desc = g_strdup_printf ("NULL");
1470 #if GLIB_CHECK_VERSION (2, 25, 9)
1471 else if (G_IS_PARAM_SPEC_VARIANT (spec))
1473 GParamSpecVariant *pspec = G_PARAM_SPEC_VARIANT (spec);
1475 if (pspec->default_value)
1476 desc = g_variant_print (pspec->default_value, TRUE);
1478 desc = g_strdup ("NULL");
1483 desc = g_strdup ("");
1491 output_object_args (FILE *fp, GType object_type)
1494 const gchar *object_class_name;
1496 gchar flags[16], *pos;
1497 GParamSpec **properties;
1499 gboolean child_prop;
1500 gboolean style_prop;
1501 gboolean is_pointer;
1502 const gchar *type_name;
1504 gchar *default_value;
1506 if (G_TYPE_IS_OBJECT (object_type))
1508 class = g_type_class_peek (object_type);
1512 properties = g_object_class_list_properties (class, &n_properties);
1514 #if GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 3)
1515 else if (G_TYPE_IS_INTERFACE (object_type))
1517 class = g_type_default_interface_ref (object_type);
1522 properties = g_object_interface_list_properties (class, &n_properties);
1528 object_class_name = g_type_name (object_type);
1534 qsort (properties, n_properties, sizeof (GParamSpec *), compare_param_specs);
1535 for (arg = 0; arg < n_properties; arg++)
1537 GParamSpec *spec = properties[arg];
1538 const gchar *nick, *blurb, *dot;
1540 if (spec->owner_type != object_type)
1544 /* We use one-character flags for simplicity. */
1545 if (child_prop && !style_prop)
1549 if (spec->flags & G_PARAM_READABLE)
1551 if (spec->flags & G_PARAM_WRITABLE)
1553 if (spec->flags & G_PARAM_CONSTRUCT)
1555 if (spec->flags & G_PARAM_CONSTRUCT_ONLY)
1559 nick = g_param_spec_get_nick (spec);
1560 blurb = g_param_spec_get_blurb (spec);
1564 int str_len = strlen (blurb);
1565 if (str_len > 0 && blurb[str_len - 1] != '.')
1569 type_desc = describe_type (spec);
1570 default_value = describe_default (spec);
1571 type_name = get_type_name (spec->value_type, &is_pointer);
1572 fprintf (fp, "<ARG>\\n<NAME>%s::%s</NAME>\\n<TYPE>%s%s</TYPE>\\n<RANGE>%s</RANGE>\\n<FLAGS>%s</FLAGS>\\n<NICK>%s</NICK>\\n<BLURB>%s%s</BLURB>\\n<DEFAULT>%s</DEFAULT>\\n</ARG>\\n\\n",
1573 object_class_name, g_param_spec_get_name (spec), type_name, is_pointer ? "*" : "", type_desc, flags, nick ? nick : "(null)", blurb ? blurb : "(null)", dot, default_value);
1575 g_free (default_value);
1578 g_free (properties);
1580 #ifdef GTK_IS_CONTAINER_CLASS
1581 if (!child_prop && GTK_IS_CONTAINER_CLASS (class)) {
1582 properties = gtk_container_class_list_child_properties (class, &n_properties);
1588 #ifdef GTK_IS_WIDGET_CLASS
1589 #if GTK_CHECK_VERSION(2,1,0)
1590 if (!style_prop && GTK_IS_WIDGET_CLASS (class)) {
1591 properties = gtk_widget_class_list_style_properties (GTK_WIDGET_CLASS (class), &n_properties);
1600 if ($QUERY_CHILD_PROPERTIES) {
1603 properties = $QUERY_CHILD_PROPERTIES (class, &n_properties);
1621 # Compile and run our file
1623 $CC = $ENV{CC} ? $ENV{CC} : "gcc";
1624 $LD = $ENV{LD} ? $ENV{LD} : $CC;
1625 $CFLAGS = $ENV{CFLAGS} ? $ENV{CFLAGS} : "";
1626 $LDFLAGS = $ENV{LDFLAGS} ? $ENV{LDFLAGS} : "";
1627 $RUN = $ENV{RUN} ? $ENV{RUN} : "";
1630 if ($CC =~ /libtool/) {
1631 $o_file = "$MODULE-scan.lo"
1633 $o_file = "$MODULE-scan.o"
1636 print "gtk-doc: Compiling scanner\n";
1637 $command = "$CC $CFLAGS -c -o $o_file $MODULE-scan.c";
1638 system("($command)") == 0 or die "Compilation of scanner failed: $!\n";
1640 print "gtk-doc: Linking scanner\n";
1641 # FIXME: Can we turn off as-needed for the docs (or better fix it?)
1642 #$command = "$LD -Wl,--no-as-needed $o_file $LDFLAGS -o $MODULE-scan";
1643 $command = "$LD $o_file $LDFLAGS -o $MODULE-scan";
1644 system("($command)") == 0 or die "Linking of scanner failed: $!\n";
1646 print "gtk-doc: Running scanner $MODULE-scan\n";
1647 system("($RUN ./$MODULE-scan)") == 0 or die "Scan failed: $!\n";
1650 if (!defined($ENV{"GTK_DOC_KEEP_INTERMEDIATE"})) {
1651 unlink "./$MODULE-scan.c", "./$MODULE-scan.o", "./$MODULE-scan.lo", "./$MODULE-scan";
1654 &UpdateFileIfChanged ($old_signals_filename, $new_signals_filename, 0);
1655 &UpdateFileIfChanged ($old_hierarchy_filename, $new_hierarchy_filename, 0);
1656 &UpdateFileIfChanged ($old_interfaces_filename, $new_interfaces_filename, 0);
1657 &UpdateFileIfChanged ($old_prerequisites_filename, $new_prerequisites_filename, 0);
1658 &UpdateFileIfChanged ($old_args_filename, $new_args_filename, 0);