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