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