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*. */
512 /* For all GObject subclasses we can use the class name with a "*",
513 e.g. 'GtkWidget *'. */
514 if (g_type_is_a (type, G_TYPE_OBJECT))
517 /* Also catch non GObject root types */
518 if (G_TYPE_IS_CLASSED (type))
521 /* All boxed subtypes will be pointers as well. */
522 if (g_type_is_a (type, G_TYPE_BOXED))
525 /* All pointer subtypes will be pointers as well. */
526 if (g_type_is_a (type, G_TYPE_POINTER))
529 /* But enums are not */
530 if (g_type_is_a (type, G_TYPE_ENUM) ||
531 g_type_is_a (type, G_TYPE_FLAGS))
539 get_gdk_event (const gchar * signal_name)
541 static const gchar *GbGDKEvents[] =
543 "button_press_event", "GdkEventButton",
544 "button_release_event", "GdkEventButton",
545 "motion_notify_event", "GdkEventMotion",
546 "delete_event", "GdkEvent",
547 "destroy_event", "GdkEvent",
548 "expose_event", "GdkEventExpose",
549 "key_press_event", "GdkEventKey",
550 "key_release_event", "GdkEventKey",
551 "enter_notify_event", "GdkEventCrossing",
552 "leave_notify_event", "GdkEventCrossing",
553 "configure_event", "GdkEventConfigure",
554 "focus_in_event", "GdkEventFocus",
555 "focus_out_event", "GdkEventFocus",
556 "map_event", "GdkEvent",
557 "unmap_event", "GdkEvent",
558 "property_notify_event", "GdkEventProperty",
559 "selection_clear_event", "GdkEventSelection",
560 "selection_request_event", "GdkEventSelection",
561 "selection_notify_event", "GdkEventSelection",
562 "proximity_in_event", "GdkEventProximity",
563 "proximity_out_event", "GdkEventProximity",
564 "drag_begin_event", "GdkEventDragBegin",
565 "drag_request_event", "GdkEventDragRequest",
566 "drag_end_event", "GdkEventDragRequest",
567 "drop_enter_event", "GdkEventDropEnter",
568 "drop_leave_event", "GdkEventDropLeave",
569 "drop_data_available_event", "GdkEventDropDataAvailable",
570 "other_event", "GdkEventOther",
571 "client_event", "GdkEventClient",
572 "no_expose_event", "GdkEventNoExpose",
573 "visibility_notify_event", "GdkEventVisibility",
574 "window_state_event", "GdkEventWindowState",
575 "scroll_event", "GdkEventScroll",
581 for (i = 0; GbGDKEvents[i]; i += 2)
583 if (!strcmp (signal_name, GbGDKEvents[i]))
584 return GbGDKEvents[i + 1];
590 /* This returns argument names to use for some known GTK signals.
591 It is passed a widget name, e.g. 'GtkCList' and a signal name, e.g.
592 'select_row' and it returns a pointer to an array of argument types and
594 static const gchar **
595 lookup_signal_arg_names (const gchar * type, const gchar * signal_name)
597 /* Each arg array starts with the object type name and the signal name,
598 and then signal arguments follow. */
599 static const gchar *GbArgTable[][16] =
601 {"GtkCList", "select_row",
604 "GdkEventButton *event"},
605 {"GtkCList", "unselect_row",
608 "GdkEventButton *event"},
609 {"GtkCList", "click_column",
612 {"GtkCList", "resize_column",
616 {"GtkCList", "extend_selection",
617 "GtkScrollType scroll_type",
619 "gboolean auto_start_selection"},
620 {"GtkCList", "scroll_vertical",
621 "GtkScrollType scroll_type",
623 {"GtkCList", "scroll_horizontal",
624 "GtkScrollType scroll_type",
627 {"GtkCTree", "tree_select_row",
628 "GtkCTreeNode *node",
630 {"GtkCTree", "tree_unselect_row",
631 "GtkCTreeNode *node",
633 {"GtkCTree", "tree_expand",
634 "GtkCTreeNode *node"},
635 {"GtkCTree", "tree_collapse",
636 "GtkCTreeNode *node"},
637 {"GtkCTree", "tree_move",
638 "GtkCTreeNode *node",
639 "GtkCTreeNode *new_parent",
640 "GtkCTreeNode *new_sibling"},
641 {"GtkCTree", "change_focus_row_expansion",
642 "GtkCTreeExpansionType expansion"},
644 {"GtkEditable", "insert_text",
646 "gint new_text_length",
648 {"GtkEditable", "delete_text",
651 {"GtkEditable", "set_editable",
652 "gboolean is_editable"},
653 {"GtkEditable", "move_cursor",
656 {"GtkEditable", "move_word",
658 {"GtkEditable", "move_page",
661 {"GtkEditable", "move_to_row",
663 {"GtkEditable", "move_to_column",
666 {"GtkEditable", "kill_char",
668 {"GtkEditable", "kill_word",
670 {"GtkEditable", "kill_line",
674 {"GtkInputDialog", "enable_device",
675 "GdkDevice *deviceid"},
676 {"GtkInputDialog", "disable_device",
677 "GdkDevice *deviceid"},
679 {"GtkListItem", "extend_selection",
680 "GtkScrollType scroll_type",
682 "gboolean auto_start_selection"},
683 {"GtkListItem", "scroll_vertical",
684 "GtkScrollType scroll_type",
686 {"GtkListItem", "scroll_horizontal",
687 "GtkScrollType scroll_type",
690 {"GtkMenuShell", "move_current",
691 "GtkMenuDirectionType direction"},
692 {"GtkMenuShell", "activate_current",
693 "gboolean force_hide"},
696 {"GtkNotebook", "switch_page",
697 "GtkNotebookPage *page",
699 {"GtkStatusbar", "text_pushed",
702 {"GtkStatusbar", "text_popped",
705 {"GtkTipsQuery", "widget_entered",
708 "gchar *tip_private"},
709 {"GtkTipsQuery", "widget_selected",
712 "gchar *tip_private",
713 "GdkEventButton *event"},
714 {"GtkToolbar", "orientation_changed",
715 "GtkOrientation orientation"},
716 {"GtkToolbar", "style_changed",
717 "GtkToolbarStyle style"},
718 {"GtkWidget", "draw",
719 "GdkRectangle *area"},
720 {"GtkWidget", "size_request",
721 "GtkRequisition *requisition"},
722 {"GtkWidget", "size_allocate",
723 "GtkAllocation *allocation"},
724 {"GtkWidget", "state_changed",
725 "GtkStateType state"},
726 {"GtkWidget", "style_set",
727 "GtkStyle *previous_style"},
729 {"GtkWidget", "install_accelerator",
730 "gchar *signal_name",
734 {"GtkWidget", "add_accelerator",
735 "guint accel_signal_id",
736 "GtkAccelGroup *accel_group",
738 "GdkModifierType accel_mods",
739 "GtkAccelFlags accel_flags"},
741 {"GtkWidget", "parent_set",
742 "GtkObject *old_parent"},
744 {"GtkWidget", "remove_accelerator",
745 "GtkAccelGroup *accel_group",
747 "GdkModifierType accel_mods"},
748 {"GtkWidget", "debug_msg",
750 {"GtkWindow", "move_resize",
755 {"GtkWindow", "set_focus",
756 "GtkWidget *widget"},
758 {"GtkWidget", "selection_get",
759 "GtkSelectionData *data",
762 {"GtkWidget", "selection_received",
763 "GtkSelectionData *data",
766 {"GtkWidget", "drag_begin",
767 "GdkDragContext *drag_context"},
768 {"GtkWidget", "drag_end",
769 "GdkDragContext *drag_context"},
770 {"GtkWidget", "drag_data_delete",
771 "GdkDragContext *drag_context"},
772 {"GtkWidget", "drag_leave",
773 "GdkDragContext *drag_context",
775 {"GtkWidget", "drag_motion",
776 "GdkDragContext *drag_context",
780 {"GtkWidget", "drag_drop",
781 "GdkDragContext *drag_context",
785 {"GtkWidget", "drag_data_get",
786 "GdkDragContext *drag_context",
787 "GtkSelectionData *data",
790 {"GtkWidget", "drag_data_received",
791 "GdkDragContext *drag_context",
794 "GtkSelectionData *data",
803 for (i = 0; GbArgTable[i][0]; i++)
806 if (!strcmp (type, GbArgTable[i][0])
807 && !strcmp (signal_name, GbArgTable[i][1]))
808 return &GbArgTable[i][2];
814 /* This outputs the hierarchy of all objects which have been initialized,
815 i.e. by calling their XXX_get_type() initialization function. */
817 output_object_hierarchy (void)
822 fp = fopen (hierarchy_filename, "w");
825 g_warning ("Couldn't open output file: %s : %s", hierarchy_filename, g_strerror(errno));
828 output_hierarchy (fp, G_TYPE_OBJECT, 0);
829 output_hierarchy (fp, G_TYPE_INTERFACE, 0);
831 for (i=0; object_types[i]; i++) {
832 if (!g_type_parent (object_types[i]) &&
833 (object_types[i] != G_TYPE_OBJECT) &&
834 (object_types[i] != G_TYPE_INTERFACE)
836 output_hierarchy (fp, object_types[i], 0);
843 /* This is called recursively to output the hierarchy of a widget. */
845 output_hierarchy (FILE *fp,
856 for (i = 0; i < level; i++)
858 fprintf (fp, "%s\\n", g_type_name (type));
860 children = g_type_children (type, &n_children);
862 for (i=0; i < n_children; i++)
863 output_hierarchy (fp, children[i], level + 1);
868 static void output_object_interfaces (void)
873 fp = fopen (interfaces_filename, "w");
876 g_warning ("Couldn't open output file: %s : %s", interfaces_filename, g_strerror(errno));
879 output_interfaces (fp, G_TYPE_OBJECT);
881 for (i = 0; object_types[i]; i++)
883 if (!g_type_parent (object_types[i]) &&
884 (object_types[i] != G_TYPE_OBJECT) &&
885 G_TYPE_IS_INSTANTIATABLE (object_types[i]))
887 output_interfaces (fp, object_types[i]);
894 output_interfaces (FILE *fp,
898 GType *children, *interfaces;
899 guint n_children, n_interfaces;
904 interfaces = g_type_interfaces (type, &n_interfaces);
906 if (n_interfaces > 0)
908 fprintf (fp, "%s", g_type_name (type));
909 for (i=0; i < n_interfaces; i++)
910 fprintf (fp, " %s", g_type_name (interfaces[i]));
915 children = g_type_children (type, &n_children);
917 for (i=0; i < n_children; i++)
918 output_interfaces (fp, children[i]);
923 static void output_interface_prerequisites (void)
927 fp = fopen (prerequisites_filename, "w");
930 g_warning ("Couldn't open output file: %s : %s", prerequisites_filename, g_strerror(errno));
933 output_prerequisites (fp, G_TYPE_INTERFACE);
938 output_prerequisites (FILE *fp,
941 #if GLIB_CHECK_VERSION(2,1,0)
943 GType *children, *prerequisites;
944 guint n_children, n_prerequisites;
949 prerequisites = g_type_interface_prerequisites (type, &n_prerequisites);
951 if (n_prerequisites > 0)
953 fprintf (fp, "%s", g_type_name (type));
954 for (i=0; i < n_prerequisites; i++)
955 fprintf (fp, " %s", g_type_name (prerequisites[i]));
958 g_free (prerequisites);
960 children = g_type_children (type, &n_children);
962 for (i=0; i < n_children; i++)
963 output_prerequisites (fp, children[i]);
975 fp = fopen (args_filename, "w");
978 g_warning ("Couldn't open output file: %s : %s", args_filename, g_strerror(errno));
982 for (i = 0; object_types[i]; i++) {
983 output_object_args (fp, object_types[i]);
990 compare_param_specs (const void *a, const void *b)
992 GParamSpec *spec_a = *(GParamSpec **)a;
993 GParamSpec *spec_b = *(GParamSpec **)b;
995 return strcmp (g_param_spec_get_name (spec_a), g_param_spec_get_name (spec_b));
998 /* Its common to have unsigned properties restricted
999 * to the signed range. Therefore we make this look
1000 * a bit nicer by spelling out the max constants.
1003 /* Don't use "==" with floats, it might trigger a gcc warning. */
1004 #define GTKDOC_COMPARE_FLOAT(x, y) (x <= y && x >= y)
1007 describe_double_constant (gdouble value)
1011 if (GTKDOC_COMPARE_FLOAT (value, G_MAXDOUBLE))
1012 desc = g_strdup ("G_MAXDOUBLE");
1013 else if (GTKDOC_COMPARE_FLOAT (value, G_MINDOUBLE))
1014 desc = g_strdup ("G_MINDOUBLE");
1015 else if (GTKDOC_COMPARE_FLOAT (value, -G_MAXDOUBLE))
1016 desc = g_strdup ("-G_MAXDOUBLE");
1017 else if (GTKDOC_COMPARE_FLOAT (value, G_MAXFLOAT))
1018 desc = g_strdup ("G_MAXFLOAT");
1019 else if (GTKDOC_COMPARE_FLOAT (value, G_MINFLOAT))
1020 desc = g_strdup ("G_MINFLOAT");
1021 else if (GTKDOC_COMPARE_FLOAT (value, -G_MAXFLOAT))
1022 desc = g_strdup ("-G_MAXFLOAT");
1024 desc = g_strdup_printf ("%lg", value);
1030 describe_signed_constant (gsize size, gint64 value)
1036 if (sizeof (int) == 2) {
1037 if (value == G_MAXINT)
1038 desc = g_strdup ("G_MAXINT");
1039 else if (value == G_MININT)
1040 desc = g_strdup ("G_MININT");
1041 else if (value == (gint64)G_MAXUINT)
1042 desc = g_strdup ("G_MAXUINT");
1046 if (sizeof (int) == 4) {
1047 if (value == G_MAXINT)
1048 desc = g_strdup ("G_MAXINT");
1049 else if (value == G_MININT)
1050 desc = g_strdup ("G_MININT");
1051 else if (value == (gint64)G_MAXUINT)
1052 desc = g_strdup ("G_MAXUINT");
1054 if (value == G_MAXLONG)
1055 desc = g_strdup ("G_MAXLONG");
1056 else if (value == G_MINLONG)
1057 desc = g_strdup ("G_MINLONG");
1058 else if (value == (gint64)G_MAXULONG)
1059 desc = g_strdup ("G_MAXULONG");
1062 if (value == G_MAXINT64)
1063 desc = g_strdup ("G_MAXINT64");
1064 else if (value == G_MININT64)
1065 desc = g_strdup ("G_MININT64");
1071 desc = g_strdup_printf ("%" G_GINT64_FORMAT, value);
1077 describe_unsigned_constant (gsize size, guint64 value)
1083 if (sizeof (int) == 2) {
1084 if (value == (guint64)G_MAXINT)
1085 desc = g_strdup ("G_MAXINT");
1086 else if (value == G_MAXUINT)
1087 desc = g_strdup ("G_MAXUINT");
1091 if (sizeof (int) == 4) {
1092 if (value == (guint64)G_MAXINT)
1093 desc = g_strdup ("G_MAXINT");
1094 else if (value == G_MAXUINT)
1095 desc = g_strdup ("G_MAXUINT");
1097 if (value == (guint64)G_MAXLONG)
1098 desc = g_strdup ("G_MAXLONG");
1099 else if (value == G_MAXULONG)
1100 desc = g_strdup ("G_MAXULONG");
1103 if (value == G_MAXINT64)
1104 desc = g_strdup ("G_MAXINT64");
1105 else if (value == G_MAXUINT64)
1106 desc = g_strdup ("G_MAXUINT64");
1112 desc = g_strdup_printf ("%" G_GUINT64_FORMAT, value);
1118 describe_type (GParamSpec *spec)
1124 if (G_IS_PARAM_SPEC_CHAR (spec))
1126 GParamSpecChar *pspec = G_PARAM_SPEC_CHAR (spec);
1128 lower = describe_signed_constant (sizeof(gchar), pspec->minimum);
1129 upper = describe_signed_constant (sizeof(gchar), pspec->maximum);
1130 if (pspec->minimum == G_MININT8 && pspec->maximum == G_MAXINT8)
1131 desc = g_strdup ("");
1132 else if (pspec->minimum == G_MININT8)
1133 desc = g_strdup_printf ("<= %s", upper);
1134 else if (pspec->maximum == G_MAXINT8)
1135 desc = g_strdup_printf (">= %s", lower);
1137 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1141 else if (G_IS_PARAM_SPEC_UCHAR (spec))
1143 GParamSpecUChar *pspec = G_PARAM_SPEC_UCHAR (spec);
1145 lower = describe_unsigned_constant (sizeof(guchar), pspec->minimum);
1146 upper = describe_unsigned_constant (sizeof(guchar), pspec->maximum);
1147 if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT8)
1148 desc = g_strdup ("");
1149 else if (pspec->minimum == 0)
1150 desc = g_strdup_printf ("<= %s", upper);
1151 else if (pspec->maximum == G_MAXUINT8)
1152 desc = g_strdup_printf (">= %s", lower);
1154 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1158 else if (G_IS_PARAM_SPEC_INT (spec))
1160 GParamSpecInt *pspec = G_PARAM_SPEC_INT (spec);
1162 lower = describe_signed_constant (sizeof(gint), pspec->minimum);
1163 upper = describe_signed_constant (sizeof(gint), pspec->maximum);
1164 if (pspec->minimum == G_MININT && pspec->maximum == G_MAXINT)
1165 desc = g_strdup ("");
1166 else if (pspec->minimum == G_MININT)
1167 desc = g_strdup_printf ("<= %s", upper);
1168 else if (pspec->maximum == G_MAXINT)
1169 desc = g_strdup_printf (">= %s", lower);
1171 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1175 else if (G_IS_PARAM_SPEC_UINT (spec))
1177 GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (spec);
1179 lower = describe_unsigned_constant (sizeof(guint), pspec->minimum);
1180 upper = describe_unsigned_constant (sizeof(guint), pspec->maximum);
1181 if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT)
1182 desc = g_strdup ("");
1183 else if (pspec->minimum == 0)
1184 desc = g_strdup_printf ("<= %s", upper);
1185 else if (pspec->maximum == G_MAXUINT)
1186 desc = g_strdup_printf (">= %s", lower);
1188 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1192 else if (G_IS_PARAM_SPEC_LONG (spec))
1194 GParamSpecLong *pspec = G_PARAM_SPEC_LONG (spec);
1196 lower = describe_signed_constant (sizeof(glong), pspec->minimum);
1197 upper = describe_signed_constant (sizeof(glong), pspec->maximum);
1198 if (pspec->minimum == G_MINLONG && pspec->maximum == G_MAXLONG)
1199 desc = g_strdup ("");
1200 else if (pspec->minimum == G_MINLONG)
1201 desc = g_strdup_printf ("<= %s", upper);
1202 else if (pspec->maximum == G_MAXLONG)
1203 desc = g_strdup_printf (">= %s", lower);
1205 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1209 else if (G_IS_PARAM_SPEC_ULONG (spec))
1211 GParamSpecULong *pspec = G_PARAM_SPEC_ULONG (spec);
1213 lower = describe_unsigned_constant (sizeof(gulong), pspec->minimum);
1214 upper = describe_unsigned_constant (sizeof(gulong), pspec->maximum);
1215 if (pspec->minimum == 0 && pspec->maximum == G_MAXULONG)
1216 desc = g_strdup ("");
1217 else if (pspec->minimum == 0)
1218 desc = g_strdup_printf ("<= %s", upper);
1219 else if (pspec->maximum == G_MAXULONG)
1220 desc = g_strdup_printf (">= %s", lower);
1222 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1226 else if (G_IS_PARAM_SPEC_INT64 (spec))
1228 GParamSpecInt64 *pspec = G_PARAM_SPEC_INT64 (spec);
1230 lower = describe_signed_constant (sizeof(gint64), pspec->minimum);
1231 upper = describe_signed_constant (sizeof(gint64), pspec->maximum);
1232 if (pspec->minimum == G_MININT64 && pspec->maximum == G_MAXINT64)
1233 desc = g_strdup ("");
1234 else if (pspec->minimum == G_MININT64)
1235 desc = g_strdup_printf ("<= %s", upper);
1236 else if (pspec->maximum == G_MAXINT64)
1237 desc = g_strdup_printf (">= %s", lower);
1239 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1243 else if (G_IS_PARAM_SPEC_UINT64 (spec))
1245 GParamSpecUInt64 *pspec = G_PARAM_SPEC_UINT64 (spec);
1247 lower = describe_unsigned_constant (sizeof(guint64), pspec->minimum);
1248 upper = describe_unsigned_constant (sizeof(guint64), pspec->maximum);
1249 if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT64)
1250 desc = g_strdup ("");
1251 else if (pspec->minimum == 0)
1252 desc = g_strdup_printf ("<= %s", upper);
1253 else if (pspec->maximum == G_MAXUINT64)
1254 desc = g_strdup_printf (">= %s", lower);
1256 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1260 else if (G_IS_PARAM_SPEC_FLOAT (spec))
1262 GParamSpecFloat *pspec = G_PARAM_SPEC_FLOAT (spec);
1264 lower = describe_double_constant (pspec->minimum);
1265 upper = describe_double_constant (pspec->maximum);
1266 if (GTKDOC_COMPARE_FLOAT (pspec->minimum, -G_MAXFLOAT))
1268 if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXFLOAT))
1269 desc = g_strdup ("");
1271 desc = g_strdup_printf ("<= %s", upper);
1273 else if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXFLOAT))
1274 desc = g_strdup_printf (">= %s", lower);
1276 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1280 else if (G_IS_PARAM_SPEC_DOUBLE (spec))
1282 GParamSpecDouble *pspec = G_PARAM_SPEC_DOUBLE (spec);
1284 lower = describe_double_constant (pspec->minimum);
1285 upper = describe_double_constant (pspec->maximum);
1286 if (GTKDOC_COMPARE_FLOAT (pspec->minimum, -G_MAXDOUBLE))
1288 if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXDOUBLE))
1289 desc = g_strdup ("");
1291 desc = g_strdup_printf ("<= %s", upper);
1293 else if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXDOUBLE))
1294 desc = g_strdup_printf (">= %s", lower);
1296 desc = g_strdup_printf ("[%s,%s]", lower, upper);
1302 desc = g_strdup ("");
1309 describe_default (GParamSpec *spec)
1313 if (G_IS_PARAM_SPEC_CHAR (spec))
1315 GParamSpecChar *pspec = G_PARAM_SPEC_CHAR (spec);
1317 desc = g_strdup_printf ("%d", pspec->default_value);
1319 else if (G_IS_PARAM_SPEC_UCHAR (spec))
1321 GParamSpecUChar *pspec = G_PARAM_SPEC_UCHAR (spec);
1323 desc = g_strdup_printf ("%u", pspec->default_value);
1325 else if (G_IS_PARAM_SPEC_BOOLEAN (spec))
1327 GParamSpecBoolean *pspec = G_PARAM_SPEC_BOOLEAN (spec);
1329 desc = g_strdup_printf ("%s", pspec->default_value ? "TRUE" : "FALSE");
1331 else if (G_IS_PARAM_SPEC_INT (spec))
1333 GParamSpecInt *pspec = G_PARAM_SPEC_INT (spec);
1335 desc = g_strdup_printf ("%d", pspec->default_value);
1337 else if (G_IS_PARAM_SPEC_UINT (spec))
1339 GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (spec);
1341 desc = g_strdup_printf ("%u", pspec->default_value);
1343 else if (G_IS_PARAM_SPEC_LONG (spec))
1345 GParamSpecLong *pspec = G_PARAM_SPEC_LONG (spec);
1347 desc = g_strdup_printf ("%ld", pspec->default_value);
1349 else if (G_IS_PARAM_SPEC_LONG (spec))
1351 GParamSpecULong *pspec = G_PARAM_SPEC_ULONG (spec);
1353 desc = g_strdup_printf ("%lu", pspec->default_value);
1355 else if (G_IS_PARAM_SPEC_INT64 (spec))
1357 GParamSpecInt64 *pspec = G_PARAM_SPEC_INT64 (spec);
1359 desc = g_strdup_printf ("%" G_GINT64_FORMAT, pspec->default_value);
1361 else if (G_IS_PARAM_SPEC_UINT64 (spec))
1363 GParamSpecUInt64 *pspec = G_PARAM_SPEC_UINT64 (spec);
1365 desc = g_strdup_printf ("%" G_GUINT64_FORMAT, pspec->default_value);
1367 else if (G_IS_PARAM_SPEC_UNICHAR (spec))
1369 GParamSpecUnichar *pspec = G_PARAM_SPEC_UNICHAR (spec);
1371 if (g_unichar_isprint (pspec->default_value))
1372 desc = g_strdup_printf ("'%c'", pspec->default_value);
1374 desc = g_strdup_printf ("%u", pspec->default_value);
1376 else if (G_IS_PARAM_SPEC_ENUM (spec))
1378 GParamSpecEnum *pspec = G_PARAM_SPEC_ENUM (spec);
1380 GEnumValue *value = g_enum_get_value (pspec->enum_class, pspec->default_value);
1382 desc = g_strdup_printf ("%s", value->value_name);
1384 desc = g_strdup_printf ("%d", pspec->default_value);
1386 else if (G_IS_PARAM_SPEC_FLAGS (spec))
1388 GParamSpecFlags *pspec = G_PARAM_SPEC_FLAGS (spec);
1389 guint default_value;
1392 default_value = pspec->default_value;
1393 acc = g_string_new ("");
1395 while (default_value)
1397 GFlagsValue *value = g_flags_get_first_value (pspec->flags_class, default_value);
1403 g_string_append (acc, "|");
1404 g_string_append (acc, value->value_name);
1406 default_value &= ~value->value;
1409 if (default_value == 0)
1410 desc = g_string_free (acc, FALSE);
1413 desc = g_strdup_printf ("%d", pspec->default_value);
1414 g_string_free (acc, TRUE);
1417 else if (G_IS_PARAM_SPEC_FLOAT (spec))
1419 GParamSpecFloat *pspec = G_PARAM_SPEC_FLOAT (spec);
1421 desc = g_strdup_printf ("%g", pspec->default_value);
1423 else if (G_IS_PARAM_SPEC_DOUBLE (spec))
1425 GParamSpecDouble *pspec = G_PARAM_SPEC_DOUBLE (spec);
1427 desc = g_strdup_printf ("%lg", pspec->default_value);
1429 else if (G_IS_PARAM_SPEC_STRING (spec))
1431 GParamSpecString *pspec = G_PARAM_SPEC_STRING (spec);
1433 if (pspec->default_value)
1435 gchar *esc = g_strescape (pspec->default_value, NULL);
1437 desc = g_strdup_printf ("\\"%s\\"", esc);
1442 desc = g_strdup_printf ("NULL");
1446 desc = g_strdup ("");
1454 output_object_args (FILE *fp, GType object_type)
1457 const gchar *object_class_name;
1459 gchar flags[16], *pos;
1460 GParamSpec **properties;
1462 gboolean child_prop;
1463 gboolean style_prop;
1464 gboolean is_pointer;
1465 const gchar *type_name;
1467 gchar *default_value;
1469 if (G_TYPE_IS_OBJECT (object_type))
1471 class = g_type_class_peek (object_type);
1475 properties = g_object_class_list_properties (class, &n_properties);
1477 #if GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 3)
1478 else if (G_TYPE_IS_INTERFACE (object_type))
1480 class = g_type_default_interface_ref (object_type);
1485 properties = g_object_interface_list_properties (class, &n_properties);
1491 object_class_name = g_type_name (object_type);
1497 qsort (properties, n_properties, sizeof (GParamSpec *), compare_param_specs);
1498 for (arg = 0; arg < n_properties; arg++)
1500 GParamSpec *spec = properties[arg];
1501 const gchar *nick, *blurb, *dot;
1503 if (spec->owner_type != object_type)
1507 /* We use one-character flags for simplicity. */
1508 if (child_prop && !style_prop)
1512 if (spec->flags & G_PARAM_READABLE)
1514 if (spec->flags & G_PARAM_WRITABLE)
1516 if (spec->flags & G_PARAM_CONSTRUCT)
1518 if (spec->flags & G_PARAM_CONSTRUCT_ONLY)
1522 nick = g_param_spec_get_nick (spec);
1523 blurb = g_param_spec_get_blurb (spec);
1527 int str_len = strlen (blurb);
1528 if (str_len > 0 && blurb[str_len - 1] != '.')
1532 type_desc = describe_type (spec);
1533 default_value = describe_default (spec);
1534 type_name = get_type_name (spec->value_type, &is_pointer);
1535 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",
1536 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);
1538 g_free (default_value);
1541 g_free (properties);
1543 #ifdef GTK_IS_CONTAINER_CLASS
1544 if (!child_prop && GTK_IS_CONTAINER_CLASS (class)) {
1545 properties = gtk_container_class_list_child_properties (class, &n_properties);
1551 #ifdef GTK_IS_WIDGET_CLASS
1552 #if GTK_CHECK_VERSION(2,1,0)
1553 if (!style_prop && GTK_IS_WIDGET_CLASS (class)) {
1554 properties = gtk_widget_class_list_style_properties (GTK_WIDGET_CLASS (class), &n_properties);
1563 if ($QUERY_CHILD_PROPERTIES) {
1566 properties = $QUERY_CHILD_PROPERTIES (class, &n_properties);
1584 # Compile and run our file
1586 $CC = $ENV{CC} ? $ENV{CC} : "gcc";
1587 $LD = $ENV{LD} ? $ENV{LD} : $CC;
1588 $CFLAGS = $ENV{CFLAGS} ? $ENV{CFLAGS} : "";
1589 $LDFLAGS = $ENV{LDFLAGS} ? $ENV{LDFLAGS} : "";
1590 $RUN = $ENV{RUN} ? $ENV{RUN} : "";
1593 if ($CC =~ /libtool/) {
1594 $o_file = "$MODULE-scan.lo"
1596 $o_file = "$MODULE-scan.o"
1599 print "gtk-doc: Compiling scanner\n";
1600 $command = "$CC $CFLAGS -c -o $o_file $MODULE-scan.c";
1601 system("($command)") == 0 or die "Compilation of scanner failed: $!\n";
1603 print "gtk-doc: Linking scanner\n";
1604 # FIXME: Can we turn off as-needed for the docs (or better fix it?)
1605 #$command = "$LD -Wl,--no-as-needed $o_file $LDFLAGS -o $MODULE-scan";
1606 $command = "$LD $o_file $LDFLAGS -o $MODULE-scan";
1607 system("($command)") == 0 or die "Linking of scanner failed: $!\n";
1609 print "gtk-doc: Running scanner $MODULE-scan\n";
1610 system("($RUN ./$MODULE-scan)") == 0 or die "Scan failed: $!\n";
1613 if (!defined($ENV{"GTK_DOC_KEEP_INTERMEDIATE"})) {
1614 unlink "./$MODULE-scan.c", "./$MODULE-scan.o", "./$MODULE-scan.lo", "./$MODULE-scan";
1617 &UpdateFileIfChanged ($old_signals_filename, $new_signals_filename, 0);
1618 &UpdateFileIfChanged ($old_hierarchy_filename, $new_hierarchy_filename, 0);
1619 &UpdateFileIfChanged ($old_interfaces_filename, $new_interfaces_filename, 0);
1620 &UpdateFileIfChanged ($old_prerequisites_filename, $new_prerequisites_filename, 0);
1621 &UpdateFileIfChanged ($old_args_filename, $new_args_filename, 0);