1 #include <string.h>
   2 #include <stdlib.h>
   3 #include <stdio.h>
   4 #include <errno.h>
   5 #include <glib-object.h>
   6 
   7 extern GType bamf_application_get_type (void);
   8 extern GType bamf_control_get_type (void);
   9 extern GType bamf_factory_get_type (void);
  10 extern GType bamf_matcher_get_type (void);
  11 extern GType bamf_tab_source_get_type (void);
  12 extern GType bamf_view_get_type (void);
  13 extern GType bamf_window_get_type (void);
  14 
  15 #ifdef GTK_IS_WIDGET_CLASS
  16 #include <gtk/gtk.h>
  17 #endif
  18 GType object_types[8];
  19 
  20 static GType *
  21 get_object_types (void)
  22 {
  23     gpointer g_object_class;
  24     gint i = 0;
  25     object_types[i++] = bamf_application_get_type ();
  26     object_types[i++] = bamf_control_get_type ();
  27     object_types[i++] = bamf_factory_get_type ();
  28     object_types[i++] = bamf_matcher_get_type ();
  29     object_types[i++] = bamf_tab_source_get_type ();
  30     object_types[i++] = bamf_view_get_type ();
  31     object_types[i++] = bamf_window_get_type ();
  32     object_types[i] = 0;
  33 
  34     /* reference the GObjectClass to initialize the param spec pool
  35      * potentially needed by interfaces. See http://bugs.gnome.org/571820 */
  36     g_object_class = g_type_class_ref (G_TYPE_OBJECT);
  37 
  38     /* Need to make sure all the types are loaded in and initialize
  39      * their signals and properties.
  40      */
  41     for (i=0; object_types[i]; i++)
  42       {
  43         if (G_TYPE_IS_CLASSED (object_types[i]))
  44           g_type_class_ref (object_types[i]);
  45         if (G_TYPE_IS_INTERFACE (object_types[i]))
  46           g_type_default_interface_ref (object_types[i]);
  47       }
  48 
  49     g_type_class_unref (g_object_class);
  50 
  51     return object_types;
  52 }
  53 
  54 /*
  55  * This uses GObject type functions to output signal prototypes and the object
  56  * hierarchy.
  57  */
  58 
  59 /* The output files */
  60 const gchar *signals_filename = "./libbamf.signals.new";
  61 const gchar *hierarchy_filename = "./libbamf.hierarchy.new";
  62 const gchar *interfaces_filename = "./libbamf.interfaces.new";
  63 const gchar *prerequisites_filename = "./libbamf.prerequisites.new";
  64 const gchar *args_filename = "./libbamf.args.new";
  65 
  66 
  67 static void output_signals (void);
  68 static void output_object_signals (FILE *fp,
  69                                    GType object_type);
  70 static void output_object_signal (FILE *fp,
  71                                   const gchar *object_class_name,
  72                                   guint signal_id);
  73 static const gchar * get_type_name (GType type,
  74                                     gboolean * is_pointer);
  75 static void output_object_hierarchy (void);
  76 static void output_hierarchy (FILE *fp,
  77                               GType type,
  78                               guint level);
  79 
  80 static void output_object_interfaces (void);
  81 static void output_interfaces (FILE *fp,
  82                                GType type);
  83 
  84 static void output_interface_prerequisites (void);
  85 static void output_prerequisites (FILE *fp,
  86                                   GType type);
  87 
  88 static void output_args (void);
  89 static void output_object_args (FILE *fp, GType object_type);
  90 
  91 int
  92 main (int argc, char *argv[])
  93 {
  94   g_type_init(); g_type_class_ref(G_TYPE_OBJECT);
  95 
  96   get_object_types ();
  97 
  98   output_signals ();
  99   output_object_hierarchy ();
 100   output_object_interfaces ();
 101   output_interface_prerequisites ();
 102   output_args ();
 103 
 104   return 0;
 105 }
 106 
 107 
 108 static void
 109 output_signals (void)
 110 {
 111   FILE *fp;
 112   gint i;
 113 
 114   fp = fopen (signals_filename, "w");
 115   if (fp == NULL)
 116     {
 117       g_warning ("Couldn't open output file: %s : %s", signals_filename, g_strerror(errno));
 118       return;
 119     }
 120 
 121   for (i = 0; object_types[i]; i++)
 122     output_object_signals (fp, object_types[i]);
 123 
 124   fclose (fp);
 125 }
 126 
 127 static gint
 128 compare_signals (const void *a, const void *b)
 129 {
 130   const guint *signal_a = a;
 131   const guint *signal_b = b;
 132 
 133   return strcmp (g_signal_name (*signal_a), g_signal_name (*signal_b));
 134 }
 135 
 136 /* This outputs all the signals of one object. */
 137 static void
 138 output_object_signals (FILE *fp, GType object_type)
 139 {
 140   const gchar *object_class_name;
 141   guint *signals, n_signals;
 142   guint sig;
 143 
 144   if (G_TYPE_IS_INSTANTIATABLE (object_type) ||
 145       G_TYPE_IS_INTERFACE (object_type))
 146     {
 147 
 148       object_class_name = g_type_name (object_type);
 149 
 150       signals = g_signal_list_ids (object_type, &n_signals);
 151       qsort (signals, n_signals, sizeof (guint), compare_signals);
 152 
 153       for (sig = 0; sig < n_signals; sig++)
 154         {
 155            output_object_signal (fp, object_class_name, signals[sig]);
 156         }
 157       g_free (signals);
 158    }
 159 }
 160 
 161 
 162 /* This outputs one signal. */
 163 static void
 164 output_object_signal (FILE *fp,
 165                       const gchar *object_name,
 166                       guint signal_id)
 167 {
 168   GSignalQuery query_info;
 169   const gchar *type_name, *ret_type, *object_arg, *arg_name;
 170   gchar *pos, *object_arg_lower;
 171   gboolean is_pointer;
 172   gchar buffer[1024];
 173   guint i, param;
 174   gint param_num, widget_num, event_num, callback_num;
 175   gint *arg_num;
 176   gchar signal_name[128];
 177   gchar flags[16];
 178 
 179   /*  g_print ("Object: %s Signal: %u\n", object_name, signal_id);*/
 180 
 181   param_num = 1;
 182   widget_num = event_num = callback_num = 0;
 183 
 184   g_signal_query (signal_id, &query_info);
 185 
 186   /* Output the signal object type and the argument name. We assume the
 187      type is a pointer - I think that is OK. We remove "Gtk" or "Gnome" and
 188      convert to lower case for the argument name. */
 189   pos = buffer;
 190   sprintf (pos, "%s ", object_name);
 191   pos += strlen (pos);
 192 
 193   /* Try to come up with a sensible variable name for the first arg
 194    * It chops off 2 know prefixes :/ and makes the name lowercase
 195    * It should replace lowercase -> uppercase with '_'
 196    * GFileMonitor -> file_monitor
 197    * GIOExtensionPoint -> extension_point
 198    * GtkTreeView -> tree_view
 199    * if 2nd char is upper case too
 200    *   search for first lower case and go back one char
 201    * else
 202    *   search for next upper case
 203    */
 204   if (!strncmp (object_name, "Gtk", 3))
 205       object_arg = object_name + 3;
 206   else if (!strncmp (object_name, "Gnome", 5))
 207       object_arg = object_name + 5;
 208   else
 209       object_arg = object_name;
 210 
 211   object_arg_lower = g_ascii_strdown (object_arg, -1);
 212   sprintf (pos, "*%s\n", object_arg_lower);
 213   pos += strlen (pos);
 214   if (!strncmp (object_arg_lower, "widget", 6))
 215     widget_num = 2;
 216   g_free(object_arg_lower);
 217 
 218   /* Convert signal name to use underscores rather than dashes '-'. */
 219   strncpy (signal_name, query_info.signal_name, 127);
 220   signal_name[127] = '\0';
 221   for (i = 0; signal_name[i]; i++)
 222     {
 223       if (signal_name[i] == '-')
 224         signal_name[i] = '_';
 225     }
 226 
 227   /* Output the signal parameters. */
 228   for (param = 0; param < query_info.n_params; param++)
 229     {
 230       type_name = get_type_name (query_info.param_types[param] & ~G_SIGNAL_TYPE_STATIC_SCOPE, &is_pointer);
 231 
 232       /* Most arguments to the callback are called "arg1", "arg2", etc.
 233          GtkWidgets are called "widget", "widget2", ...
 234          GtkCallbacks are called "callback", "callback2", ... */
 235       if (!strcmp (type_name, "GtkWidget"))
 236         {
 237           arg_name = "widget";
 238           arg_num = &widget_num;
 239         }
 240       else if (!strcmp (type_name, "GtkCallback")
 241                || !strcmp (type_name, "GtkCCallback"))
 242         {
 243           arg_name = "callback";
 244           arg_num = &callback_num;
 245         }
 246       else
 247         {
 248           arg_name = "arg";
 249           arg_num = &param_num;
 250         }
 251       sprintf (pos, "%s ", type_name);
 252       pos += strlen (pos);
 253 
 254       if (!arg_num || *arg_num == 0)
 255         sprintf (pos, "%s%s\n", is_pointer ? "*" : " ", arg_name);
 256       else
 257         sprintf (pos, "%s%s%i\n", is_pointer ? "*" : " ", arg_name,
 258                  *arg_num);
 259       pos += strlen (pos);
 260 
 261       if (arg_num)
 262         {
 263           if (*arg_num == 0)
 264             *arg_num = 2;
 265           else
 266             *arg_num += 1;
 267         }
 268     }
 269 
 270   pos = flags;
 271   /* We use one-character flags for simplicity. */
 272   if (query_info.signal_flags & G_SIGNAL_RUN_FIRST)
 273     *pos++ = 'f';
 274   if (query_info.signal_flags & G_SIGNAL_RUN_LAST)
 275     *pos++ = 'l';
 276   if (query_info.signal_flags & G_SIGNAL_RUN_CLEANUP)
 277     *pos++ = 'c';
 278   if (query_info.signal_flags & G_SIGNAL_NO_RECURSE)
 279     *pos++ = 'r';
 280   if (query_info.signal_flags & G_SIGNAL_DETAILED)
 281     *pos++ = 'd';
 282   if (query_info.signal_flags & G_SIGNAL_ACTION)
 283     *pos++ = 'a';
 284   if (query_info.signal_flags & G_SIGNAL_NO_HOOKS)
 285     *pos++ = 'h';
 286   *pos = 0;
 287 
 288   /* Output the return type and function name. */
 289   ret_type = get_type_name (query_info.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE, &is_pointer);
 290 
 291   fprintf (fp,
 292            "<SIGNAL>\n<NAME>%s::%s</NAME>\n<RETURNS>%s%s</RETURNS>\n<FLAGS>%s</FLAGS>\n%s</SIGNAL>\n\n",
 293            object_name, query_info.signal_name, ret_type, is_pointer ? "*" : "", flags, buffer);
 294 }
 295 
 296 
 297 /* Returns the type name to use for a signal argument or return value, given
 298    the GtkType from the signal info. It also sets is_pointer to TRUE if the
 299    argument needs a '*' since it is a pointer. */
 300 static const gchar *
 301 get_type_name (GType type, gboolean * is_pointer)
 302 {
 303   const gchar *type_name;
 304 
 305   *is_pointer = FALSE;
 306   type_name = g_type_name (type);
 307 
 308   switch (type) {
 309   case G_TYPE_NONE:
 310   case G_TYPE_CHAR:
 311   case G_TYPE_UCHAR:
 312   case G_TYPE_BOOLEAN:
 313   case G_TYPE_INT:
 314   case G_TYPE_UINT:
 315   case G_TYPE_LONG:
 316   case G_TYPE_ULONG:
 317   case G_TYPE_FLOAT:
 318   case G_TYPE_DOUBLE:
 319   case G_TYPE_POINTER:
 320     /* These all have normal C type names so they are OK. */
 321     return type_name;
 322 
 323   case G_TYPE_STRING:
 324     /* A GtkString is really a gchar*. */
 325     *is_pointer = TRUE;
 326     return "gchar";
 327 
 328   case G_TYPE_ENUM:
 329   case G_TYPE_FLAGS:
 330     /* We use a gint for both of these. Hopefully a subtype with a decent
 331        name will be registered and used instead, as GTK+ does itself. */
 332     return "gint";
 333 
 334   case G_TYPE_BOXED:
 335     /* The boxed type shouldn't be used itself, only subtypes. Though we
 336        return 'gpointer' just in case. */
 337     return "gpointer";
 338 
 339   case G_TYPE_PARAM:
 340     /* A GParam is really a GParamSpec*. */
 341     *is_pointer = TRUE;
 342     return "GParamSpec";
 343 
 344 #if GLIB_CHECK_VERSION (2, 25, 9)
 345   case G_TYPE_VARIANT:
 346     *is_pointer = TRUE;
 347     return "GVariant";
 348 #endif
 349 
 350 default:
 351     break;
 352   }
 353 
 354   /* For all GObject subclasses we can use the class name with a "*",
 355      e.g. 'GtkWidget *'. */
 356   if (g_type_is_a (type, G_TYPE_OBJECT))
 357     *is_pointer = TRUE;
 358 
 359   /* Also catch non GObject root types */
 360   if (G_TYPE_IS_CLASSED (type))
 361     *is_pointer = TRUE;
 362 
 363   /* All boxed subtypes will be pointers as well. */
 364   /* Exception: GStrv */
 365   if (g_type_is_a (type, G_TYPE_BOXED) &&
 366       !g_type_is_a (type, G_TYPE_STRV))
 367     *is_pointer = TRUE;
 368 
 369   /* All pointer subtypes will be pointers as well. */
 370   if (g_type_is_a (type, G_TYPE_POINTER))
 371     *is_pointer = TRUE;
 372 
 373   /* But enums are not */
 374   if (g_type_is_a (type, G_TYPE_ENUM) ||
 375       g_type_is_a (type, G_TYPE_FLAGS))
 376     *is_pointer = FALSE;
 377 
 378   return type_name;
 379 }
 380 
 381 
 382 /* This outputs the hierarchy of all objects which have been initialized,
 383    i.e. by calling their XXX_get_type() initialization function. */
 384 static void
 385 output_object_hierarchy (void)
 386 {
 387   FILE *fp;
 388   gint i,j;
 389   GType root, type;
 390   GType root_types[8] = { G_TYPE_INVALID, };
 391 
 392   fp = fopen (hierarchy_filename, "w");
 393   if (fp == NULL)
 394     {
 395       g_warning ("Couldn't open output file: %s : %s", hierarchy_filename, g_strerror(errno));
 396       return;
 397     }
 398   output_hierarchy (fp, G_TYPE_OBJECT, 0);
 399   output_hierarchy (fp, G_TYPE_INTERFACE, 0);
 400 
 401   for (i=0; object_types[i]; i++) {
 402     root = object_types[i];
 403     while ((type = g_type_parent (root))) {
 404       root = type;
 405     }
 406     if ((root != G_TYPE_OBJECT) && (root != G_TYPE_INTERFACE)) {
 407       for (j=0; root_types[j]; j++) {
 408         if (root == root_types[j]) {
 409           root = G_TYPE_INVALID; break;
 410         }
 411       }
 412       if(root) {
 413         root_types[j] = root;
 414         output_hierarchy (fp, root, 0);
 415       }
 416     }
 417   }
 418 
 419   fclose (fp);
 420 }
 421 
 422 /* This is called recursively to output the hierarchy of a object. */
 423 static void
 424 output_hierarchy (FILE  *fp,
 425                   GType  type,
 426                   guint   level)
 427 {
 428   guint i;
 429   GType *children;
 430   guint n_children;
 431 
 432   if (!type)
 433     return;
 434 
 435   for (i = 0; i < level; i++)
 436     fprintf (fp, "  ");
 437   fprintf (fp, "%s\n", g_type_name (type));
 438 
 439   children = g_type_children (type, &n_children);
 440 
 441   for (i=0; i < n_children; i++)
 442     output_hierarchy (fp, children[i], level + 1);
 443 
 444   g_free (children);
 445 }
 446 
 447 static void output_object_interfaces (void)
 448 {
 449   guint i;
 450   FILE *fp;
 451 
 452   fp = fopen (interfaces_filename, "w");
 453   if (fp == NULL)
 454     {
 455       g_warning ("Couldn't open output file: %s : %s", interfaces_filename, g_strerror(errno));
 456       return;
 457     }
 458   output_interfaces (fp, G_TYPE_OBJECT);
 459 
 460   for (i = 0; object_types[i]; i++)
 461     {
 462       if (!g_type_parent (object_types[i]) &&
 463           (object_types[i] != G_TYPE_OBJECT) &&
 464           G_TYPE_IS_INSTANTIATABLE (object_types[i]))
 465         {
 466           output_interfaces (fp, object_types[i]);
 467         }
 468     }
 469   fclose (fp);
 470 }
 471 
 472 static void
 473 output_interfaces (FILE  *fp,
 474                    GType  type)
 475 {
 476   guint i;
 477   GType *children, *interfaces;
 478   guint n_children, n_interfaces;
 479 
 480   if (!type)
 481     return;
 482 
 483   interfaces = g_type_interfaces (type, &n_interfaces);
 484 
 485   if (n_interfaces > 0)
 486     {
 487       fprintf (fp, "%s", g_type_name (type));
 488       for (i=0; i < n_interfaces; i++)
 489           fprintf (fp, " %s", g_type_name (interfaces[i]));
 490       fprintf (fp, "\n");
 491      }
 492   g_free (interfaces);
 493 
 494   children = g_type_children (type, &n_children);
 495 
 496   for (i=0; i < n_children; i++)
 497     output_interfaces (fp, children[i]);
 498 
 499   g_free (children);
 500 }
 501 
 502 static void output_interface_prerequisites (void)
 503 {
 504   FILE *fp;
 505 
 506   fp = fopen (prerequisites_filename, "w");
 507   if (fp == NULL)
 508     {
 509       g_warning ("Couldn't open output file: %s : %s", prerequisites_filename, g_strerror(errno));
 510       return;
 511     }
 512   output_prerequisites (fp, G_TYPE_INTERFACE);
 513   fclose (fp);
 514 }
 515 
 516 static void
 517 output_prerequisites (FILE  *fp,
 518                       GType  type)
 519 {
 520 #if GLIB_CHECK_VERSION(2,1,0)
 521   guint i;
 522   GType *children, *prerequisites;
 523   guint n_children, n_prerequisites;
 524 
 525   if (!type)
 526     return;
 527 
 528   prerequisites = g_type_interface_prerequisites (type, &n_prerequisites);
 529 
 530   if (n_prerequisites > 0)
 531     {
 532       fprintf (fp, "%s", g_type_name (type));
 533       for (i=0; i < n_prerequisites; i++)
 534           fprintf (fp, " %s", g_type_name (prerequisites[i]));
 535       fprintf (fp, "\n");
 536      }
 537   g_free (prerequisites);
 538 
 539   children = g_type_children (type, &n_children);
 540 
 541   for (i=0; i < n_children; i++)
 542     output_prerequisites (fp, children[i]);
 543 
 544   g_free (children);
 545 #endif
 546 }
 547 
 548 static void
 549 output_args (void)
 550 {
 551   FILE *fp;
 552   gint i;
 553 
 554   fp = fopen (args_filename, "w");
 555   if (fp == NULL)
 556     {
 557       g_warning ("Couldn't open output file: %s : %s", args_filename, g_strerror(errno));
 558       return;
 559     }
 560 
 561   for (i = 0; object_types[i]; i++) {
 562     output_object_args (fp, object_types[i]);
 563   }
 564 
 565   fclose (fp);
 566 }
 567 
 568 static gint
 569 compare_param_specs (const void *a, const void *b)
 570 {
 571   GParamSpec *spec_a = *(GParamSpec **)a;
 572   GParamSpec *spec_b = *(GParamSpec **)b;
 573 
 574   return strcmp (g_param_spec_get_name (spec_a), g_param_spec_get_name (spec_b));
 575 }
 576 
 577 /* Its common to have unsigned properties restricted
 578  * to the signed range. Therefore we make this look
 579  * a bit nicer by spelling out the max constants.
 580  */
 581 
 582 /* Don't use "==" with floats, it might trigger a gcc warning.  */
 583 #define GTKDOC_COMPARE_FLOAT(x, y) (x <= y && x >= y)
 584 
 585 static gchar*
 586 describe_double_constant (gdouble value)
 587 {
 588   gchar *desc;
 589 
 590   if (GTKDOC_COMPARE_FLOAT (value, G_MAXDOUBLE))
 591     desc = g_strdup ("G_MAXDOUBLE");
 592   else if (GTKDOC_COMPARE_FLOAT (value, G_MINDOUBLE))
 593     desc = g_strdup ("G_MINDOUBLE");
 594   else if (GTKDOC_COMPARE_FLOAT (value, -G_MAXDOUBLE))
 595     desc = g_strdup ("-G_MAXDOUBLE");
 596   else if (GTKDOC_COMPARE_FLOAT (value, G_MAXFLOAT))
 597     desc = g_strdup ("G_MAXFLOAT");
 598   else if (GTKDOC_COMPARE_FLOAT (value, G_MINFLOAT))
 599     desc = g_strdup ("G_MINFLOAT");
 600   else if (GTKDOC_COMPARE_FLOAT (value, -G_MAXFLOAT))
 601     desc = g_strdup ("-G_MAXFLOAT");
 602   else{
 603     /* make sure floats are output with a decimal dot irrespective of
 604     * current locale. Use formatd since we want human-readable numbers
 605     * and do not need the exact same bit representation when deserialising */
 606     desc = g_malloc0 (G_ASCII_DTOSTR_BUF_SIZE);
 607     g_ascii_formatd (desc, G_ASCII_DTOSTR_BUF_SIZE, "%g", value);
 608   }
 609 
 610   return desc;
 611 }
 612 
 613 static gchar*
 614 describe_signed_constant (gsize size, gint64 value)
 615 {
 616   gchar *desc = NULL;
 617 
 618   switch (size) {
 619     case 2:
 620       if (sizeof (int) == 2) {
 621         if (value == G_MAXINT)
 622           desc = g_strdup ("G_MAXINT");
 623         else if (value == G_MININT)
 624           desc = g_strdup ("G_MININT");
 625         else if (value == (gint64)G_MAXUINT)
 626           desc = g_strdup ("G_MAXUINT");
 627       }
 628       break;
 629     case 4:
 630       if (sizeof (int) == 4) {
 631         if (value == G_MAXINT)
 632           desc = g_strdup ("G_MAXINT");
 633         else if (value == G_MININT)
 634           desc = g_strdup ("G_MININT");
 635         else if (value == (gint64)G_MAXUINT)
 636           desc = g_strdup ("G_MAXUINT");
 637       }
 638       if (value == G_MAXLONG)
 639         desc = g_strdup ("G_MAXLONG");
 640       else if (value == G_MINLONG)
 641         desc = g_strdup ("G_MINLONG");
 642       else if (value == (gint64)G_MAXULONG)
 643         desc = g_strdup ("G_MAXULONG");
 644       break;
 645     case 8:
 646       if (value == G_MAXINT64)
 647         desc = g_strdup ("G_MAXINT64");
 648       else if (value == G_MININT64)
 649         desc = g_strdup ("G_MININT64");
 650       break;
 651     default:
 652       break;
 653   }
 654   if (!desc)
 655     desc = g_strdup_printf ("%" G_GINT64_FORMAT, value);
 656 
 657   return desc;
 658 }
 659 
 660 static gchar*
 661 describe_unsigned_constant (gsize size, guint64 value)
 662 {
 663   gchar *desc = NULL;
 664 
 665   switch (size) {
 666     case 2:
 667       if (sizeof (int) == 2) {
 668         if (value == (guint64)G_MAXINT)
 669           desc = g_strdup ("G_MAXINT");
 670         else if (value == G_MAXUINT)
 671           desc = g_strdup ("G_MAXUINT");
 672       }
 673       break;
 674     case 4:
 675       if (sizeof (int) == 4) {
 676         if (value == (guint64)G_MAXINT)
 677           desc = g_strdup ("G_MAXINT");
 678         else if (value == G_MAXUINT)
 679           desc = g_strdup ("G_MAXUINT");
 680       }
 681       if (value == (guint64)G_MAXLONG)
 682         desc = g_strdup ("G_MAXLONG");
 683       else if (value == G_MAXULONG)
 684         desc = g_strdup ("G_MAXULONG");
 685       break;
 686     case 8:
 687       if (value == G_MAXINT64)
 688         desc = g_strdup ("G_MAXINT64");
 689       else if (value == G_MAXUINT64)
 690         desc = g_strdup ("G_MAXUINT64");
 691       break;
 692     default:
 693       break;
 694   }
 695   if (!desc)
 696     desc = g_strdup_printf ("%" G_GUINT64_FORMAT, value);
 697 
 698   return desc;
 699 }
 700 
 701 static gchar*
 702 describe_type (GParamSpec *spec)
 703 {
 704   gchar *desc;
 705   gchar *lower;
 706   gchar *upper;
 707 
 708   if (G_IS_PARAM_SPEC_CHAR (spec))
 709     {
 710       GParamSpecChar *pspec = G_PARAM_SPEC_CHAR (spec);
 711 
 712       lower = describe_signed_constant (sizeof(gchar), pspec->minimum);
 713       upper = describe_signed_constant (sizeof(gchar), pspec->maximum);
 714       if (pspec->minimum == G_MININT8 && pspec->maximum == G_MAXINT8)
 715         desc = g_strdup ("");
 716       else if (pspec->minimum == G_MININT8)
 717         desc = g_strdup_printf ("<= %s", upper);
 718       else if (pspec->maximum == G_MAXINT8)
 719         desc = g_strdup_printf (">= %s", lower);
 720       else
 721         desc = g_strdup_printf ("[%s,%s]", lower, upper);
 722       g_free (lower);
 723       g_free (upper);
 724     }
 725   else if (G_IS_PARAM_SPEC_UCHAR (spec))
 726     {
 727       GParamSpecUChar *pspec = G_PARAM_SPEC_UCHAR (spec);
 728 
 729       lower = describe_unsigned_constant (sizeof(guchar), pspec->minimum);
 730       upper = describe_unsigned_constant (sizeof(guchar), pspec->maximum);
 731       if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT8)
 732         desc = g_strdup ("");
 733       else if (pspec->minimum == 0)
 734         desc = g_strdup_printf ("<= %s", upper);
 735       else if (pspec->maximum == G_MAXUINT8)
 736         desc = g_strdup_printf (">= %s", lower);
 737       else
 738         desc = g_strdup_printf ("[%s,%s]", lower, upper);
 739       g_free (lower);
 740       g_free (upper);
 741     }
 742   else if (G_IS_PARAM_SPEC_INT (spec))
 743     {
 744       GParamSpecInt *pspec = G_PARAM_SPEC_INT (spec);
 745 
 746       lower = describe_signed_constant (sizeof(gint), pspec->minimum);
 747       upper = describe_signed_constant (sizeof(gint), pspec->maximum);
 748       if (pspec->minimum == G_MININT && pspec->maximum == G_MAXINT)
 749         desc = g_strdup ("");
 750       else if (pspec->minimum == G_MININT)
 751         desc = g_strdup_printf ("<= %s", upper);
 752       else if (pspec->maximum == G_MAXINT)
 753         desc = g_strdup_printf (">= %s", lower);
 754       else
 755         desc = g_strdup_printf ("[%s,%s]", lower, upper);
 756       g_free (lower);
 757       g_free (upper);
 758     }
 759   else if (G_IS_PARAM_SPEC_UINT (spec))
 760     {
 761       GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (spec);
 762 
 763       lower = describe_unsigned_constant (sizeof(guint), pspec->minimum);
 764       upper = describe_unsigned_constant (sizeof(guint), pspec->maximum);
 765       if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT)
 766         desc = g_strdup ("");
 767       else if (pspec->minimum == 0)
 768         desc = g_strdup_printf ("<= %s", upper);
 769       else if (pspec->maximum == G_MAXUINT)
 770         desc = g_strdup_printf (">= %s", lower);
 771       else
 772         desc = g_strdup_printf ("[%s,%s]", lower, upper);
 773       g_free (lower);
 774       g_free (upper);
 775     }
 776   else if (G_IS_PARAM_SPEC_LONG (spec))
 777     {
 778       GParamSpecLong *pspec = G_PARAM_SPEC_LONG (spec);
 779 
 780       lower = describe_signed_constant (sizeof(glong), pspec->minimum);
 781       upper = describe_signed_constant (sizeof(glong), pspec->maximum);
 782       if (pspec->minimum == G_MINLONG && pspec->maximum == G_MAXLONG)
 783         desc = g_strdup ("");
 784       else if (pspec->minimum == G_MINLONG)
 785         desc = g_strdup_printf ("<= %s", upper);
 786       else if (pspec->maximum == G_MAXLONG)
 787         desc = g_strdup_printf (">= %s", lower);
 788       else
 789         desc = g_strdup_printf ("[%s,%s]", lower, upper);
 790       g_free (lower);
 791       g_free (upper);
 792     }
 793   else if (G_IS_PARAM_SPEC_ULONG (spec))
 794     {
 795       GParamSpecULong *pspec = G_PARAM_SPEC_ULONG (spec);
 796 
 797       lower = describe_unsigned_constant (sizeof(gulong), pspec->minimum);
 798       upper = describe_unsigned_constant (sizeof(gulong), pspec->maximum);
 799       if (pspec->minimum == 0 && pspec->maximum == G_MAXULONG)
 800         desc = g_strdup ("");
 801       else if (pspec->minimum == 0)
 802         desc = g_strdup_printf ("<= %s", upper);
 803       else if (pspec->maximum == G_MAXULONG)
 804         desc = g_strdup_printf (">= %s", lower);
 805       else
 806         desc = g_strdup_printf ("[%s,%s]", lower, upper);
 807       g_free (lower);
 808       g_free (upper);
 809     }
 810   else if (G_IS_PARAM_SPEC_INT64 (spec))
 811     {
 812       GParamSpecInt64 *pspec = G_PARAM_SPEC_INT64 (spec);
 813 
 814       lower = describe_signed_constant (sizeof(gint64), pspec->minimum);
 815       upper = describe_signed_constant (sizeof(gint64), pspec->maximum);
 816       if (pspec->minimum == G_MININT64 && pspec->maximum == G_MAXINT64)
 817         desc = g_strdup ("");
 818       else if (pspec->minimum == G_MININT64)
 819         desc = g_strdup_printf ("<= %s", upper);
 820       else if (pspec->maximum == G_MAXINT64)
 821         desc = g_strdup_printf (">= %s", lower);
 822       else
 823         desc = g_strdup_printf ("[%s,%s]", lower, upper);
 824       g_free (lower);
 825       g_free (upper);
 826     }
 827   else if (G_IS_PARAM_SPEC_UINT64 (spec))
 828     {
 829       GParamSpecUInt64 *pspec = G_PARAM_SPEC_UINT64 (spec);
 830 
 831       lower = describe_unsigned_constant (sizeof(guint64), pspec->minimum);
 832       upper = describe_unsigned_constant (sizeof(guint64), pspec->maximum);
 833       if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT64)
 834         desc = g_strdup ("");
 835       else if (pspec->minimum == 0)
 836         desc = g_strdup_printf ("<= %s", upper);
 837       else if (pspec->maximum == G_MAXUINT64)
 838         desc = g_strdup_printf (">= %s", lower);
 839       else
 840         desc = g_strdup_printf ("[%s,%s]", lower, upper);
 841       g_free (lower);
 842       g_free (upper);
 843     }
 844   else if (G_IS_PARAM_SPEC_FLOAT (spec))
 845     {
 846       GParamSpecFloat *pspec = G_PARAM_SPEC_FLOAT (spec);
 847 
 848       lower = describe_double_constant (pspec->minimum);
 849       upper = describe_double_constant (pspec->maximum);
 850       if (GTKDOC_COMPARE_FLOAT (pspec->minimum, -G_MAXFLOAT))
 851         {
 852           if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXFLOAT))
 853             desc = g_strdup ("");
 854           else
 855             desc = g_strdup_printf ("<= %s", upper);
 856         }
 857       else if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXFLOAT))
 858         desc = g_strdup_printf (">= %s", lower);
 859       else
 860         desc = g_strdup_printf ("[%s,%s]", lower, upper);
 861       g_free (lower);
 862       g_free (upper);
 863     }
 864   else if (G_IS_PARAM_SPEC_DOUBLE (spec))
 865     {
 866       GParamSpecDouble *pspec = G_PARAM_SPEC_DOUBLE (spec);
 867 
 868       lower = describe_double_constant (pspec->minimum);
 869       upper = describe_double_constant (pspec->maximum);
 870       if (GTKDOC_COMPARE_FLOAT (pspec->minimum, -G_MAXDOUBLE))
 871         {
 872           if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXDOUBLE))
 873             desc = g_strdup ("");
 874           else
 875             desc = g_strdup_printf ("<= %s", upper);
 876         }
 877       else if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXDOUBLE))
 878         desc = g_strdup_printf (">= %s", lower);
 879       else
 880         desc = g_strdup_printf ("[%s,%s]", lower, upper);
 881       g_free (lower);
 882       g_free (upper);
 883     }
 884 #if GLIB_CHECK_VERSION (2, 12, 0)
 885   else if (G_IS_PARAM_SPEC_GTYPE (spec))
 886     {
 887       GParamSpecGType *pspec = G_PARAM_SPEC_GTYPE (spec);
 888       gboolean is_pointer;
 889 
 890       desc = g_strdup (get_type_name (pspec->is_a_type, &is_pointer));
 891     }
 892 #endif
 893 #if GLIB_CHECK_VERSION (2, 25, 9)
 894   else if (G_IS_PARAM_SPEC_VARIANT (spec))
 895     {
 896       GParamSpecVariant *pspec = G_PARAM_SPEC_VARIANT (spec);
 897       gchar *variant_type;
 898 
 899       variant_type = g_variant_type_dup_string (pspec->type);
 900       desc = g_strdup_printf ("GVariant<%s>", variant_type);
 901       g_free (variant_type);
 902     }
 903 #endif
 904   else
 905     {
 906       desc = g_strdup ("");
 907     }
 908 
 909   return desc;
 910 }
 911 
 912 static gchar*
 913 describe_default (GParamSpec *spec)
 914 {
 915   gchar *desc;
 916 
 917   if (G_IS_PARAM_SPEC_CHAR (spec))
 918     {
 919       GParamSpecChar *pspec = G_PARAM_SPEC_CHAR (spec);
 920 
 921       desc = g_strdup_printf ("%d", pspec->default_value);
 922     }
 923   else if (G_IS_PARAM_SPEC_UCHAR (spec))
 924     {
 925       GParamSpecUChar *pspec = G_PARAM_SPEC_UCHAR (spec);
 926 
 927       desc = g_strdup_printf ("%u", pspec->default_value);
 928     }
 929   else if (G_IS_PARAM_SPEC_BOOLEAN (spec))
 930     {
 931       GParamSpecBoolean *pspec = G_PARAM_SPEC_BOOLEAN (spec);
 932 
 933       desc = g_strdup_printf ("%s", pspec->default_value ? "TRUE" : "FALSE");
 934     }
 935   else if (G_IS_PARAM_SPEC_INT (spec))
 936     {
 937       GParamSpecInt *pspec = G_PARAM_SPEC_INT (spec);
 938 
 939       desc = g_strdup_printf ("%d", pspec->default_value);
 940     }
 941   else if (G_IS_PARAM_SPEC_UINT (spec))
 942     {
 943       GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (spec);
 944 
 945       desc = g_strdup_printf ("%u", pspec->default_value);
 946     }
 947   else if (G_IS_PARAM_SPEC_LONG (spec))
 948     {
 949       GParamSpecLong *pspec = G_PARAM_SPEC_LONG (spec);
 950 
 951       desc = g_strdup_printf ("%ld", pspec->default_value);
 952     }
 953   else if (G_IS_PARAM_SPEC_LONG (spec))
 954     {
 955       GParamSpecULong *pspec = G_PARAM_SPEC_ULONG (spec);
 956 
 957       desc = g_strdup_printf ("%lu", pspec->default_value);
 958     }
 959   else if (G_IS_PARAM_SPEC_INT64 (spec))
 960     {
 961       GParamSpecInt64 *pspec = G_PARAM_SPEC_INT64 (spec);
 962 
 963       desc = g_strdup_printf ("%" G_GINT64_FORMAT, pspec->default_value);
 964     }
 965   else if (G_IS_PARAM_SPEC_UINT64 (spec))
 966     {
 967       GParamSpecUInt64 *pspec = G_PARAM_SPEC_UINT64 (spec);
 968 
 969       desc = g_strdup_printf ("%" G_GUINT64_FORMAT, pspec->default_value);
 970     }
 971   else if (G_IS_PARAM_SPEC_UNICHAR (spec))
 972     {
 973       GParamSpecUnichar *pspec = G_PARAM_SPEC_UNICHAR (spec);
 974 
 975       if (g_unichar_isprint (pspec->default_value))
 976         desc = g_strdup_printf ("'%c'", pspec->default_value);
 977       else
 978         desc = g_strdup_printf ("%u", pspec->default_value);
 979     }
 980   else if (G_IS_PARAM_SPEC_ENUM (spec))
 981     {
 982       GParamSpecEnum *pspec = G_PARAM_SPEC_ENUM (spec);
 983 
 984       GEnumValue *value = g_enum_get_value (pspec->enum_class, pspec->default_value);
 985       if (value)
 986         desc = g_strdup_printf ("%s", value->value_name);
 987       else
 988         desc = g_strdup_printf ("%d", pspec->default_value);
 989     }
 990   else if (G_IS_PARAM_SPEC_FLAGS (spec))
 991     {
 992       GParamSpecFlags *pspec = G_PARAM_SPEC_FLAGS (spec);
 993       guint default_value;
 994       GString *acc;
 995 
 996       default_value = pspec->default_value;
 997       acc = g_string_new ("");
 998 
 999       while (default_value)
1000         {
1001           GFlagsValue *value = g_flags_get_first_value (pspec->flags_class, default_value);
1002 
1003           if (!value)
1004             break;
1005 
1006           if (acc->len > 0)
1007             g_string_append (acc, "|");
1008           g_string_append (acc, value->value_name);
1009 
1010           default_value &= ~value->value;
1011         }
1012 
1013       if (default_value == 0)
1014         desc = g_string_free (acc, FALSE);
1015       else
1016         {
1017           desc = g_strdup_printf ("%d", pspec->default_value);
1018           g_string_free (acc, TRUE);
1019         }
1020     }
1021   else if (G_IS_PARAM_SPEC_FLOAT (spec))
1022     {
1023       GParamSpecFloat *pspec = G_PARAM_SPEC_FLOAT (spec);
1024 
1025       /* make sure floats are output with a decimal dot irrespective of
1026        * current locale. Use formatd since we want human-readable numbers
1027        * and do not need the exact same bit representation when deserialising */
1028       desc = g_malloc0 (G_ASCII_DTOSTR_BUF_SIZE);
1029       g_ascii_formatd (desc, G_ASCII_DTOSTR_BUF_SIZE, "%g",
1030           pspec->default_value);
1031     }
1032   else if (G_IS_PARAM_SPEC_DOUBLE (spec))
1033     {
1034       GParamSpecDouble *pspec = G_PARAM_SPEC_DOUBLE (spec);
1035 
1036       /* make sure floats are output with a decimal dot irrespective of
1037        * current locale. Use formatd since we want human-readable numbers
1038        * and do not need the exact same bit representation when deserialising */
1039       desc = g_malloc0 (G_ASCII_DTOSTR_BUF_SIZE);
1040       g_ascii_formatd (desc, G_ASCII_DTOSTR_BUF_SIZE, "%g",
1041           pspec->default_value);
1042     }
1043   else if (G_IS_PARAM_SPEC_STRING (spec))
1044     {
1045       GParamSpecString *pspec = G_PARAM_SPEC_STRING (spec);
1046 
1047       if (pspec->default_value)
1048         {
1049           gchar *esc = g_strescape (pspec->default_value, NULL);
1050 
1051           desc = g_strdup_printf ("\"%s\"", esc);
1052 
1053           g_free (esc);
1054         }
1055       else
1056         desc = g_strdup_printf ("NULL");
1057     }
1058 #if GLIB_CHECK_VERSION (2, 25, 9)
1059   else if (G_IS_PARAM_SPEC_VARIANT (spec))
1060     {
1061       GParamSpecVariant *pspec = G_PARAM_SPEC_VARIANT (spec);
1062 
1063       if (pspec->default_value)
1064         desc = g_variant_print (pspec->default_value, TRUE);
1065       else
1066         desc = g_strdup ("NULL");
1067     }
1068 #endif
1069   else
1070     {
1071       desc = g_strdup ("");
1072     }
1073 
1074   return desc;
1075 }
1076 
1077 
1078 static void
1079 output_object_args (FILE *fp, GType object_type)
1080 {
1081   gpointer class;
1082   const gchar *object_class_name;
1083   guint arg;
1084   gchar flags[16], *pos;
1085   GParamSpec **properties;
1086   guint n_properties;
1087   gboolean child_prop;
1088   gboolean style_prop;
1089   gboolean is_pointer;
1090   const gchar *type_name;
1091   gchar *type_desc;
1092   gchar *default_value;
1093 
1094   if (G_TYPE_IS_OBJECT (object_type))
1095     {
1096       class = g_type_class_peek (object_type);
1097       if (!class)
1098         return;
1099 
1100       properties = g_object_class_list_properties (class, &n_properties);
1101     }
1102 #if GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 3)
1103   else if (G_TYPE_IS_INTERFACE (object_type))
1104     {
1105       class = g_type_default_interface_ref (object_type);
1106 
1107       if (!class)
1108         return;
1109 
1110       properties = g_object_interface_list_properties (class, &n_properties);
1111     }
1112 #endif
1113   else
1114     return;
1115 
1116   object_class_name = g_type_name (object_type);
1117 
1118   child_prop = FALSE;
CID 10034 - DEADCODE
After this line, the value of "style_prop" is equal to 0.
Assigning: "style_prop" = "0".
1119   style_prop = FALSE;
1120 
1121   while (TRUE) {
1122     qsort (properties, n_properties, sizeof (GParamSpec *), compare_param_specs);
1123     for (arg = 0; arg < n_properties; arg++)
1124       {
1125         GParamSpec *spec = properties[arg];
1126         const gchar *nick, *blurb, *dot;
1127 
1128         if (spec->owner_type != object_type)
1129           continue;
1130 
1131         pos = flags;
1132         /* We use one-character flags for simplicity. */
1133         if (child_prop && !style_prop)
1134              *pos++ = 'c';
CID 10034 - DEADCODE
On this path, the condition "style_prop" cannot be true.
After this line, the value of "style_prop" is equal to 0.
Noticing condition "style_prop".
1135         if (style_prop)
CID 10034 - DEADCODE
Execution cannot reach this statement "*pos++ = 's';".
1136              *pos++ = 's';
1137         if (spec->flags & G_PARAM_READABLE)
1138            *pos++ = 'r';
1139         if (spec->flags & G_PARAM_WRITABLE)
1140           *pos++ = 'w';
1141         if (spec->flags & G_PARAM_CONSTRUCT)
1142           *pos++ = 'x';
1143         if (spec->flags & G_PARAM_CONSTRUCT_ONLY)
1144           *pos++ = 'X';
1145         *pos = 0;
1146 
1147         nick = g_param_spec_get_nick (spec);
1148         blurb = g_param_spec_get_blurb (spec);
1149 
1150         dot = "";
1151         if (blurb) {
1152           int str_len = strlen (blurb);
1153           if (str_len > 0  && blurb[str_len - 1] != '.')
1154             dot = ".";
1155         }
1156 
1157         type_desc = describe_type (spec);
1158         default_value = describe_default (spec);
1159         type_name = get_type_name (spec->value_type, &is_pointer);
1160         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",
1161                  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);
1162         g_free (type_desc);
1163         g_free (default_value);
1164       }
1165 
1166     g_free (properties);
1167 
1168 #ifdef GTK_IS_CONTAINER_CLASS
1169     if (!child_prop && GTK_IS_CONTAINER_CLASS (class)) {
1170       properties = gtk_container_class_list_child_properties (class, &n_properties);
1171       child_prop = TRUE;
1172       continue;
1173     }
1174 #endif
1175 
1176 #ifdef GTK_IS_CELL_AREA_CLASS
1177     if (!child_prop && GTK_IS_CELL_AREA_CLASS (class)) {
1178       properties = gtk_cell_area_class_list_cell_properties (class, &n_properties);
1179       child_prop = TRUE;
1180       continue;
1181     }
1182 #endif
1183 
1184 #ifdef GTK_IS_WIDGET_CLASS
1185 #if GTK_CHECK_VERSION(2,1,0)
1186     if (!style_prop && GTK_IS_WIDGET_CLASS (class)) {
1187       properties = gtk_widget_class_list_style_properties (GTK_WIDGET_CLASS (class), &n_properties);
1188       style_prop = TRUE;
1189       continue;
1190     }
1191 #endif
1192 #endif
1193 
1194     break;
1195   }
1196 }