Package version up
[platform/upstream/libxkbcommon.git] / tools / registry-list.c
1 /*
2  * Copyright © 2020 Red Hat, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23
24 #include "config.h"
25
26 #include <assert.h>
27 #include <stdio.h>
28 #include <getopt.h>
29
30 #include "xkbcommon/xkbregistry.h"
31
32 static void
33 usage(const char *progname, FILE *fp)
34 {
35     fprintf(fp,
36             "Usage: %s [OPTIONS] [/path/to/xkb_base_directory [/path2]...]\n"
37             "\n"
38             "Options:\n"
39             "  --verbose, -v .......... Increase verbosity, use multiple times for debugging output\n"
40             "  --ruleset=foo .......... Load the 'foo' ruleset\n"
41             "  --skip-default-paths ... Do not load the default XKB paths\n"
42             "  --load-exotic .......... Load the exotic (extra) rulesets\n"
43             "  --help ................. Print this help and exit\n"
44             "\n"
45             "Trailing arguments are treated as XKB base directory installations.\n",
46             progname);
47 }
48
49 int
50 main(int argc, char **argv)
51 {
52     int rc = 1;
53     struct rxkb_context *ctx = NULL;
54     struct rxkb_model *m;
55     struct rxkb_layout *l;
56     struct rxkb_option_group *g;
57     enum rxkb_context_flags flags = RXKB_CONTEXT_NO_FLAGS;
58     bool load_defaults = true;
59     int verbosity = 0;
60     const char *ruleset = DEFAULT_XKB_RULES;
61
62     static const struct option opts[] = {
63         {"help",                no_argument,        0, 'h'},
64         {"verbose",             no_argument,        0, 'v'},
65         {"load-exotic",         no_argument,        0, 'e'},
66         {"skip-default-paths",  no_argument,        0, 'd'},
67         {"ruleset",             required_argument,  0, 'r'},
68         {0, 0, 0, 0},
69     };
70
71     while (1) {
72         int c;
73         int option_index = 0;
74
75         c = getopt_long(argc, argv, "hev", opts, &option_index);
76         if (c == -1)
77             break;
78
79         switch (c) {
80             case 'h':
81                 usage(argv[0], stdout);
82                 return 0;
83             case '?':
84                 usage(argv[0], stderr);
85                 return EXIT_INVALID_USAGE;
86             case 'd':
87                 load_defaults = false;
88                 break;
89             case 'e':
90                 flags |= RXKB_CONTEXT_LOAD_EXOTIC_RULES;
91                 break;
92             case 'r':
93                 ruleset = optarg;
94                 break;
95             case 'v':
96                 verbosity++;
97                 break;
98         }
99     }
100
101     if (optind < argc)
102         flags |= RXKB_CONTEXT_NO_DEFAULT_INCLUDES;
103
104     ctx = rxkb_context_new(flags);
105     assert(ctx);
106
107     switch (verbosity) {
108         case 0:
109             rxkb_context_set_log_level(ctx, RXKB_LOG_LEVEL_ERROR);
110             break;
111         case 1:
112             rxkb_context_set_log_level(ctx, RXKB_LOG_LEVEL_INFO);
113             break;
114         default:
115             rxkb_context_set_log_level(ctx, RXKB_LOG_LEVEL_DEBUG);
116             break;
117     }
118
119     if (optind < argc) {
120         for (int i = optind; i < argc; i++) {
121             if (!rxkb_context_include_path_append(ctx, argv[i])) {
122                 fprintf(stderr, "Failed to append include path '%s'\n",
123                         argv[i]);
124                 goto err;
125             }
126         }
127
128         if (load_defaults) {
129             if (!rxkb_context_include_path_append_default(ctx)) {
130                 fprintf(stderr, "Failed to include default paths.\n");
131                 goto err;
132             }
133         }
134     }
135     if (!rxkb_context_parse(ctx, ruleset)) {
136         fprintf(stderr, "Failed to parse XKB descriptions.\n");
137         goto err;
138     }
139
140     printf("models:\n");
141     m = rxkb_model_first(ctx);
142     assert(m); /* Empty model list is usually a bug or a bad xml file */
143     while (m) {
144         const char *vendor = rxkb_model_get_vendor(m);
145         printf("- name: %s\n"
146                "  vendor: %s\n"
147                "  description: %s\n",
148                rxkb_model_get_name(m),
149                vendor ? vendor : "''",
150                rxkb_model_get_description(m));
151         m = rxkb_model_next(m);
152     }
153
154     printf("\n");
155     printf("layouts:\n");
156     l = rxkb_layout_first(ctx);
157     assert(l); /* Empty layout list is usually a bug or a bad xml file */
158     while (l) {
159         struct rxkb_iso639_code *iso639;
160         struct rxkb_iso3166_code *iso3166;
161         const char *variant = rxkb_layout_get_variant(l);
162         const char *brief = rxkb_layout_get_brief(l);
163
164         printf("- layout: '%s'\n"
165                "  variant: '%s'\n"
166                "  brief: '%s'\n"
167                "  description: %s\n",
168                rxkb_layout_get_name(l),
169                variant ? variant : "",
170                brief ? brief : "''",
171                rxkb_layout_get_description(l));
172
173         printf("  iso639: [");
174         iso639 = rxkb_layout_get_iso639_first(l);
175         if (iso639) {
176             const char *sep = "";
177             while (iso639) {
178                 printf("%s'%s'", sep, rxkb_iso639_code_get_code(iso639));
179                 iso639 = rxkb_iso639_code_next(iso639);
180                 sep = ", ";
181             }
182         }
183         printf("]\n");
184         printf("  iso3166: [");
185         iso3166 = rxkb_layout_get_iso3166_first(l);
186         if (iso3166) {
187             const char *sep = "";
188             while (iso3166) {
189                 printf("%s'%s'", sep, rxkb_iso3166_code_get_code(iso3166));
190                 iso3166 = rxkb_iso3166_code_next(iso3166);
191                 sep = ", ";
192             }
193         }
194         printf("]\n");
195         l = rxkb_layout_next(l);
196     }
197     printf("\n");
198     printf("option_groups:\n");
199     g = rxkb_option_group_first(ctx);
200     assert(g); /* Empty option goups list is usually a bug or a bad xml file */
201     while (g) {
202         struct rxkb_option *o;
203
204         printf("- name: '%s'\n"
205                "  description: %s\n"
206                "  allows_multiple: %s\n"
207                "  options:\n",
208                rxkb_option_group_get_name(g),
209                rxkb_option_group_get_description(g),
210                rxkb_option_group_allows_multiple(g) ? "true" : "false");
211
212         o = rxkb_option_first(g);
213         assert(o); /* Empty option list is usually a bug or a bad xml file */
214         while (o) {
215             const char *brief = rxkb_option_get_brief(o);
216
217             printf("  - name: '%s'\n"
218                    "    brief: '%s'\n"
219                    "    description: '%s'\n",
220                    rxkb_option_get_name(o),
221                    brief ? brief : "",
222                    rxkb_option_get_description(o));
223             o = rxkb_option_next(o);
224         }
225
226         g = rxkb_option_group_next(g);
227     }
228
229     rc = 0;
230
231 err:
232     if (ctx)
233         rxkb_context_unref(ctx);
234
235     return rc;
236 }