interactive-wayland: fallback to ftruncate() if needed
[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             "\n"
44             "Trailing arguments are treated as XKB base directory installations.\n",
45             progname);
46 }
47
48 int
49 main(int argc, char **argv)
50 {
51     int rc = 1;
52     struct rxkb_context *ctx = NULL;
53     struct rxkb_model *m;
54     struct rxkb_layout *l;
55     struct rxkb_option_group *g;
56     enum rxkb_context_flags flags = RXKB_CONTEXT_NO_FLAGS;
57     bool load_defaults = true;
58     int verbosity = 0;
59     const char *ruleset = DEFAULT_XKB_RULES;
60
61     static const struct option opts[] = {
62         {"help",                no_argument,        0, 'h'},
63         {"verbose",             no_argument,        0, 'v'},
64         {"load-exotic",         no_argument,        0, 'e'},
65         {"skip-default-paths",  no_argument,        0, 'd'},
66         {"ruleset",             required_argument,  0, 'r'},
67         {0, 0, 0, 0},
68     };
69
70     while (1) {
71         int c;
72         int option_index = 0;
73
74         c = getopt_long(argc, argv, "hev", opts, &option_index);
75         if (c == -1)
76             break;
77
78         switch (c) {
79             case 'h':
80                 usage(argv[0], stdout);
81                 return 0;
82             case '?':
83                 usage(argv[0], stderr);
84                 return EXIT_INVALID_USAGE;
85             case 'd':
86                 load_defaults = false;
87                 break;
88             case 'e':
89                 flags |= RXKB_CONTEXT_LOAD_EXOTIC_RULES;
90                 break;
91             case 'r':
92                 ruleset = optarg;
93                 break;
94             case 'v':
95                 verbosity++;
96                 break;
97         }
98     }
99
100     if (optind < argc)
101         flags |= RXKB_CONTEXT_NO_DEFAULT_INCLUDES;
102
103     ctx = rxkb_context_new(flags);
104     assert(ctx);
105
106     switch (verbosity) {
107         case 0:
108             rxkb_context_set_log_level(ctx, RXKB_LOG_LEVEL_ERROR);
109             break;
110         case 1:
111             rxkb_context_set_log_level(ctx, RXKB_LOG_LEVEL_INFO);
112             break;
113         default:
114             rxkb_context_set_log_level(ctx, RXKB_LOG_LEVEL_DEBUG);
115             break;
116     }
117
118     if (optind < argc) {
119         for (int i = optind; i < argc; i++) {
120             if (!rxkb_context_include_path_append(ctx, argv[i])) {
121                 fprintf(stderr, "Failed to append include path '%s'\n",
122                         argv[i]);
123                 goto err;
124             }
125         }
126
127         if (load_defaults) {
128             if (!rxkb_context_include_path_append_default(ctx)) {
129                 fprintf(stderr, "Failed to include default paths.\n");
130                 goto err;
131             }
132         }
133     }
134     if (!rxkb_context_parse(ctx, ruleset)) {
135         fprintf(stderr, "Failed to parse XKB descriptions.\n");
136         goto err;
137     }
138
139     printf("Models:\n");
140     m = rxkb_model_first(ctx);
141     assert(m); /* Empty model list is usually a bug or a bad xml file */
142     while (m) {
143         printf("- %s:%s:%s\n",
144                rxkb_model_get_name(m),
145                rxkb_model_get_vendor(m),
146                rxkb_model_get_description(m));
147         m = rxkb_model_next(m);
148     }
149
150     printf("\n");
151     printf("Layouts:\n");
152     l = rxkb_layout_first(ctx);
153     assert(l); /* Empty layout list is usually a bug or a bad xml file */
154     while (l) {
155         struct rxkb_iso639_code *iso639;
156         struct rxkb_iso3166_code *iso3166;
157         const char *variant = rxkb_layout_get_variant(l);
158         const char *brief = rxkb_layout_get_brief(l);
159         bool first;
160
161         printf("- %s%s%s%s:%s:%s",
162                rxkb_layout_get_name(l),
163                variant ? "(" : "",
164                variant ? variant : "",
165                variant ? ")" : "",
166                brief ? brief : "",
167                rxkb_layout_get_description(l));
168
169         iso639 = rxkb_layout_get_iso639_first(l);
170         if (iso639)
171             printf(":iso639-");
172         first = true;
173         while (iso639) {
174             printf("%s%s", first ? "" : ",", rxkb_iso639_code_get_code(iso639));
175             iso639 = rxkb_iso639_code_next(iso639);
176             first = false;
177         }
178         iso3166 = rxkb_layout_get_iso3166_first(l);
179         if (iso3166)
180             printf(":iso3166-");
181         first = true;
182         while (iso3166) {
183             printf("%s%s", first ? "" : ",", rxkb_iso3166_code_get_code(iso3166));
184             iso3166 = rxkb_iso3166_code_next(iso3166);
185             first = false;
186         }
187
188         printf("\n");
189         l = rxkb_layout_next(l);
190     }
191     printf("\n");
192     printf("Options:\n");
193     g = rxkb_option_group_first(ctx);
194     assert(g); /* Empty option goups list is usually a bug or a bad xml file */
195     while (g) {
196         struct rxkb_option *o;
197
198         printf("- %s:%s (%s)\n",
199                rxkb_option_group_get_name(g),
200                rxkb_option_group_get_description(g),
201                rxkb_option_group_allows_multiple(g) ? "multiple" : "single");
202
203         o = rxkb_option_first(g);
204         assert(o); /* Empty option list is usually a bug or a bad xml file */
205         while (o) {
206             const char *brief = rxkb_option_get_brief(o);
207
208             printf("  - %s:%s:%s\n",
209                    rxkb_option_get_name(o),
210                    brief ? brief : "",
211                    rxkb_option_get_description(o));
212             o = rxkb_option_next(o);
213         }
214
215         g = rxkb_option_group_next(g);
216     }
217
218     rc = 0;
219
220 err:
221     if (ctx)
222         rxkb_context_unref(ctx);
223
224     return rc;
225 }