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