tests: fix gobject warnings
[gtk-doc.git] / gtkdoc-scanobj.in
blob96d7902074c576e58bfe3db746435ad78491c269
1 #!@PERL@ -w
2 # -*- cperl -*-
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
33 use Getopt::Long;
35 push @INC, '@PACKAGE_DATA_DIR@';
36 require "gtkdoc-common.pl";
38 # Options
40 # name of documentation module
41 my $MODULE;
42 my $OUTPUT_DIR;
43 my $PRINT_VERSION;
45 %optctl = (module => \$MODULE,
46            types => \$TYPES_FILE,
47            nogtkinit => \$NO_GTK_INIT,
48            'output-dir' => \$OUTPUT_DIR,
49            'version' => \$PRINT_VERSION,
50            'help' => \$PRINT_HELP);
51            
52 GetOptions(\%optctl, "module=s", "types:s", "output-dir:s", "nogtkinit", "version", "help");
54 if ($PRINT_VERSION) {
55     print "@VERSION@\n";
56     exit 0;
59 if (!$MODULE) {
60     $PRINT_HELP = 1;
63 if ($PRINT_HELP) {
64     print <<EOF;
65 gtkdoc-scanobj version @VERSION@ - introspect gtk-objects
67 --module=MODULE_NAME          Name of the doc module being parsed
68 --types=FILE                  The name of the file to store the types in
69 --output-dir=DIRNAME          The directory where the results are stored
70 --version                     Print the version of this program
71 --help                        Print this help
72 EOF
73     exit 0;
76 $OUTPUT_DIR = $OUTPUT_DIR ? $OUTPUT_DIR : ".";
78 $TYPES_FILE = $TYPES_FILE ? $TYPES_FILE : "$OUTPUT_DIR/$MODULE.types";
80 open (TYPES, $TYPES_FILE) || die "Cannot open $TYPES_FILE: $!\n";
81 open (OUTPUT, ">$MODULE-scan.c") || die "Cannot open $MODULE-scan.c: $!\n";
83 my $old_signals_filename = "$OUTPUT_DIR/$MODULE.signals";
84 my $new_signals_filename = "$OUTPUT_DIR/$MODULE.signals.new";
85 my $old_hierarchy_filename = "$OUTPUT_DIR/$MODULE.hierarchy";
86 my $new_hierarchy_filename = "$OUTPUT_DIR/$MODULE.hierarchy.new";
87 my $old_args_filename = "$OUTPUT_DIR/$MODULE.args";
88 my $new_args_filename = "$OUTPUT_DIR/$MODULE.args.new";
90 # write a C program to scan the types
92 $includes = "";
93 @types = ();
95 for (<TYPES>) {
96     if (/^#include/) {
97         $includes .= $_;
98     } elsif (/^%/) {
99         next;
100     } elsif (/^\s*$/) {
101         next;
102     } else {
103         chomp;
104         push @types, $_;
105     }
108 $ntypes = @types + 1;
110 print OUTPUT <<EOT;
111 #include <string.h>
112 #include <stdlib.h>
113 #include <stdio.h>
114 #include <errno.h>
116 $includes
117 GtkType object_types[$ntypes];
119 GtkType *
120 get_object_types (void)
122     gint i = 0;
125 for (@types) {
126     print OUTPUT "    object_types[i++] = $_ ();\n";
129 print OUTPUT <<EOT;
130     object_types[i] = 0;
132     return object_types;
136  * This uses GTK type functions to output signal prototypes and the widget
137  * hierarchy.
138  */
140 /* The output files */
141 gchar *signals_filename = "$new_signals_filename";
142 gchar *hierarchy_filename = "$new_hierarchy_filename";
143 gchar *args_filename = "$new_args_filename";
146 static void output_signals (void);
147 static void output_widget_signals (FILE *fp,
148                                    GtkType object_type);
149 static void output_widget_signal (FILE *fp,
150                                   GtkType object_type,
151                                   gchar *object_class_name,
152                                   guint signal_id);
153 static gchar * get_type_name (GtkType type,
154                               gboolean * is_pointer);
155 static gchar * get_gdk_event (const gchar * signal_name);
156 static gchar ** lookup_signal_arg_names (gchar * type,
157                                          const gchar * signal_name);
159 static void output_widget_hierarchy (void);
160 static void output_hierarchy (FILE *fp,
161                               GtkType type,
162                               guint level);
164 static void output_args (void);
165 static void output_widget_args (FILE *fp, GtkType object_type);
168 main (int argc, char *argv[])
172   if ($NO_GTK_INIT) {
173     print OUTPUT <<EOT;
174   gtk_type_init ();
176   } else {
177     print OUTPUT <<EOT;
178   gtk_init (&argc, &argv);
180   }
182 print OUTPUT <<EOT;
183   get_object_types ();
185   output_signals ();
186   output_widget_hierarchy ();
187   output_args ();
189   return 0;
193 static void
194 output_signals (void)
196   FILE *fp;
197   gint i;
199   fp = fopen (signals_filename, "w");
200   if (fp == NULL)
201     {
202       g_warning ("Couldn't open output file: %s : %s", signals_filename, g_strerror(errno));
203       return;
204     }
206   for (i = 0; object_types[i]; i++)
207     output_widget_signals (fp, object_types[i]);
209   fclose (fp);
213 /* This outputs all the signals of one widget. */
214 static void
215 output_widget_signals (FILE *fp, GtkType object_type)
217   GtkObjectClass *class;
218   gchar *object_class_name;
219   guint sig;
221   class = gtk_type_class (object_type);
222   if (!class || class->nsignals == 0)
223     return;
225   object_class_name = gtk_type_name (object_type);
227   for (sig = 0; sig < class->nsignals; sig++)
228     {
229       if (!class->signals[sig])
230         {
231           /*g_print ("Signal slot [%u] is empty\\n", sig);*/
232           continue;
233         }
235       output_widget_signal (fp, object_type, object_class_name,
236                             class->signals[sig]);
237     }
241 /* This outputs one signal. */
242 static void
243 output_widget_signal (FILE *fp,
244                       GtkType object_type,
245                       gchar *object_name,
246                       guint signal_id)
248   GtkSignalQuery *query_info;
249   gchar *ret_type, *pos, *type_name, *arg_name, *object_arg, *object_arg_start;
250   gboolean is_pointer;
251   gchar buffer[1024];
252   guint i, param;
253   gchar **arg_names;
254   gint param_num, widget_num, event_num, callback_num;
255   gint *arg_num;
256   gchar signal_name[128];
258   /*  g_print ("Object: %s Type: %i Signal: %u\\n", object_name, object_type,
259       signal_id);*/
261   param_num = 1;
262   widget_num = event_num = callback_num = 0;
264   query_info = gtk_signal_query (signal_id);
265   if (query_info == NULL)
266     {
267       g_warning ("Couldn't query signal");
268       return;
269     }
271   /* Output the signal object type and the argument name. We assume the
272      type is a pointer - I think that is OK. We remove "Gtk" or "Gnome" and
273      convert to lower case for the argument name. */
274   pos = buffer;
275   sprintf (pos, "%s ", object_name);
276   pos += strlen (pos);
278   /* Try to come up with a sensible variable name for the first arg
279    * I chops off 2 know prefixes :/ and makes the name lowercase
280    * It should replace lowercase -> uppercase with '_'
281    * see gtkdoc-scangobject.in for better algorithm
282    */
283   if (!strncmp (object_name, "Gtk", 3))
284       object_arg = object_name + 3;
285   else if (!strncmp (object_name, "Gnome", 5))
286       object_arg = object_name + 5;
287   else
288       object_arg = object_name;
290   object_arg_start = pos;
291   sprintf (pos, "*%s\\n", object_arg);
292   pos += strlen (pos);
293   g_strdown (object_arg_start);
294   if (!strcmp (object_arg_start, "widget"))
295     widget_num++;
296   
297   /* Convert signal name to use underscores rather than dashes '-'. */
298   strncpy (signal_name, query_info->signal_name, 127);
299   signal_name[127] = '\\0';
300   for (i = 0; signal_name[i]; i++)
301     {
302       if (signal_name[i] == '-')
303         signal_name[i] = '_';
304     }
306   /* Output the signal parameters. */
307   arg_names = lookup_signal_arg_names (object_name, signal_name);
309   for (param = 0; param < query_info->nparams; param++)
310     {
311       if (arg_names)
312         {
313           sprintf (pos, "%s\\n", arg_names[param]);
314           pos += strlen (pos);
315         }
316       else
317         {
318           type_name = get_type_name (query_info->params[param], &is_pointer);
320           /* Most arguments to the callback are called "arg1", "arg2", etc.
321              GdkWidgets are called "widget", "widget2", ...
322              GdkEvents are called "event", "event2", ...
323              GtkCallbacks are called "callback", "callback2", ... */
324           if (!strcmp (type_name, "GtkWidget"))
325             {
326               arg_name = "widget";
327               arg_num = &widget_num;
328             }
329           else if (!strcmp (type_name, "GdkEvent"))
330             {
331               type_name = get_gdk_event (signal_name);
332               arg_name = "event";
333               arg_num = &event_num;
334               is_pointer = TRUE;
335             }
336           else if (!strcmp (type_name, "GtkCallback")
337                    || !strcmp (type_name, "GtkCCallback"))
338             {
339               arg_name = "callback";
340               arg_num = &callback_num;
341             }
342           else
343             {
344               arg_name = "arg";
345               arg_num = &param_num;
346             }
347           sprintf (pos, "%s ", type_name);
348           pos += strlen (pos);
350           if (!arg_num || *arg_num == 0)
351             sprintf (pos, "%s%s\\n", is_pointer ? "*" : " ", arg_name);
352           else
353             sprintf (pos, "%s%s%i\\n", is_pointer ? "*" : " ", arg_name,
354                      *arg_num);
355               pos += strlen (pos);
356               
357               if (arg_num)
358                 *arg_num += 1;
359         }
360     }
362   /* Output the return type and function name. */
363   ret_type = get_type_name (query_info->return_val, &is_pointer);
365   fprintf (fp,
366            "<SIGNAL>\\n<NAME>%s::%s</NAME>\\n<RETURNS>%s%s</RETURNS>\\n%s</SIGNAL>\\n\\n",
367            object_name, query_info->signal_name, ret_type, is_pointer ? "*" : "", buffer);
368   g_free (query_info);
372 /* Returns the type name to use for a signal argument or return value, given
373    the GtkType from the signal info. It also sets is_pointer to TRUE if the
374    argument needs a '*' since it is a pointer. */
375 static gchar *
376 get_type_name (GtkType type, gboolean * is_pointer)
378   gchar *type_name;
380   *is_pointer = FALSE;
381   type_name = gtk_type_name (type);
383   switch (type) {
384   case GTK_TYPE_NONE:
385   case GTK_TYPE_CHAR:
386   case GTK_TYPE_UCHAR:
387   case GTK_TYPE_BOOL:
388   case GTK_TYPE_INT:
389   case GTK_TYPE_UINT:
390   case GTK_TYPE_LONG:
391   case GTK_TYPE_ULONG:
392   case GTK_TYPE_FLOAT:
393   case GTK_TYPE_DOUBLE:
394   case GTK_TYPE_POINTER:
395     /* These all have normal C type names so they are OK. */
396     return type_name;
398   case GTK_TYPE_STRING:
399     /* A GtkString is really a gchar*. */
400     *is_pointer = TRUE;
401     return "gchar";
403   case GTK_TYPE_ENUM:
404   case GTK_TYPE_FLAGS:
405     /* We use a gint for both of these. Hopefully a subtype with a decent
406        name will be registered and used instead, as GTK+ does itself. */
407     return "gint";
409   case GTK_TYPE_BOXED:
410     /* A boxed value is just an opaque pointer, I think. */
411     return "gpointer";
413   case GTK_TYPE_SIGNAL:
414   case GTK_TYPE_ARGS:
415   case GTK_TYPE_FOREIGN:
416   case GTK_TYPE_CALLBACK:
417   case GTK_TYPE_C_CALLBACK:
418     /* FIXME: These are wrong. I think they expand into more than 1 argument.
419        See the GtkArg struct in gtktypeutils.h and gtkargcollector.c.
420        Fortunately I doubt anything uses these as signal args. */
421     return "gpointer";
423   default:
424     break;
425   }
427   /* For all GtkObject subclasses we can use the class name with a "*",
428      e.g. 'GtkWidget *'. */
429   if (gtk_type_is_a (type, GTK_TYPE_OBJECT))
430     *is_pointer = TRUE;
432   return type_name;
436 static gchar *
437 get_gdk_event (const gchar * signal_name)
439   static gchar *GbGDKEvents[] =
440   {
441     "button_press_event", "GdkEventButton",
442     "button_release_event", "GdkEventButton",
443     "motion_notify_event", "GdkEventMotion",
444     "delete_event", "GdkEvent",
445     "destroy_event", "GdkEvent",
446     "expose_event", "GdkEventExpose",
447     "key_press_event", "GdkEventKey",
448     "key_release_event", "GdkEventKey",
449     "enter_notify_event", "GdkEventCrossing",
450     "leave_notify_event", "GdkEventCrossing",
451     "configure_event", "GdkEventConfigure",
452     "focus_in_event", "GdkEventFocus",
453     "focus_out_event", "GdkEventFocus",
454     "map_event", "GdkEvent",
455     "unmap_event", "GdkEvent",
456     "property_notify_event", "GdkEventProperty",
457     "selection_clear_event", "GdkEventSelection",
458     "selection_request_event", "GdkEventSelection",
459     "selection_notify_event", "GdkEventSelection",
460     "proximity_in_event", "GdkEventProximity",
461     "proximity_out_event", "GdkEventProximity",
462     "drag_begin_event", "GdkEventDragBegin",
463     "drag_request_event", "GdkEventDragRequest",
464     "drag_end_event", "GdkEventDragRequest",
465     "drop_enter_event", "GdkEventDropEnter",
466     "drop_leave_event", "GdkEventDropLeave",
467     "drop_data_available_event", "GdkEventDropDataAvailable",
468     "other_event", "GdkEventOther",
469     "client_event", "GdkEventClient",
470     "no_expose_event", "GdkEventNoExpose",
471     "visibility_notify_event", "GdkEventVisibility",
472     "window_state_event", "GdkEventWindowState",
473     "scroll_event", "GdkEventScroll",
474     NULL
475   };
477   gint i;
479   for (i = 0; GbGDKEvents[i]; i += 2)
480     {
481       if (!strcmp (signal_name, GbGDKEvents[i]))
482         return GbGDKEvents[i + 1];
483     }
484   return "GdkEvent";
488 /* This returns argument names to use for some known GTK signals.
489     It is passed a widget name, e.g. 'GtkCList' and a signal name, e.g.
490     'select_row' and it returns a pointer to an array of argument types and
491     names. */
492 static gchar **
493 lookup_signal_arg_names (gchar * type, const gchar * signal_name)
495   /* Each arg array starts with the object type name and the signal name,
496      and then signal arguments follow. */
497   static gchar *GbArgTable[][16] =
498   {
499     {"GtkCList", "select_row",
500      "gint             row",
501      "gint             column",
502      "GdkEventButton  *event"},
503     {"GtkCList", "unselect_row",
504      "gint             row",
505      "gint             column",
506      "GdkEventButton  *event"},
507     {"GtkCList", "click_column",
508      "gint             column"},
510     {"GtkCList", "resize_column",
511      "gint             column",
512      "gint             width"},
514     {"GtkCList", "extend_selection",
515      "GtkScrollType    scroll_type",
516      "gfloat           position",
517      "gboolean         auto_start_selection"},
518     {"GtkCList", "scroll_vertical",
519      "GtkScrollType    scroll_type",
520      "gfloat           position"},
521     {"GtkCList", "scroll_horizontal",
522      "GtkScrollType    scroll_type",
523      "gfloat           position"},
524     {"GtkContainer", "focus",
525      "GtkDirectionType direction"},
526     {"GtkCTree", "tree_select_row",
527      "GList           *node",
528      "gint             column"},
529     {"GtkCTree", "tree_unselect_row",
530      "GList           *node",
531      "gint             column"},
533     {"GtkCTree", "tree_expand",
534      "GList           *node"},
535     {"GtkCTree", "tree_collapse",
536      "GList           *node"},
537     {"GtkCTree", "tree_move",
538      "GList           *node",
539      "GList           *new_parent",
540      "GList           *new_sibling"},
541     {"GtkCTree", "change_focus_row_expansion",
542      "GtkCTreeExpansionType expansion"},
544     {"GtkEditable", "insert_text",
545      "gchar           *new_text",
546      "gint             new_text_length",
547      "gint            *position"},
548     {"GtkEditable", "delete_text",
549      "gint             start_pos",
550      "gint             end_pos"},
551     {"GtkEditable", "set_editable",
552      "gboolean         is_editable"},
553     {"GtkEditable", "move_cursor",
554      "gint             x",
555      "gint             y"},
556     {"GtkEditable", "move_word",
557      "gint             num_words"},
558     {"GtkEditable", "move_page",
559      "gint             x",
560      "gint             y"},
561     {"GtkEditable", "move_to_row",
562      "gint             row"},
563     {"GtkEditable", "move_to_column",
564      "gint             column"},
566     {"GtkEditable", "kill_char",
567      "gint             direction"},
568     {"GtkEditable", "kill_word",
569      "gint             direction"},
570     {"GtkEditable", "kill_line",
571      "gint             direction"},
574     {"GtkInputDialog", "enable_device",
575      "gint             deviceid"},
576     {"GtkInputDialog", "disable_device",
577      "gint             deviceid"},
579     {"GtkListItem", "extend_selection",
580      "GtkScrollType    scroll_type",
581      "gfloat           position",
582      "gboolean         auto_start_selection"},
583     {"GtkListItem", "scroll_vertical",
584      "GtkScrollType    scroll_type",
585      "gfloat           position"},
586     {"GtkListItem", "scroll_horizontal",
587      "GtkScrollType    scroll_type",
588      "gfloat           position"},
590     {"GtkMenuShell", "move_current",
591      "GtkMenuDirectionType direction"},
592     {"GtkMenuShell", "activate_current",
593      "gboolean         force_hide"},
596     {"GtkNotebook", "switch_page",
597      "GtkNotebookPage *page",
598      "gint             page_num"},
599     {"GtkStatusbar", "text_pushed",
600      "guint            context_id",
601      "gchar           *text"},
602     {"GtkStatusbar", "text_popped",
603      "guint            context_id",
604      "gchar           *text"},
605     {"GtkTipsQuery", "widget_entered",
606      "GtkWidget       *widget",
607      "gchar           *tip_text",
608      "gchar           *tip_private"},
609     {"GtkTipsQuery", "widget_selected",
610      "GtkWidget       *widget",
611      "gchar           *tip_text",
612      "gchar           *tip_private",
613      "GdkEventButton  *event"},
614     {"GtkToolbar", "orientation_changed",
615      "GtkOrientation   orientation"},
616     {"GtkToolbar", "style_changed",
617      "GtkToolbarStyle  style"},
618     {"GtkWidget", "draw",
619      "GdkRectangle    *area"},
620     {"GtkWidget", "size_request",
621      "GtkRequisition  *requisition"},
622     {"GtkWidget", "size_allocate",
623      "GtkAllocation   *allocation"},
624     {"GtkWidget", "state_changed",
625      "GtkStateType     state"},
626     {"GtkWidget", "style_set",
627      "GtkStyle        *previous_style"},
629     {"GtkWidget", "install_accelerator",
630      "gchar           *signal_name",
631      "gchar            key",
632      "gint             modifiers"},
634     {"GtkWidget", "add_accelerator",
635      "guint            accel_signal_id",
636      "GtkAccelGroup   *accel_group",
637      "guint            accel_key",
638      "GdkModifierType  accel_mods",
639      "GtkAccelFlags    accel_flags"},
641     {"GtkWidget", "parent_set",
642      "GtkObject       *old_parent"},
644     {"GtkWidget", "remove_accelerator",
645      "GtkAccelGroup   *accel_group",
646      "guint            accel_key",
647      "GdkModifierType  accel_mods"},
648     {"GtkWidget", "debug_msg",
649      "gchar           *message"},
650     {"GtkWindow", "move_resize",
651      "gint            *x",
652      "gint            *y",
653      "gint             width",
654      "gint             height"},
655     {"GtkWindow", "set_focus",
656      "GtkWidget       *widget"},
658     {"GtkWidget", "selection_get",
659      "GtkSelectionData *data",
660      "guint            info",
661      "guint            time"},
662     {"GtkWidget", "selection_received",
663      "GtkSelectionData *data",
664      "guint            time"},
666     {"GtkWidget", "drag_begin",
667      "GdkDragContext  *drag_context"},
668     {"GtkWidget", "drag_end",
669      "GdkDragContext  *drag_context"},
670     {"GtkWidget", "drag_data_delete",
671      "GdkDragContext  *drag_context"},
672     {"GtkWidget", "drag_leave",
673      "GdkDragContext  *drag_context",
674      "guint            time"},
675     {"GtkWidget", "drag_motion",
676      "GdkDragContext  *drag_context",
677      "gint             x",
678      "gint             y",
679      "guint            time"},
680     {"GtkWidget", "drag_drop",
681      "GdkDragContext  *drag_context",
682      "gint             x",
683      "gint             y",
684      "guint            time"},
685     {"GtkWidget", "drag_data_get",
686      "GdkDragContext  *drag_context",
687      "GtkSelectionData *data",
688      "guint            info",
689      "guint            time"},
690     {"GtkWidget", "drag_data_received",
691      "GdkDragContext  *drag_context",
692      "gint             x",
693      "gint             y",
694      "GtkSelectionData *data",
695      "guint            info",
696      "guint            time"},
698     {NULL}
699   };
701   gint i;
703   for (i = 0; GbArgTable[i][0]; i++)
704     {
705       if (!strcmp (type, GbArgTable[i][0])
706           && !strcmp (signal_name, GbArgTable[i][1]))
707         return &GbArgTable[i][2];
708     }
709   return NULL;
713 /* This outputs the hierarchy of all widgets which have been initialized,
714    i.e. by calling their XXX_get_type() initialization function. */
715 static void
716 output_widget_hierarchy (void)
718   FILE *fp;
720   fp = fopen (hierarchy_filename, "w");
721   if (fp == NULL)
722     {
723       g_warning ("Couldn't open output file: %s : %s", hierarchy_filename, g_strerror(errno));
724       return;
725     }
726   output_hierarchy (fp, GTK_TYPE_OBJECT, 0);
727   fclose (fp);
731 /* This is called recursively to output the hierarchy of a widget. */
732 static void
733 output_hierarchy (FILE *fp,
734                   GtkType type,
735                   guint level)
737   GList *list;
738   guint i;
740   if (!type)
741     return;
743   for (i = 0; i < level; i++)
744     fprintf (fp, "  ");
745   fprintf (fp, "%s\\n", gtk_type_name (type));
747   list = gtk_type_children_types (type);
749   while (list)
750     {
751       GtkType child = (GtkType) list->data;
752       output_hierarchy (fp, child, level + 1);
753       list = list->next;
754     }
758 static void
759 output_args (void)
761   FILE *fp;
762   gint i;
764   fp = fopen (args_filename, "w");
765   if (fp == NULL)
766     {
767       g_warning ("Couldn't open output file: %s : %s", args_filename, g_strerror(errno));
768       return;
769     }
771   for (i = 0; object_types[i]; i++)
772     output_widget_args (fp, object_types[i]);
774   fclose (fp);
778 static void
779 output_widget_args (FILE *fp, GtkType object_type)
781   GtkObjectClass *class;
782   gchar *object_class_name;
783   GtkArg *args;
784   guint32 *arg_flags;
785   guint n_args;
786   guint arg;
787   gchar flags[16], *pos;
789   class = gtk_type_class (object_type);
790   if (!class)
791     return;
793   object_class_name = gtk_type_name (object_type);
795   args = gtk_object_query_args (class->type, &arg_flags, &n_args);
797   for (arg = 0; arg < n_args; arg++)
798     {
799       pos = flags;
800       /* We use one-character flags for simplicity. */
801       if (arg_flags[arg] & GTK_ARG_READABLE)
802         *pos++ = 'r';
803       if (arg_flags[arg] & GTK_ARG_WRITABLE)
804         *pos++ = 'w';
805       if (arg_flags[arg] & GTK_ARG_CONSTRUCT)
806         *pos++ = 'x';
807       if (arg_flags[arg] & GTK_ARG_CONSTRUCT_ONLY)
808         *pos++ = 'X';
809       if (arg_flags[arg] & GTK_ARG_CHILD_ARG)
810         *pos++ = 'c';
811       *pos = 0;
813       fprintf (fp, "<ARG>\\n<NAME>%s</NAME>\\n<TYPE>%s</TYPE>\\n<FLAGS>%s</FLAGS>\\n</ARG>\\n\\n",
814                args[arg].name, gtk_type_name (args[arg].type), flags);
815     }
817   g_free (args);
818   g_free (arg_flags);
822 close OUTPUT;
824 # Compile and run our file
826 $CC = $ENV{CC} ? $ENV{CC} : "gcc";
827 $LD = $ENV{LD} ? $ENV{LD} : $CC;
828 $CFLAGS = $ENV{CFLAGS} ? $ENV{CFLAGS} : "";
829 $LDFLAGS = $ENV{LDFLAGS} ? $ENV{LDFLAGS} : "";
830 $RUN = $ENV{RUN} ? $ENV{RUN} : "";
832 my $o_file;
833 if ($CC =~ /libtool/) {
834   $o_file  = "$MODULE-scan.lo"
835 } else {
836   $o_file = "$MODULE-scan.o"
839 print "gtk-doc: Compiling scanner\n";
840 $command = "$CC $CFLAGS -c -o $o_file $MODULE-scan.c";
841 system("($command)") == 0 or die "Compilation of scanner failed: $!\n";
843 print "gtk-doc: Linking scanner\n";
844 # FIXME: Can we turn off as-needed for the docs (or better fix it?)
845 #$command = "$LD -Wl,--no-as-needed $o_file $LDFLAGS -o $MODULE-scan";
846 $command = "$LD $o_file $LDFLAGS -o $MODULE-scan";
847 system("($command)") == 0 or die "Linking of scanner failed: $!\n";
849 print "gtk-doc: Running scanner $MODULE-scan\n";
850 system("($RUN ./$MODULE-scan)") == 0 or die "Scan failed: $!\n";
852 if (!defined($ENV{"GTK_DOC_KEEP_INTERMEDIATE"})) {
853   unlink "./$MODULE-scan.c", "./$MODULE-scan.o", "./$MODULE-scan.lo", "./$MODULE-scan";
856 &UpdateFileIfChanged ($old_signals_filename, $new_signals_filename, 0);
857 &UpdateFileIfChanged ($old_hierarchy_filename, $new_hierarchy_filename, 0);
858 &UpdateFileIfChanged ($old_args_filename, $new_args_filename, 0);