| /* GObject - GLib Type, Object, Parameter and Signal Library | |
| * Copyright (C) 1998-1999, 2000-2001 Tim Janik and Red Hat, Inc. | |
| * | |
| * SPDX-License-Identifier: LGPL-2.1-or-later | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General | |
| * Public License along with this library; if not, see <http://www.gnu.org/licenses/>. | |
| */ | |
| #include "config.h" | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <sys/stat.h> | |
| #include <fcntl.h> | |
| #include <glib-object.h> | |
| #include <glib/gprintf.h> | |
| static gchar *indent_inc = NULL; | |
| static guint spacing = 1; | |
| static FILE *f_out = NULL; | |
| static GType root = 0; | |
| static gboolean recursion = TRUE; | |
| #define O_SPACE " " | |
| #define O_ESPACE "" | |
| #define O_BRANCH "├" | |
| #define O_VLINE "│" | |
| #define O_LLEAF "└" | |
| #define O_KEY_FILL "_" | |
| static void | |
| show_nodes (GType type, | |
| GType sibling, | |
| const gchar *indent) | |
| { | |
| GType *children; | |
| size_t i; | |
| if (!type) | |
| return; | |
| children = g_type_children (type, NULL); | |
| g_fprintf (f_out, "%s%s%s%s", | |
| indent, | |
| sibling ? O_BRANCH : (type != root ? O_LLEAF : O_SPACE), | |
| O_ESPACE, | |
| g_type_name (type)); | |
| for (i = strlen (g_type_name (type)); i <= strlen (indent_inc); i++) | |
| fputs (O_KEY_FILL, f_out); | |
| fputc ('\n', f_out); | |
| if (children && recursion) | |
| { | |
| gchar *new_indent; | |
| GType *child; | |
| if (sibling) | |
| new_indent = g_strconcat (indent, O_VLINE, indent_inc, NULL); | |
| else | |
| new_indent = g_strconcat (indent, O_SPACE, indent_inc, NULL); | |
| for (child = children; *child; child++) | |
| show_nodes (child[0], child[1], new_indent); | |
| g_free (new_indent); | |
| } | |
| g_free (children); | |
| } | |
| static gint | |
| help (const gchar *arg) | |
| { | |
| g_fprintf (stdout, "usage: gobject-query <qualifier> [-r <type>] [-{i|b} \"\"] [-s #] [-{h|x|y}]\n"); | |
| g_fprintf (stdout, " -r specify root type\n"); | |
| g_fprintf (stdout, " -n don't descend type tree\n"); | |
| g_fprintf (stdout, " -h show help\n"); | |
| g_fprintf (stdout, " -b specify indent string\n"); | |
| g_fprintf (stdout, " -i specify incremental indent string\n"); | |
| g_fprintf (stdout, " -s specify line spacing\n"); | |
| g_fprintf (stdout, "qualifiers:\n"); | |
| g_fprintf (stdout, " froots iterate over fundamental roots\n"); | |
| g_fprintf (stdout, " tree print type tree\n"); | |
| return arg != NULL; | |
| } | |
| int | |
| main (gint argc, | |
| gchar *argv[]) | |
| { | |
| GLogLevelFlags fatal_mask; | |
| gboolean gen_froots = 0; | |
| gboolean gen_tree = 0; | |
| gint i; | |
| const gchar *iindent = ""; | |
| f_out = stdout; | |
| fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK); | |
| fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL; | |
| g_log_set_always_fatal (fatal_mask); | |
| root = G_TYPE_OBJECT; | |
| for (i = 1; i < argc; i++) | |
| { | |
| if (strcmp ("-s", argv[i]) == 0) | |
| { | |
| i++; | |
| if (i < argc) | |
| spacing = atoi (argv[i]); | |
| } | |
| else if (strcmp ("-i", argv[i]) == 0) | |
| { | |
| i++; | |
| if (i < argc) | |
| { | |
| char *p; | |
| guint n; | |
| p = argv[i]; | |
| while (*p) | |
| p++; | |
| n = p - argv[i]; | |
| indent_inc = g_new (gchar, n * strlen (O_SPACE) + 1); | |
| *indent_inc = 0; | |
| while (n) | |
| { | |
| n--; | |
| strcpy (indent_inc, O_SPACE); | |
| } | |
| } | |
| } | |
| else if (strcmp ("-b", argv[i]) == 0) | |
| { | |
| i++; | |
| if (i < argc) | |
| iindent = argv[i]; | |
| } | |
| else if (strcmp ("-r", argv[i]) == 0) | |
| { | |
| i++; | |
| if (i < argc) | |
| root = g_type_from_name (argv[i]); | |
| } | |
| else if (strcmp ("-n", argv[i]) == 0) | |
| { | |
| recursion = FALSE; | |
| } | |
| else if (strcmp ("froots", argv[i]) == 0) | |
| { | |
| gen_froots = 1; | |
| } | |
| else if (strcmp ("tree", argv[i]) == 0) | |
| { | |
| gen_tree = 1; | |
| } | |
| else if (strcmp ("--version", argv[i]) == 0) | |
| { | |
| g_print (PACKAGE_VERSION "\n"); | |
| return 0; | |
| } | |
| else if (strcmp ("-h", argv[i]) == 0 || | |
| strcmp ("--help", argv[i]) == 0) | |
| { | |
| return help (NULL); | |
| } | |
| else | |
| return help (argv[i]); | |
| } | |
| if (!gen_froots && !gen_tree) | |
| return help ((argc > 0) ? argv[i-1] : NULL); | |
| if (!indent_inc) | |
| { | |
| indent_inc = g_new (gchar, strlen (O_SPACE) + 1); | |
| *indent_inc = 0; | |
| strcpy (indent_inc, O_SPACE); | |
| } | |
| if (gen_tree) | |
| show_nodes (root, 0, iindent); | |
| if (gen_froots) | |
| { | |
| root = ~0; | |
| for (i = 0; i <= G_TYPE_FUNDAMENTAL_MAX; i += G_TYPE_MAKE_FUNDAMENTAL (1)) | |
| { | |
| const gchar *name = g_type_name (i); | |
| GType sibling = i + G_TYPE_MAKE_FUNDAMENTAL (1); | |
| if (sibling > G_TYPE_FUNDAMENTAL_MAX || g_type_name (sibling) == NULL) | |
| sibling = 0; | |
| if (name) | |
| show_nodes (i, sibling, iindent); | |
| } | |
| } | |
| return 0; | |
| } |