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.
30 push @INC, '@PACKAGE_DATA_DIR@';
31 require "gtkdoc-common.pl";
35 # name of documentation module
46 %optctl = (module => \$MODULE,
47 types => \$TYPES_FILE,
48 nogtkinit => \$NO_GTK_INIT,
49 'output-dir' => \$OUTPUT_DIR,
53 'ldflags' => \$LDFLAGS,
55 'version' => \$PRINT_VERSION,
56 'help' => \$PRINT_HELP);
58 GetOptions(\%optctl, "module=s", "types:s", "output-dir:s", "nogtkinit", "cc:s", "ld:s", "run:s", "cflags:s", "ldflags:s", "version", "help");
71 gtkdoc-scanobj version @VERSION@ - introspect gtk-objects
73 --module=MODULE_NAME Name of the doc module being parsed
74 --types=FILE The name of the file to store the types in
75 --output-dir=DIRNAME The directory where the results are stored
76 --cc=COMPILER The compiler to use
77 --ld=LINKER The linker to use
78 --run=RUN Command for running the scanner
79 --cflags=CFLAGS Compiler flags
80 --ldflags=LDFLAGS Linker flags
81 --version Print the version of this program
82 --help Print this help
87 $OUTPUT_DIR = $OUTPUT_DIR ? $OUTPUT_DIR : ".";
89 $TYPES_FILE = $TYPES_FILE ? $TYPES_FILE : "$OUTPUT_DIR/$MODULE.types";
91 open (TYPES, $TYPES_FILE) || die "Cannot open $TYPES_FILE: $!\n";
92 open (OUTPUT, ">$MODULE-scan.c") || die "Cannot open $MODULE-scan.c: $!\n";
94 my $old_signals_filename = "$OUTPUT_DIR/$MODULE.signals";
95 my $new_signals_filename = "$OUTPUT_DIR/$MODULE.signals.new";
96 my $old_hierarchy_filename = "$OUTPUT_DIR/$MODULE.hierarchy";
97 my $new_hierarchy_filename = "$OUTPUT_DIR/$MODULE.hierarchy.new";
98 my $old_args_filename = "$OUTPUT_DIR/$MODULE.args";
99 my $new_args_filename = "$OUTPUT_DIR/$MODULE.args.new";
101 # write a C program to scan the types
119 $ntypes = @types + 1;
128 GtkType object_types[$ntypes];
131 get_object_types (void)
137 print OUTPUT " object_types[i++] = $_ ();\n";
147 * This uses GTK type functions to output signal prototypes and the widget
151 /* The output files */
152 gchar *signals_filename = "$new_signals_filename";
153 gchar *hierarchy_filename = "$new_hierarchy_filename";
154 gchar *args_filename = "$new_args_filename";
157 static void output_signals (void);
158 static void output_widget_signals (FILE *fp,
159 GtkType object_type);
160 static void output_widget_signal (FILE *fp,
162 gchar *object_class_name,
164 static gchar * get_type_name (GtkType type,
165 gboolean * is_pointer);
166 static void output_widget_hierarchy (void);
167 static void output_hierarchy (FILE *fp,
171 static void output_args (void);
172 static void output_widget_args (FILE *fp, GtkType object_type);
175 main (int argc, char *argv[])
185 gtk_init (&argc, &argv);
193 output_widget_hierarchy ();
201 output_signals (void)
206 fp = fopen (signals_filename, "w");
209 g_warning ("Couldn't open output file: %s : %s", signals_filename, g_strerror(errno));
213 for (i = 0; object_types[i]; i++)
214 output_widget_signals (fp, object_types[i]);
220 /* This outputs all the signals of one widget. */
222 output_widget_signals (FILE *fp, GtkType object_type)
224 GtkObjectClass *class;
225 gchar *object_class_name;
228 class = gtk_type_class (object_type);
229 if (!class || class->nsignals == 0)
232 object_class_name = gtk_type_name (object_type);
234 for (sig = 0; sig < class->nsignals; sig++)
236 if (!class->signals[sig])
238 /*g_print ("Signal slot [%u] is empty\\n", sig);*/
242 output_widget_signal (fp, object_type, object_class_name,
243 class->signals[sig]);
248 /* This outputs one signal. */
250 output_widget_signal (FILE *fp,
255 GtkSignalQuery *query_info;
256 gchar *ret_type, *pos, *type_name, *arg_name, *object_arg, *object_arg_start;
260 gint param_num, widget_num, event_num, callback_num;
262 gchar signal_name[128];
264 /* g_print ("Object: %s Type: %i Signal: %u\\n", object_name, object_type,
268 widget_num = event_num = callback_num = 0;
270 query_info = gtk_signal_query (signal_id);
271 if (query_info == NULL)
273 g_warning ("Couldn't query signal");
277 /* Output the signal object type and the argument name. We assume the
278 type is a pointer - I think that is OK. We remove "Gtk" or "Gnome" and
279 convert to lower case for the argument name. */
281 sprintf (pos, "%s ", object_name);
284 /* Try to come up with a sensible variable name for the first arg
285 * I chops off 2 know prefixes :/ and makes the name lowercase
286 * It should replace lowercase -> uppercase with '_'
287 * see gtkdoc-scangobject.in for better algorithm
289 if (!strncmp (object_name, "Gtk", 3))
290 object_arg = object_name + 3;
291 else if (!strncmp (object_name, "Gnome", 5))
292 object_arg = object_name + 5;
294 object_arg = object_name;
296 object_arg_start = pos;
297 sprintf (pos, "*%s\\n", object_arg);
299 g_strdown (object_arg_start);
300 if (!strcmp (object_arg_start, "widget"))
303 /* Convert signal name to use underscores rather than dashes '-'. */
304 strncpy (signal_name, query_info->signal_name, 127);
305 signal_name[127] = '\\0';
306 for (i = 0; signal_name[i]; i++)
308 if (signal_name[i] == '-')
309 signal_name[i] = '_';
312 /* Output the signal parameters. */
313 for (param = 0; param < query_info->nparams; param++)
315 type_name = get_type_name (query_info->params[param], &is_pointer);
317 /* Most arguments to the callback are called "arg1", "arg2", etc.
318 GtkWidgets are called "widget", "widget2", ...
319 GtkCallbacks are called "callback", "callback2", ... */
320 if (!strcmp (type_name, "GtkWidget"))
323 arg_num = &widget_num;
325 else if (!strcmp (type_name, "GtkCallback")
326 || !strcmp (type_name, "GtkCCallback"))
328 arg_name = "callback";
329 arg_num = &callback_num;
334 arg_num = ¶m_num;
336 sprintf (pos, "%s ", type_name);
339 if (!arg_num || *arg_num == 0)
340 sprintf (pos, "%s%s\\n", is_pointer ? "*" : " ", arg_name);
342 sprintf (pos, "%s%s%i\\n", is_pointer ? "*" : " ", arg_name,
350 /* Output the return type and function name. */
351 ret_type = get_type_name (query_info->return_val, &is_pointer);
354 "<SIGNAL>\\n<NAME>%s::%s</NAME>\\n<RETURNS>%s%s</RETURNS>\\n%s</SIGNAL>\\n\\n",
355 object_name, query_info->signal_name, ret_type, is_pointer ? "*" : "", buffer);
360 /* Returns the type name to use for a signal argument or return value, given
361 the GtkType from the signal info. It also sets is_pointer to TRUE if the
362 argument needs a '*' since it is a pointer. */
364 get_type_name (GtkType type, gboolean * is_pointer)
369 type_name = gtk_type_name (type);
381 case GTK_TYPE_DOUBLE:
382 case GTK_TYPE_POINTER:
383 /* These all have normal C type names so they are OK. */
386 case GTK_TYPE_STRING:
387 /* A GtkString is really a gchar*. */
393 /* We use a gint for both of these. Hopefully a subtype with a decent
394 name will be registered and used instead, as GTK+ does itself. */
398 /* A boxed value is just an opaque pointer, I think. */
401 case GTK_TYPE_SIGNAL:
403 case GTK_TYPE_FOREIGN:
404 case GTK_TYPE_CALLBACK:
405 case GTK_TYPE_C_CALLBACK:
406 /* FIXME: These are wrong. I think they expand into more than 1 argument.
407 See the GtkArg struct in gtktypeutils.h and gtkargcollector.c.
408 Fortunately I doubt anything uses these as signal args. */
415 /* For all GtkObject subclasses we can use the class name with a "*",
416 e.g. 'GtkWidget *'. */
417 if (gtk_type_is_a (type, GTK_TYPE_OBJECT))
424 /* This outputs the hierarchy of all widgets which have been initialized,
425 i.e. by calling their XXX_get_type() initialization function. */
427 output_widget_hierarchy (void)
431 fp = fopen (hierarchy_filename, "w");
434 g_warning ("Couldn't open output file: %s : %s", hierarchy_filename, g_strerror(errno));
437 output_hierarchy (fp, GTK_TYPE_OBJECT, 0);
442 /* This is called recursively to output the hierarchy of a widget. */
444 output_hierarchy (FILE *fp,
454 for (i = 0; i < level; i++)
456 fprintf (fp, "%s\\n", gtk_type_name (type));
458 list = gtk_type_children_types (type);
462 GtkType child = (GtkType) list->data;
463 output_hierarchy (fp, child, level + 1);
475 fp = fopen (args_filename, "w");
478 g_warning ("Couldn't open output file: %s : %s", args_filename, g_strerror(errno));
482 for (i = 0; object_types[i]; i++)
483 output_widget_args (fp, object_types[i]);
490 output_widget_args (FILE *fp, GtkType object_type)
492 GtkObjectClass *class;
493 gchar *object_class_name;
498 gchar flags[16], *pos;
500 class = gtk_type_class (object_type);
504 object_class_name = gtk_type_name (object_type);
506 args = gtk_object_query_args (class->type, &arg_flags, &n_args);
508 for (arg = 0; arg < n_args; arg++)
511 /* We use one-character flags for simplicity. */
512 if (arg_flags[arg] & GTK_ARG_READABLE)
514 if (arg_flags[arg] & GTK_ARG_WRITABLE)
516 if (arg_flags[arg] & GTK_ARG_CONSTRUCT)
518 if (arg_flags[arg] & GTK_ARG_CONSTRUCT_ONLY)
520 if (arg_flags[arg] & GTK_ARG_CHILD_ARG)
524 fprintf (fp, "<ARG>\\n<NAME>%s</NAME>\\n<TYPE>%s</TYPE>\\n<FLAGS>%s</FLAGS>\\n</ARG>\\n\\n",
525 args[arg].name, gtk_type_name (args[arg].type), flags);
535 # Compile and run our file
538 $CC = $ENV{CC} ? $ENV{CC} : "gcc";
541 $LD = $ENV{LD} ? $ENV{LD} : $CC;
544 $CFLAGS = $ENV{CFLAGS} ? $ENV{CFLAGS} : "";
547 $LDFLAGS = $ENV{LDFLAGS} ? $ENV{LDFLAGS} : "";
550 $RUN = $ENV{RUN} ? $ENV{RUN} : "";
554 if ($CC =~ /libtool/) {
555 $o_file = "$MODULE-scan.lo"
557 $o_file = "$MODULE-scan.o"
561 $command = "$CC $CFLAGS -c -o $o_file $MODULE-scan.c";
562 system("($command)") == 0 or die "Compilation of scanner failed: $!\n";
565 # FIXME: Can we turn off as-needed for the docs (or better fix it?)
566 #$command = "$LD -Wl,--no-as-needed $o_file $LDFLAGS -o $MODULE-scan";
567 $command = "$LD $o_file $LDFLAGS -o $MODULE-scan";
568 system("($command)") == 0 or die "Linking of scanner failed: $!\n";
570 # Running scanner $MODULE-scan ";
571 system("($RUN ./$MODULE-scan)") == 0 or die "Scan failed: $!\n";
573 if (!defined($ENV{"GTK_DOC_KEEP_INTERMEDIATE"})) {
574 unlink "./$MODULE-scan.c", "./$MODULE-scan.o", "./$MODULE-scan.lo", "./$MODULE-scan";
577 &UpdateFileIfChanged ($old_signals_filename, $new_signals_filename, 0);
578 &UpdateFileIfChanged ($old_hierarchy_filename, $new_hierarchy_filename, 0);
579 &UpdateFileIfChanged ($old_args_filename, $new_args_filename, 0);