release: update news and date in manual
[gtk-doc.git] / gtkdoc-scangobj.in
blob0c10d0cf8f2b7f237e4f53ef93707fc20d34fa60
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 hierarchies and signals
24 # by compiling a small C program. CFLAGS and LDFLAGS must be
25 # set appropriately before running this script.
28 use Getopt::Long;
30 push @INC, '@PACKAGE_DATA_DIR@';
31 require "gtkdoc-common.pl";
33 # Options
35 # name of documentation module
36 my $MODULE;
37 my $OUTPUT_DIR;
38 my $PRINT_VERSION;
39 my $PRINT_HELP;
40 my $TYPE_INIT_FUNC="g_type_init(); g_type_class_ref(G_TYPE_OBJECT)";
41 my $QUERY_CHILD_PROPERTIES;
43 # --nogtkinit is deprecated, as it is the default now anyway.
44 %optctl = (module => \$MODULE,
45            types => \$TYPES_FILE,
46            nogtkinit => \$NO_GTK_INIT,
47            'type-init-func' => \$TYPE_INIT_FUNC,
48            'query-child-properties' => \$QUERY_CHILD_PROPERTIES,
49            'output-dir' => \$OUTPUT_DIR,
50            'version' => \$PRINT_VERSION,
51            'help' => \$PRINT_HELP);
53 GetOptions(\%optctl, "module=s", "types:s", "output-dir:s", "nogtkinit", "type-init-func:s", "query-child-properties:s", "version", "help");
55 if ($NO_GTK_INIT) {
56   # Do nothing. This just avoids a warning.
57   # the option is not used anymore
60 if ($PRINT_VERSION) {
61     print "@VERSION@\n";
62     exit 0;
65 if (!$MODULE) {
66     $PRINT_HELP = 1;
69 if ($PRINT_HELP) {
70     print <<EOF;
71 gtkdoc-scangobj version @VERSION@ - introspect g-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 --type-init-func=FUNC         The init function to call instead of g_type_init()
76 --query-child-properties=FUNC A function that returns a list of child
77                               properties for a class
78 --output-dir=DIRNAME          The directory where the results are stored
79 --version                     Print the version of this program
80 --help                        Print this help
81 EOF
82     exit 0;
85 $OUTPUT_DIR = $OUTPUT_DIR ? $OUTPUT_DIR : ".";
87 $TYPES_FILE = $TYPES_FILE ? $TYPES_FILE : "$OUTPUT_DIR/$MODULE.types";
89 open (TYPES, $TYPES_FILE) || die "Cannot open $TYPES_FILE: $!\n";
90 open (OUTPUT, ">$MODULE-scan.c") || die "Cannot open $MODULE-scan.c: $!\n";
92 my $old_signals_filename = "$OUTPUT_DIR/$MODULE.signals";
93 my $new_signals_filename = "$OUTPUT_DIR/$MODULE.signals.new";
94 my $old_hierarchy_filename = "$OUTPUT_DIR/$MODULE.hierarchy";
95 my $new_hierarchy_filename = "$OUTPUT_DIR/$MODULE.hierarchy.new";
96 my $old_interfaces_filename = "$OUTPUT_DIR/$MODULE.interfaces";
97 my $new_interfaces_filename = "$OUTPUT_DIR/$MODULE.interfaces.new";
98 my $old_prerequisites_filename = "$OUTPUT_DIR/$MODULE.prerequisites";
99 my $new_prerequisites_filename = "$OUTPUT_DIR/$MODULE.prerequisites.new";
100 my $old_args_filename = "$OUTPUT_DIR/$MODULE.args";
101 my $new_args_filename = "$OUTPUT_DIR/$MODULE.args.new";
103 # write a C program to scan the types
105 $includes = "";
106 @types = ();
108 for (<TYPES>) {
109     if (/^#include/) {
110         $includes .= $_;
111     } elsif (/^gnome_keyring_item_info_get_type$/) {
112         # HACK: This isn't really a GObject type so skip it.
113         next;
114     } elsif (/^%/) {
115         next;
116     } elsif (/^\s*$/) {
117         next;
118     } else {
119         chomp;
120         push @types, $_;
121     }
124 $ntypes = @types + 1;
126 print OUTPUT <<EOT;
127 #include <string.h>
128 #include <stdlib.h>
129 #include <stdio.h>
130 #include <errno.h>
131 #include <glib-object.h>
135 if ($includes) {
136     print OUTPUT $includes;
137 } else {
138     for (@types) {
139         print OUTPUT "extern GType $_ (void);\n";
140     }
143 if ($QUERY_CHILD_PROPERTIES) {
144   print OUTPUT <<EOT;
145 extern GParamSpec** $QUERY_CHILD_PROPERTIES (gpointer class, guint *n_properties);
149 print OUTPUT <<EOT;
151 #ifdef GTK_IS_WIDGET_CLASS
152 #include <gtk/gtk.h>
153 #endif
154 GType object_types[$ntypes];
156 static GType *
157 get_object_types (void)
159     gpointer g_object_class;
160     gint i = 0;
163 for (@types) {
164     print OUTPUT "    object_types[i++] = $_ ();\n";
167 print OUTPUT <<EOT;
168     object_types[i] = 0;
170     /* reference the GObjectClass to initialize the param spec pool
171      * potentially needed by interfaces. See http://bugs.gnome.org/571820 */
172     g_object_class = g_type_class_ref (G_TYPE_OBJECT);
174     /* Need to make sure all the types are loaded in and initialize
175      * their signals and properties.
176      */
177     for (i=0; object_types[i]; i++)
178       {
179         if (G_TYPE_IS_CLASSED (object_types[i]))
180           g_type_class_ref (object_types[i]);
181         if (G_TYPE_IS_INTERFACE (object_types[i]))
182           g_type_default_interface_ref (object_types[i]);
183       }
185     g_type_class_unref (g_object_class);
187     return object_types;
191  * This uses GObject type functions to output signal prototypes and the object
192  * hierarchy.
193  */
195 /* The output files */
196 const gchar *signals_filename = "$new_signals_filename";
197 const gchar *hierarchy_filename = "$new_hierarchy_filename";
198 const gchar *interfaces_filename = "$new_interfaces_filename";
199 const gchar *prerequisites_filename = "$new_prerequisites_filename";
200 const gchar *args_filename = "$new_args_filename";
203 static void output_signals (void);
204 static void output_object_signals (FILE *fp,
205                                    GType object_type);
206 static void output_object_signal (FILE *fp,
207                                   const gchar *object_class_name,
208                                   guint signal_id);
209 static const gchar * get_type_name (GType type,
210                                     gboolean * is_pointer);
211 static void output_object_hierarchy (void);
212 static void output_hierarchy (FILE *fp,
213                               GType type,
214                               guint level);
216 static void output_object_interfaces (void);
217 static void output_interfaces (FILE *fp,
218                                GType type);
220 static void output_interface_prerequisites (void);
221 static void output_prerequisites (FILE *fp,
222                                   GType type);
224 static void output_args (void);
225 static void output_object_args (FILE *fp, GType object_type);
228 main (int argc, char *argv[])
230   $TYPE_INIT_FUNC;
232   get_object_types ();
234   output_signals ();
235   output_object_hierarchy ();
236   output_object_interfaces ();
237   output_interface_prerequisites ();
238   output_args ();
240   return 0;
244 static void
245 output_signals (void)
247   FILE *fp;
248   gint i;
250   fp = fopen (signals_filename, "w");
251   if (fp == NULL)
252     {
253       g_warning ("Couldn't open output file: %s : %s", signals_filename, g_strerror(errno));
254       return;
255     }
257   for (i = 0; object_types[i]; i++)
258     output_object_signals (fp, object_types[i]);
260   fclose (fp);
263 static gint
264 compare_signals (const void *a, const void *b)
266   const guint *signal_a = a;
267   const guint *signal_b = b;
269   return strcmp (g_signal_name (*signal_a), g_signal_name (*signal_b));
272 /* This outputs all the signals of one object. */
273 static void
274 output_object_signals (FILE *fp, GType object_type)
276   const gchar *object_class_name;
277   guint *signals, n_signals;
278   guint sig;
280   if (G_TYPE_IS_INSTANTIATABLE (object_type) ||
281       G_TYPE_IS_INTERFACE (object_type))
282     {
284       object_class_name = g_type_name (object_type);
286       signals = g_signal_list_ids (object_type, &n_signals);
287       qsort (signals, n_signals, sizeof (guint), compare_signals);
289       for (sig = 0; sig < n_signals; sig++)
290         {
291            output_object_signal (fp, object_class_name, signals[sig]);
292         }
293       g_free (signals);
294    }
298 /* This outputs one signal. */
299 static void
300 output_object_signal (FILE *fp,
301                       const gchar *object_name,
302                       guint signal_id)
304   GSignalQuery query_info;
305   const gchar *type_name, *ret_type, *object_arg, *arg_name;
306   gchar *pos, *object_arg_lower;
307   gboolean is_pointer;
308   gchar buffer[1024];
309   guint i, param;
310   gint param_num, widget_num, event_num, callback_num;
311   gint *arg_num;
312   gchar signal_name[128];
313   gchar flags[16];
315   /*  g_print ("Object: %s Signal: %u\\n", object_name, signal_id);*/
317   param_num = 1;
318   widget_num = event_num = callback_num = 0;
320   g_signal_query (signal_id, &query_info);
322   /* Output the signal object type and the argument name. We assume the
323      type is a pointer - I think that is OK. We remove "Gtk" or "Gnome" and
324      convert to lower case for the argument name. */
325   pos = buffer;
326   sprintf (pos, "%s ", object_name);
327   pos += strlen (pos);
329   /* Try to come up with a sensible variable name for the first arg
330    * It chops off 2 know prefixes :/ and makes the name lowercase
331    * It should replace lowercase -> uppercase with '_'
332    * GFileMonitor -> file_monitor
333    * GIOExtensionPoint -> extension_point
334    * GtkTreeView -> tree_view
335    * if 2nd char is upper case too
336    *   search for first lower case and go back one char
337    * else
338    *   search for next upper case
339    */
340   if (!strncmp (object_name, "Gtk", 3))
341       object_arg = object_name + 3;
342   else if (!strncmp (object_name, "Gnome", 5))
343       object_arg = object_name + 5;
344   else
345       object_arg = object_name;
347   object_arg_lower = g_ascii_strdown (object_arg, -1);
348   sprintf (pos, "*%s\\n", object_arg_lower);
349   pos += strlen (pos);
350   if (!strncmp (object_arg_lower, "widget", 6))
351     widget_num = 2;
352   g_free(object_arg_lower);
354   /* Convert signal name to use underscores rather than dashes '-'. */
355   strncpy (signal_name, query_info.signal_name, 127);
356   signal_name[127] = '\\0';
357   for (i = 0; signal_name[i]; i++)
358     {
359       if (signal_name[i] == '-')
360         signal_name[i] = '_';
361     }
363   /* Output the signal parameters. */
364   for (param = 0; param < query_info.n_params; param++)
365     {
366       type_name = get_type_name (query_info.param_types[param] & ~G_SIGNAL_TYPE_STATIC_SCOPE, &is_pointer);
368       /* Most arguments to the callback are called "arg1", "arg2", etc.
369          GtkWidgets are called "widget", "widget2", ...
370          GtkCallbacks are called "callback", "callback2", ... */
371       if (!strcmp (type_name, "GtkWidget"))
372         {
373           arg_name = "widget";
374           arg_num = &widget_num;
375         }
376       else if (!strcmp (type_name, "GtkCallback")
377                || !strcmp (type_name, "GtkCCallback"))
378         {
379           arg_name = "callback";
380           arg_num = &callback_num;
381         }
382       else
383         {
384           arg_name = "arg";
385           arg_num = &param_num;
386         }
387       sprintf (pos, "%s ", type_name);
388       pos += strlen (pos);
390       if (!arg_num || *arg_num == 0)
391         sprintf (pos, "%s%s\\n", is_pointer ? "*" : " ", arg_name);
392       else
393         sprintf (pos, "%s%s%i\\n", is_pointer ? "*" : " ", arg_name,
394                  *arg_num);
395       pos += strlen (pos);
397       if (arg_num)
398         {
399           if (*arg_num == 0)
400             *arg_num = 2;
401           else
402             *arg_num += 1;
403         }
404     }
406   pos = flags;
407   /* We use one-character flags for simplicity. */
408   if (query_info.signal_flags & G_SIGNAL_RUN_FIRST)
409     *pos++ = 'f';
410   if (query_info.signal_flags & G_SIGNAL_RUN_LAST)
411     *pos++ = 'l';
412   if (query_info.signal_flags & G_SIGNAL_RUN_CLEANUP)
413     *pos++ = 'c';
414   if (query_info.signal_flags & G_SIGNAL_NO_RECURSE)
415     *pos++ = 'r';
416   if (query_info.signal_flags & G_SIGNAL_DETAILED)
417     *pos++ = 'd';
418   if (query_info.signal_flags & G_SIGNAL_ACTION)
419     *pos++ = 'a';
420   if (query_info.signal_flags & G_SIGNAL_NO_HOOKS)
421     *pos++ = 'h';
422   *pos = 0;
424   /* Output the return type and function name. */
425   ret_type = get_type_name (query_info.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE, &is_pointer);
427   fprintf (fp,
428            "<SIGNAL>\\n<NAME>%s::%s</NAME>\\n<RETURNS>%s%s</RETURNS>\\n<FLAGS>%s</FLAGS>\\n%s</SIGNAL>\\n\\n",
429            object_name, query_info.signal_name, ret_type, is_pointer ? "*" : "", flags, buffer);
433 /* Returns the type name to use for a signal argument or return value, given
434    the GtkType from the signal info. It also sets is_pointer to TRUE if the
435    argument needs a '*' since it is a pointer. */
436 static const gchar *
437 get_type_name (GType type, gboolean * is_pointer)
439   const gchar *type_name;
441   *is_pointer = FALSE;
442   type_name = g_type_name (type);
444   switch (type) {
445   case G_TYPE_NONE:
446   case G_TYPE_CHAR:
447   case G_TYPE_UCHAR:
448   case G_TYPE_BOOLEAN:
449   case G_TYPE_INT:
450   case G_TYPE_UINT:
451   case G_TYPE_LONG:
452   case G_TYPE_ULONG:
453   case G_TYPE_FLOAT:
454   case G_TYPE_DOUBLE:
455   case G_TYPE_POINTER:
456     /* These all have normal C type names so they are OK. */
457     return type_name;
459   case G_TYPE_STRING:
460     /* A GtkString is really a gchar*. */
461     *is_pointer = TRUE;
462     return "gchar";
464   case G_TYPE_ENUM:
465   case G_TYPE_FLAGS:
466     /* We use a gint for both of these. Hopefully a subtype with a decent
467        name will be registered and used instead, as GTK+ does itself. */
468     return "gint";
470   case G_TYPE_BOXED:
471     /* The boxed type shouldn't be used itself, only subtypes. Though we
472        return 'gpointer' just in case. */
473     return "gpointer";
475   case G_TYPE_PARAM:
476     /* A GParam is really a GParamSpec*. */
477     *is_pointer = TRUE;
478     return "GParamSpec";
480 #if GLIB_CHECK_VERSION (2, 25, 9)
481   case G_TYPE_VARIANT:
482     *is_pointer = TRUE;
483     return "GVariant";
484 #endif
486 default:
487     break;
488   }
490   /* For all GObject subclasses we can use the class name with a "*",
491      e.g. 'GtkWidget *'. */
492   if (g_type_is_a (type, G_TYPE_OBJECT))
493     *is_pointer = TRUE;
495   /* Also catch non GObject root types */
496   if (G_TYPE_IS_CLASSED (type))
497     *is_pointer = TRUE;
499   /* All boxed subtypes will be pointers as well. */
500   /* Exception: GStrv */
501   if (g_type_is_a (type, G_TYPE_BOXED) &&
502       !g_type_is_a (type, G_TYPE_STRV))
503     *is_pointer = TRUE;
505   /* All pointer subtypes will be pointers as well. */
506   if (g_type_is_a (type, G_TYPE_POINTER))
507     *is_pointer = TRUE;
509   /* But enums are not */
510   if (g_type_is_a (type, G_TYPE_ENUM) ||
511       g_type_is_a (type, G_TYPE_FLAGS))
512     *is_pointer = FALSE;
514   return type_name;
518 /* This outputs the hierarchy of all objects which have been initialized,
519    i.e. by calling their XXX_get_type() initialization function. */
520 static void
521 output_object_hierarchy (void)
523   FILE *fp;
524   gint i,j;
525   GType root, type;
526   GType root_types[$ntypes] = { G_TYPE_INVALID, };
528   fp = fopen (hierarchy_filename, "w");
529   if (fp == NULL)
530     {
531       g_warning ("Couldn't open output file: %s : %s", hierarchy_filename, g_strerror(errno));
532       return;
533     }
534   output_hierarchy (fp, G_TYPE_OBJECT, 0);
535   output_hierarchy (fp, G_TYPE_INTERFACE, 0);
537   for (i=0; object_types[i]; i++) {
538     root = object_types[i];
539     while ((type = g_type_parent (root))) {
540       root = type;
541     }
542     if ((root != G_TYPE_OBJECT) && (root != G_TYPE_INTERFACE)) {
543       for (j=0; root_types[j]; j++) {
544         if (root == root_types[j]) {
545           root = G_TYPE_INVALID; break;
546         }
547       }
548       if(root) {
549         root_types[j] = root;
550         output_hierarchy (fp, root, 0);
551       }
552     }
553   }
555   fclose (fp);
558 /* This is called recursively to output the hierarchy of a object. */
559 static void
560 output_hierarchy (FILE  *fp,
561                   GType  type,
562                   guint   level)
564   guint i;
565   GType *children;
566   guint n_children;
568   if (!type)
569     return;
571   for (i = 0; i < level; i++)
572     fprintf (fp, "  ");
573   fprintf (fp, "%s\\n", g_type_name (type));
575   children = g_type_children (type, &n_children);
577   for (i=0; i < n_children; i++)
578     output_hierarchy (fp, children[i], level + 1);
580   g_free (children);
583 static void output_object_interfaces (void)
585   guint i;
586   FILE *fp;
588   fp = fopen (interfaces_filename, "w");
589   if (fp == NULL)
590     {
591       g_warning ("Couldn't open output file: %s : %s", interfaces_filename, g_strerror(errno));
592       return;
593     }
594   output_interfaces (fp, G_TYPE_OBJECT);
596   for (i = 0; object_types[i]; i++)
597     {
598       if (!g_type_parent (object_types[i]) &&
599           (object_types[i] != G_TYPE_OBJECT) &&
600           G_TYPE_IS_INSTANTIATABLE (object_types[i]))
601         {
602           output_interfaces (fp, object_types[i]);
603         }
604     }
605   fclose (fp);
608 static void
609 output_interfaces (FILE  *fp,
610                    GType  type)
612   guint i;
613   GType *children, *interfaces;
614   guint n_children, n_interfaces;
616   if (!type)
617     return;
619   interfaces = g_type_interfaces (type, &n_interfaces);
621   if (n_interfaces > 0)
622     {
623       fprintf (fp, "%s", g_type_name (type));
624       for (i=0; i < n_interfaces; i++)
625           fprintf (fp, " %s", g_type_name (interfaces[i]));
626       fprintf (fp, "\\n");
627      }
628   g_free (interfaces);
630   children = g_type_children (type, &n_children);
632   for (i=0; i < n_children; i++)
633     output_interfaces (fp, children[i]);
635   g_free (children);
638 static void output_interface_prerequisites (void)
640   FILE *fp;
642   fp = fopen (prerequisites_filename, "w");
643   if (fp == NULL)
644     {
645       g_warning ("Couldn't open output file: %s : %s", prerequisites_filename, g_strerror(errno));
646       return;
647     }
648   output_prerequisites (fp, G_TYPE_INTERFACE);
649   fclose (fp);
652 static void
653 output_prerequisites (FILE  *fp,
654                       GType  type)
656 #if GLIB_CHECK_VERSION(2,1,0)
657   guint i;
658   GType *children, *prerequisites;
659   guint n_children, n_prerequisites;
661   if (!type)
662     return;
664   prerequisites = g_type_interface_prerequisites (type, &n_prerequisites);
666   if (n_prerequisites > 0)
667     {
668       fprintf (fp, "%s", g_type_name (type));
669       for (i=0; i < n_prerequisites; i++)
670           fprintf (fp, " %s", g_type_name (prerequisites[i]));
671       fprintf (fp, "\\n");
672      }
673   g_free (prerequisites);
675   children = g_type_children (type, &n_children);
677   for (i=0; i < n_children; i++)
678     output_prerequisites (fp, children[i]);
680   g_free (children);
681 #endif
684 static void
685 output_args (void)
687   FILE *fp;
688   gint i;
690   fp = fopen (args_filename, "w");
691   if (fp == NULL)
692     {
693       g_warning ("Couldn't open output file: %s : %s", args_filename, g_strerror(errno));
694       return;
695     }
697   for (i = 0; object_types[i]; i++) {
698     output_object_args (fp, object_types[i]);
699   }
701   fclose (fp);
704 static gint
705 compare_param_specs (const void *a, const void *b)
707   GParamSpec *spec_a = *(GParamSpec **)a;
708   GParamSpec *spec_b = *(GParamSpec **)b;
710   return strcmp (g_param_spec_get_name (spec_a), g_param_spec_get_name (spec_b));
713 /* Its common to have unsigned properties restricted
714  * to the signed range. Therefore we make this look
715  * a bit nicer by spelling out the max constants.
716  */
718 /* Don't use "==" with floats, it might trigger a gcc warning.  */
719 #define GTKDOC_COMPARE_FLOAT(x, y) (x <= y && x >= y)
721 static gchar*
722 describe_double_constant (gdouble value)
724   gchar *desc;
726   if (GTKDOC_COMPARE_FLOAT (value, G_MAXDOUBLE))
727     desc = g_strdup ("G_MAXDOUBLE");
728   else if (GTKDOC_COMPARE_FLOAT (value, G_MINDOUBLE))
729     desc = g_strdup ("G_MINDOUBLE");
730   else if (GTKDOC_COMPARE_FLOAT (value, -G_MAXDOUBLE))
731     desc = g_strdup ("-G_MAXDOUBLE");
732   else if (GTKDOC_COMPARE_FLOAT (value, G_MAXFLOAT))
733     desc = g_strdup ("G_MAXFLOAT");
734   else if (GTKDOC_COMPARE_FLOAT (value, G_MINFLOAT))
735     desc = g_strdup ("G_MINFLOAT");
736   else if (GTKDOC_COMPARE_FLOAT (value, -G_MAXFLOAT))
737     desc = g_strdup ("-G_MAXFLOAT");
738   else{
739     /* make sure floats are output with a decimal dot irrespective of
740     * current locale. Use formatd since we want human-readable numbers
741     * and do not need the exact same bit representation when deserialising */
742     desc = g_malloc0 (G_ASCII_DTOSTR_BUF_SIZE);
743     g_ascii_formatd (desc, G_ASCII_DTOSTR_BUF_SIZE, "%g", value);
744   }
746   return desc;
749 static gchar*
750 describe_signed_constant (gsize size, gint64 value)
752   gchar *desc = NULL;
754   switch (size) {
755     case 2:
756       if (sizeof (int) == 2) {
757         if (value == G_MAXINT)
758           desc = g_strdup ("G_MAXINT");
759         else if (value == G_MININT)
760           desc = g_strdup ("G_MININT");
761         else if (value == (gint64)G_MAXUINT)
762           desc = g_strdup ("G_MAXUINT");
763       }
764       break;
765     case 4:
766       if (sizeof (int) == 4) {
767         if (value == G_MAXINT)
768           desc = g_strdup ("G_MAXINT");
769         else if (value == G_MININT)
770           desc = g_strdup ("G_MININT");
771         else if (value == (gint64)G_MAXUINT)
772           desc = g_strdup ("G_MAXUINT");
773       }
774       if (value == G_MAXLONG)
775         desc = g_strdup ("G_MAXLONG");
776       else if (value == G_MINLONG)
777         desc = g_strdup ("G_MINLONG");
778       else if (value == (gint64)G_MAXULONG)
779         desc = g_strdup ("G_MAXULONG");
780       break;
781     case 8:
782       if (value == G_MAXINT64)
783         desc = g_strdup ("G_MAXINT64");
784       else if (value == G_MININT64)
785         desc = g_strdup ("G_MININT64");
786       break;
787     default:
788       break;
789   }
790   if (!desc)
791     desc = g_strdup_printf ("%" G_GINT64_FORMAT, value);
793   return desc;
796 static gchar*
797 describe_unsigned_constant (gsize size, guint64 value)
799   gchar *desc = NULL;
801   switch (size) {
802     case 2:
803       if (sizeof (int) == 2) {
804         if (value == (guint64)G_MAXINT)
805           desc = g_strdup ("G_MAXINT");
806         else if (value == G_MAXUINT)
807           desc = g_strdup ("G_MAXUINT");
808       }
809       break;
810     case 4:
811       if (sizeof (int) == 4) {
812         if (value == (guint64)G_MAXINT)
813           desc = g_strdup ("G_MAXINT");
814         else if (value == G_MAXUINT)
815           desc = g_strdup ("G_MAXUINT");
816       }
817       if (value == (guint64)G_MAXLONG)
818         desc = g_strdup ("G_MAXLONG");
819       else if (value == G_MAXULONG)
820         desc = g_strdup ("G_MAXULONG");
821       break;
822     case 8:
823       if (value == G_MAXINT64)
824         desc = g_strdup ("G_MAXINT64");
825       else if (value == G_MAXUINT64)
826         desc = g_strdup ("G_MAXUINT64");
827       break;
828     default:
829       break;
830   }
831   if (!desc)
832     desc = g_strdup_printf ("%" G_GUINT64_FORMAT, value);
834   return desc;
837 static gchar*
838 describe_type (GParamSpec *spec)
840   gchar *desc;
841   gchar *lower;
842   gchar *upper;
844   if (G_IS_PARAM_SPEC_CHAR (spec))
845     {
846       GParamSpecChar *pspec = G_PARAM_SPEC_CHAR (spec);
848       lower = describe_signed_constant (sizeof(gchar), pspec->minimum);
849       upper = describe_signed_constant (sizeof(gchar), pspec->maximum);
850       if (pspec->minimum == G_MININT8 && pspec->maximum == G_MAXINT8)
851         desc = g_strdup ("");
852       else if (pspec->minimum == G_MININT8)
853         desc = g_strdup_printf ("<= %s", upper);
854       else if (pspec->maximum == G_MAXINT8)
855         desc = g_strdup_printf (">= %s", lower);
856       else
857         desc = g_strdup_printf ("[%s,%s]", lower, upper);
858       g_free (lower);
859       g_free (upper);
860     }
861   else if (G_IS_PARAM_SPEC_UCHAR (spec))
862     {
863       GParamSpecUChar *pspec = G_PARAM_SPEC_UCHAR (spec);
865       lower = describe_unsigned_constant (sizeof(guchar), pspec->minimum);
866       upper = describe_unsigned_constant (sizeof(guchar), pspec->maximum);
867       if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT8)
868         desc = g_strdup ("");
869       else if (pspec->minimum == 0)
870         desc = g_strdup_printf ("<= %s", upper);
871       else if (pspec->maximum == G_MAXUINT8)
872         desc = g_strdup_printf (">= %s", lower);
873       else
874         desc = g_strdup_printf ("[%s,%s]", lower, upper);
875       g_free (lower);
876       g_free (upper);
877     }
878   else if (G_IS_PARAM_SPEC_INT (spec))
879     {
880       GParamSpecInt *pspec = G_PARAM_SPEC_INT (spec);
882       lower = describe_signed_constant (sizeof(gint), pspec->minimum);
883       upper = describe_signed_constant (sizeof(gint), pspec->maximum);
884       if (pspec->minimum == G_MININT && pspec->maximum == G_MAXINT)
885         desc = g_strdup ("");
886       else if (pspec->minimum == G_MININT)
887         desc = g_strdup_printf ("<= %s", upper);
888       else if (pspec->maximum == G_MAXINT)
889         desc = g_strdup_printf (">= %s", lower);
890       else
891         desc = g_strdup_printf ("[%s,%s]", lower, upper);
892       g_free (lower);
893       g_free (upper);
894     }
895   else if (G_IS_PARAM_SPEC_UINT (spec))
896     {
897       GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (spec);
899       lower = describe_unsigned_constant (sizeof(guint), pspec->minimum);
900       upper = describe_unsigned_constant (sizeof(guint), pspec->maximum);
901       if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT)
902         desc = g_strdup ("");
903       else if (pspec->minimum == 0)
904         desc = g_strdup_printf ("<= %s", upper);
905       else if (pspec->maximum == G_MAXUINT)
906         desc = g_strdup_printf (">= %s", lower);
907       else
908         desc = g_strdup_printf ("[%s,%s]", lower, upper);
909       g_free (lower);
910       g_free (upper);
911     }
912   else if (G_IS_PARAM_SPEC_LONG (spec))
913     {
914       GParamSpecLong *pspec = G_PARAM_SPEC_LONG (spec);
916       lower = describe_signed_constant (sizeof(glong), pspec->minimum);
917       upper = describe_signed_constant (sizeof(glong), pspec->maximum);
918       if (pspec->minimum == G_MINLONG && pspec->maximum == G_MAXLONG)
919         desc = g_strdup ("");
920       else if (pspec->minimum == G_MINLONG)
921         desc = g_strdup_printf ("<= %s", upper);
922       else if (pspec->maximum == G_MAXLONG)
923         desc = g_strdup_printf (">= %s", lower);
924       else
925         desc = g_strdup_printf ("[%s,%s]", lower, upper);
926       g_free (lower);
927       g_free (upper);
928     }
929   else if (G_IS_PARAM_SPEC_ULONG (spec))
930     {
931       GParamSpecULong *pspec = G_PARAM_SPEC_ULONG (spec);
933       lower = describe_unsigned_constant (sizeof(gulong), pspec->minimum);
934       upper = describe_unsigned_constant (sizeof(gulong), pspec->maximum);
935       if (pspec->minimum == 0 && pspec->maximum == G_MAXULONG)
936         desc = g_strdup ("");
937       else if (pspec->minimum == 0)
938         desc = g_strdup_printf ("<= %s", upper);
939       else if (pspec->maximum == G_MAXULONG)
940         desc = g_strdup_printf (">= %s", lower);
941       else
942         desc = g_strdup_printf ("[%s,%s]", lower, upper);
943       g_free (lower);
944       g_free (upper);
945     }
946   else if (G_IS_PARAM_SPEC_INT64 (spec))
947     {
948       GParamSpecInt64 *pspec = G_PARAM_SPEC_INT64 (spec);
950       lower = describe_signed_constant (sizeof(gint64), pspec->minimum);
951       upper = describe_signed_constant (sizeof(gint64), pspec->maximum);
952       if (pspec->minimum == G_MININT64 && pspec->maximum == G_MAXINT64)
953         desc = g_strdup ("");
954       else if (pspec->minimum == G_MININT64)
955         desc = g_strdup_printf ("<= %s", upper);
956       else if (pspec->maximum == G_MAXINT64)
957         desc = g_strdup_printf (">= %s", lower);
958       else
959         desc = g_strdup_printf ("[%s,%s]", lower, upper);
960       g_free (lower);
961       g_free (upper);
962     }
963   else if (G_IS_PARAM_SPEC_UINT64 (spec))
964     {
965       GParamSpecUInt64 *pspec = G_PARAM_SPEC_UINT64 (spec);
967       lower = describe_unsigned_constant (sizeof(guint64), pspec->minimum);
968       upper = describe_unsigned_constant (sizeof(guint64), pspec->maximum);
969       if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT64)
970         desc = g_strdup ("");
971       else if (pspec->minimum == 0)
972         desc = g_strdup_printf ("<= %s", upper);
973       else if (pspec->maximum == G_MAXUINT64)
974         desc = g_strdup_printf (">= %s", lower);
975       else
976         desc = g_strdup_printf ("[%s,%s]", lower, upper);
977       g_free (lower);
978       g_free (upper);
979     }
980   else if (G_IS_PARAM_SPEC_FLOAT (spec))
981     {
982       GParamSpecFloat *pspec = G_PARAM_SPEC_FLOAT (spec);
984       lower = describe_double_constant (pspec->minimum);
985       upper = describe_double_constant (pspec->maximum);
986       if (GTKDOC_COMPARE_FLOAT (pspec->minimum, -G_MAXFLOAT))
987         {
988           if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXFLOAT))
989             desc = g_strdup ("");
990           else
991             desc = g_strdup_printf ("<= %s", upper);
992         }
993       else if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXFLOAT))
994         desc = g_strdup_printf (">= %s", lower);
995       else
996         desc = g_strdup_printf ("[%s,%s]", lower, upper);
997       g_free (lower);
998       g_free (upper);
999     }
1000   else if (G_IS_PARAM_SPEC_DOUBLE (spec))
1001     {
1002       GParamSpecDouble *pspec = G_PARAM_SPEC_DOUBLE (spec);
1004       lower = describe_double_constant (pspec->minimum);
1005       upper = describe_double_constant (pspec->maximum);
1006       if (GTKDOC_COMPARE_FLOAT (pspec->minimum, -G_MAXDOUBLE))
1007         {
1008           if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXDOUBLE))
1009             desc = g_strdup ("");
1010           else
1011             desc = g_strdup_printf ("<= %s", upper);
1012         }
1013       else if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXDOUBLE))
1014         desc = g_strdup_printf (">= %s", lower);
1015       else
1016         desc = g_strdup_printf ("[%s,%s]", lower, upper);
1017       g_free (lower);
1018       g_free (upper);
1019     }
1020 #if GLIB_CHECK_VERSION (2, 12, 0)
1021   else if (G_IS_PARAM_SPEC_GTYPE (spec))
1022     {
1023       GParamSpecGType *pspec = G_PARAM_SPEC_GTYPE (spec);
1024       gboolean is_pointer;
1026       desc = g_strdup (get_type_name (pspec->is_a_type, &is_pointer));
1027     }
1028 #endif
1029 #if GLIB_CHECK_VERSION (2, 25, 9)
1030   else if (G_IS_PARAM_SPEC_VARIANT (spec))
1031     {
1032       GParamSpecVariant *pspec = G_PARAM_SPEC_VARIANT (spec);
1033       gchar *variant_type;
1035       variant_type = g_variant_type_dup_string (pspec->type);
1036       desc = g_strdup_printf ("GVariant<%s>", variant_type);
1037       g_free (variant_type);
1038     }
1039 #endif
1040   else
1041     {
1042       desc = g_strdup ("");
1043     }
1045   return desc;
1048 static gchar*
1049 describe_default (GParamSpec *spec)
1051   gchar *desc;
1053   if (G_IS_PARAM_SPEC_CHAR (spec))
1054     {
1055       GParamSpecChar *pspec = G_PARAM_SPEC_CHAR (spec);
1057       desc = g_strdup_printf ("%d", pspec->default_value);
1058     }
1059   else if (G_IS_PARAM_SPEC_UCHAR (spec))
1060     {
1061       GParamSpecUChar *pspec = G_PARAM_SPEC_UCHAR (spec);
1063       desc = g_strdup_printf ("%u", pspec->default_value);
1064     }
1065   else if (G_IS_PARAM_SPEC_BOOLEAN (spec))
1066     {
1067       GParamSpecBoolean *pspec = G_PARAM_SPEC_BOOLEAN (spec);
1069       desc = g_strdup_printf ("%s", pspec->default_value ? "TRUE" : "FALSE");
1070     }
1071   else if (G_IS_PARAM_SPEC_INT (spec))
1072     {
1073       GParamSpecInt *pspec = G_PARAM_SPEC_INT (spec);
1075       desc = g_strdup_printf ("%d", pspec->default_value);
1076     }
1077   else if (G_IS_PARAM_SPEC_UINT (spec))
1078     {
1079       GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (spec);
1081       desc = g_strdup_printf ("%u", pspec->default_value);
1082     }
1083   else if (G_IS_PARAM_SPEC_LONG (spec))
1084     {
1085       GParamSpecLong *pspec = G_PARAM_SPEC_LONG (spec);
1087       desc = g_strdup_printf ("%ld", pspec->default_value);
1088     }
1089   else if (G_IS_PARAM_SPEC_LONG (spec))
1090     {
1091       GParamSpecULong *pspec = G_PARAM_SPEC_ULONG (spec);
1093       desc = g_strdup_printf ("%lu", pspec->default_value);
1094     }
1095   else if (G_IS_PARAM_SPEC_INT64 (spec))
1096     {
1097       GParamSpecInt64 *pspec = G_PARAM_SPEC_INT64 (spec);
1099       desc = g_strdup_printf ("%" G_GINT64_FORMAT, pspec->default_value);
1100     }
1101   else if (G_IS_PARAM_SPEC_UINT64 (spec))
1102     {
1103       GParamSpecUInt64 *pspec = G_PARAM_SPEC_UINT64 (spec);
1105       desc = g_strdup_printf ("%" G_GUINT64_FORMAT, pspec->default_value);
1106     }
1107   else if (G_IS_PARAM_SPEC_UNICHAR (spec))
1108     {
1109       GParamSpecUnichar *pspec = G_PARAM_SPEC_UNICHAR (spec);
1111       if (g_unichar_isprint (pspec->default_value))
1112         desc = g_strdup_printf ("'%c'", pspec->default_value);
1113       else
1114         desc = g_strdup_printf ("%u", pspec->default_value);
1115     }
1116   else if (G_IS_PARAM_SPEC_ENUM (spec))
1117     {
1118       GParamSpecEnum *pspec = G_PARAM_SPEC_ENUM (spec);
1120       GEnumValue *value = g_enum_get_value (pspec->enum_class, pspec->default_value);
1121       if (value)
1122         desc = g_strdup_printf ("%s", value->value_name);
1123       else
1124         desc = g_strdup_printf ("%d", pspec->default_value);
1125     }
1126   else if (G_IS_PARAM_SPEC_FLAGS (spec))
1127     {
1128       GParamSpecFlags *pspec = G_PARAM_SPEC_FLAGS (spec);
1129       guint default_value;
1130       GString *acc;
1132       default_value = pspec->default_value;
1133       acc = g_string_new ("");
1135       while (default_value)
1136         {
1137           GFlagsValue *value = g_flags_get_first_value (pspec->flags_class, default_value);
1139           if (!value)
1140             break;
1142           if (acc->len > 0)
1143             g_string_append (acc, "|");
1144           g_string_append (acc, value->value_name);
1146           default_value &= ~value->value;
1147         }
1149       if (default_value == 0)
1150         desc = g_string_free (acc, FALSE);
1151       else
1152         {
1153           desc = g_strdup_printf ("%d", pspec->default_value);
1154           g_string_free (acc, TRUE);
1155         }
1156     }
1157   else if (G_IS_PARAM_SPEC_FLOAT (spec))
1158     {
1159       GParamSpecFloat *pspec = G_PARAM_SPEC_FLOAT (spec);
1161       /* make sure floats are output with a decimal dot irrespective of
1162        * current locale. Use formatd since we want human-readable numbers
1163        * and do not need the exact same bit representation when deserialising */
1164       desc = g_malloc0 (G_ASCII_DTOSTR_BUF_SIZE);
1165       g_ascii_formatd (desc, G_ASCII_DTOSTR_BUF_SIZE, "%g",
1166           pspec->default_value);
1167     }
1168   else if (G_IS_PARAM_SPEC_DOUBLE (spec))
1169     {
1170       GParamSpecDouble *pspec = G_PARAM_SPEC_DOUBLE (spec);
1172       /* make sure floats are output with a decimal dot irrespective of
1173        * current locale. Use formatd since we want human-readable numbers
1174        * and do not need the exact same bit representation when deserialising */
1175       desc = g_malloc0 (G_ASCII_DTOSTR_BUF_SIZE);
1176       g_ascii_formatd (desc, G_ASCII_DTOSTR_BUF_SIZE, "%g",
1177           pspec->default_value);
1178     }
1179   else if (G_IS_PARAM_SPEC_STRING (spec))
1180     {
1181       GParamSpecString *pspec = G_PARAM_SPEC_STRING (spec);
1183       if (pspec->default_value)
1184         {
1185           gchar *esc = g_strescape (pspec->default_value, NULL);
1187           desc = g_strdup_printf ("\\"%s\\"", esc);
1189           g_free (esc);
1190         }
1191       else
1192         desc = g_strdup_printf ("NULL");
1193     }
1194 #if GLIB_CHECK_VERSION (2, 25, 9)
1195   else if (G_IS_PARAM_SPEC_VARIANT (spec))
1196     {
1197       GParamSpecVariant *pspec = G_PARAM_SPEC_VARIANT (spec);
1199       if (pspec->default_value)
1200         desc = g_variant_print (pspec->default_value, TRUE);
1201       else
1202         desc = g_strdup ("NULL");
1203     }
1204 #endif
1205   else
1206     {
1207       desc = g_strdup ("");
1208     }
1210   return desc;
1214 static void
1215 output_object_args (FILE *fp, GType object_type)
1217   gpointer class;
1218   const gchar *object_class_name;
1219   guint arg;
1220   gchar flags[16], *pos;
1221   GParamSpec **properties;
1222   guint n_properties;
1223   gboolean child_prop;
1224   gboolean style_prop;
1225   gboolean is_pointer;
1226   const gchar *type_name;
1227   gchar *type_desc;
1228   gchar *default_value;
1230   if (G_TYPE_IS_OBJECT (object_type))
1231     {
1232       class = g_type_class_peek (object_type);
1233       if (!class)
1234         return;
1236       properties = g_object_class_list_properties (class, &n_properties);
1237     }
1238 #if GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 3)
1239   else if (G_TYPE_IS_INTERFACE (object_type))
1240     {
1241       class = g_type_default_interface_ref (object_type);
1243       if (!class)
1244         return;
1246       properties = g_object_interface_list_properties (class, &n_properties);
1247     }
1248 #endif
1249   else
1250     return;
1252   object_class_name = g_type_name (object_type);
1254   child_prop = FALSE;
1255   style_prop = FALSE;
1257   while (TRUE) {
1258     qsort (properties, n_properties, sizeof (GParamSpec *), compare_param_specs);
1259     for (arg = 0; arg < n_properties; arg++)
1260       {
1261         GParamSpec *spec = properties[arg];
1262         const gchar *nick, *blurb, *dot;
1264         if (spec->owner_type != object_type)
1265           continue;
1267         pos = flags;
1268         /* We use one-character flags for simplicity. */
1269         if (child_prop && !style_prop)
1270           *pos++ = 'c';
1271         if (style_prop)
1272           *pos++ = 's';
1273         if (spec->flags & G_PARAM_READABLE)
1274           *pos++ = 'r';
1275         if (spec->flags & G_PARAM_WRITABLE)
1276           *pos++ = 'w';
1277         if (spec->flags & G_PARAM_CONSTRUCT)
1278           *pos++ = 'x';
1279         if (spec->flags & G_PARAM_CONSTRUCT_ONLY)
1280           *pos++ = 'X';
1281         *pos = 0;
1283         nick = g_param_spec_get_nick (spec);
1284         blurb = g_param_spec_get_blurb (spec);
1286         dot = "";
1287         if (blurb) {
1288           int str_len = strlen (blurb);
1289           if (str_len > 0  && blurb[str_len - 1] != '.')
1290             dot = ".";
1291         }
1293         type_desc = describe_type (spec);
1294         default_value = describe_default (spec);
1295         type_name = get_type_name (spec->value_type, &is_pointer);
1296         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",
1297                  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);
1298         g_free (type_desc);
1299         g_free (default_value);
1300       }
1302     g_free (properties);
1304 #ifdef GTK_IS_CONTAINER_CLASS
1305     if (!child_prop && GTK_IS_CONTAINER_CLASS (class)) {
1306       properties = gtk_container_class_list_child_properties (class, &n_properties);
1307       child_prop = TRUE;
1308       continue;
1309     }
1310 #endif
1312 #ifdef GTK_IS_CELL_AREA_CLASS
1313     if (!child_prop && GTK_IS_CELL_AREA_CLASS (class)) {
1314       properties = gtk_cell_area_class_list_cell_properties (class, &n_properties);
1315       child_prop = TRUE;
1316       continue;
1317     }
1318 #endif
1320 #ifdef GTK_IS_WIDGET_CLASS
1321 #if GTK_CHECK_VERSION(2,1,0)
1322     if (!style_prop && GTK_IS_WIDGET_CLASS (class)) {
1323       properties = gtk_widget_class_list_style_properties (GTK_WIDGET_CLASS (class), &n_properties);
1324       style_prop = TRUE;
1325       continue;
1326     }
1327 #endif
1328 #endif
1332 if ($QUERY_CHILD_PROPERTIES) {
1333   print OUTPUT <<EOT;
1334     if (!child_prop) {
1335       properties = $QUERY_CHILD_PROPERTIES (class, &n_properties);
1336       if (properties) {
1337         child_prop = TRUE;
1338         continue;
1339       }
1340    }
1345 print OUTPUT <<EOT;
1346     break;
1347   }
1351 close OUTPUT;
1353 # Compile and run our file
1355 $CC = $ENV{CC} ? $ENV{CC} : "gcc";
1356 $LD = $ENV{LD} ? $ENV{LD} : $CC;
1357 $CFLAGS = $ENV{CFLAGS} ? $ENV{CFLAGS} : "";
1358 $LDFLAGS = $ENV{LDFLAGS} ? $ENV{LDFLAGS} : "";
1359 $RUN = $ENV{RUN} ? $ENV{RUN} : "";
1361 my $o_file;
1362 if ($CC =~ /libtool/) {
1363   $o_file  = "$MODULE-scan.lo"
1364 } else {
1365   $o_file = "$MODULE-scan.o"
1368 print "gtk-doc: Compiling scanner\n";
1369 $command = "$CC $CFLAGS -c -o $o_file $MODULE-scan.c";
1370 system("($command)") == 0 or die "Compilation of scanner failed: $!\n";
1372 print "gtk-doc: Linking scanner\n";
1373 # FIXME: Can we turn off as-needed for the docs (or better fix it?)
1374 #$command = "$LD -Wl,--no-as-needed $o_file $LDFLAGS -o $MODULE-scan";
1375 $command = "$LD $o_file $LDFLAGS -o $MODULE-scan";
1376 system("($command)") == 0 or die "Linking of scanner failed: $!\n";
1378 print "gtk-doc: Running scanner $MODULE-scan\n";
1379 system("($RUN ./$MODULE-scan)") == 0 or die "Scan failed: $!\n";
1382 if (!defined($ENV{"GTK_DOC_KEEP_INTERMEDIATE"})) {
1383   unlink "./$MODULE-scan.c", "./$MODULE-scan.o", "./$MODULE-scan.lo", "./$MODULE-scan";
1386 &UpdateFileIfChanged ($old_signals_filename, $new_signals_filename, 0);
1387 &UpdateFileIfChanged ($old_hierarchy_filename, $new_hierarchy_filename, 0);
1388 &UpdateFileIfChanged ($old_interfaces_filename, $new_interfaces_filename, 0);
1389 &UpdateFileIfChanged ($old_prerequisites_filename, $new_prerequisites_filename, 0);
1390 &UpdateFileIfChanged ($old_args_filename, $new_args_filename, 0);