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 = ¶m_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 }