xref: /aosp_15_r20/external/libxkbcommon/tools/compile-keymap.c (revision 2b949d0487e80d67f1fda82db69e101e761f8064)
1*2b949d04SAndroid Build Coastguard Worker /*
2*2b949d04SAndroid Build Coastguard Worker  * Copyright © 2018 Red Hat, Inc.
3*2b949d04SAndroid Build Coastguard Worker  *
4*2b949d04SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*2b949d04SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*2b949d04SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*2b949d04SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*2b949d04SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*2b949d04SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*2b949d04SAndroid Build Coastguard Worker  *
11*2b949d04SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*2b949d04SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*2b949d04SAndroid Build Coastguard Worker  * Software.
14*2b949d04SAndroid Build Coastguard Worker  *
15*2b949d04SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*2b949d04SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*2b949d04SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*2b949d04SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*2b949d04SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*2b949d04SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21*2b949d04SAndroid Build Coastguard Worker  * DEALINGS IN THE SOFTWARE.
22*2b949d04SAndroid Build Coastguard Worker  */
23*2b949d04SAndroid Build Coastguard Worker 
24*2b949d04SAndroid Build Coastguard Worker #include "config.h"
25*2b949d04SAndroid Build Coastguard Worker 
26*2b949d04SAndroid Build Coastguard Worker #include <assert.h>
27*2b949d04SAndroid Build Coastguard Worker #include <errno.h>
28*2b949d04SAndroid Build Coastguard Worker #include <getopt.h>
29*2b949d04SAndroid Build Coastguard Worker #include <stdio.h>
30*2b949d04SAndroid Build Coastguard Worker #include <stdbool.h>
31*2b949d04SAndroid Build Coastguard Worker #include <stdlib.h>
32*2b949d04SAndroid Build Coastguard Worker #include <string.h>
33*2b949d04SAndroid Build Coastguard Worker 
34*2b949d04SAndroid Build Coastguard Worker #include "xkbcommon/xkbcommon.h"
35*2b949d04SAndroid Build Coastguard Worker #if ENABLE_PRIVATE_APIS
36*2b949d04SAndroid Build Coastguard Worker #include "xkbcomp/xkbcomp-priv.h"
37*2b949d04SAndroid Build Coastguard Worker #include "xkbcomp/rules.h"
38*2b949d04SAndroid Build Coastguard Worker #endif
39*2b949d04SAndroid Build Coastguard Worker #include "tools-common.h"
40*2b949d04SAndroid Build Coastguard Worker 
41*2b949d04SAndroid Build Coastguard Worker #define DEFAULT_INCLUDE_PATH_PLACEHOLDER "__defaults__"
42*2b949d04SAndroid Build Coastguard Worker 
43*2b949d04SAndroid Build Coastguard Worker static bool verbose = false;
44*2b949d04SAndroid Build Coastguard Worker static enum output_format {
45*2b949d04SAndroid Build Coastguard Worker     FORMAT_RMLVO,
46*2b949d04SAndroid Build Coastguard Worker     FORMAT_KEYMAP,
47*2b949d04SAndroid Build Coastguard Worker     FORMAT_KCCGST,
48*2b949d04SAndroid Build Coastguard Worker     FORMAT_KEYMAP_FROM_XKB,
49*2b949d04SAndroid Build Coastguard Worker } output_format = FORMAT_KEYMAP;
50*2b949d04SAndroid Build Coastguard Worker static const char *includes[64];
51*2b949d04SAndroid Build Coastguard Worker static size_t num_includes = 0;
52*2b949d04SAndroid Build Coastguard Worker 
53*2b949d04SAndroid Build Coastguard Worker static void
usage(char ** argv)54*2b949d04SAndroid Build Coastguard Worker usage(char **argv)
55*2b949d04SAndroid Build Coastguard Worker {
56*2b949d04SAndroid Build Coastguard Worker     printf("Usage: %s [OPTIONS]\n"
57*2b949d04SAndroid Build Coastguard Worker            "\n"
58*2b949d04SAndroid Build Coastguard Worker            "Compile the given RMLVO to a keymap and print it\n"
59*2b949d04SAndroid Build Coastguard Worker            "\n"
60*2b949d04SAndroid Build Coastguard Worker            "Options:\n"
61*2b949d04SAndroid Build Coastguard Worker            " --verbose\n"
62*2b949d04SAndroid Build Coastguard Worker            "    Enable verbose debugging output\n"
63*2b949d04SAndroid Build Coastguard Worker #if ENABLE_PRIVATE_APIS
64*2b949d04SAndroid Build Coastguard Worker            " --kccgst\n"
65*2b949d04SAndroid Build Coastguard Worker            "    Print a keymap which only includes the KcCGST component names instead of the full keymap\n"
66*2b949d04SAndroid Build Coastguard Worker #endif
67*2b949d04SAndroid Build Coastguard Worker            " --rmlvo\n"
68*2b949d04SAndroid Build Coastguard Worker            "    Print the full RMLVO with the defaults filled in for missing elements\n"
69*2b949d04SAndroid Build Coastguard Worker            " --from-xkb\n"
70*2b949d04SAndroid Build Coastguard Worker            "    Load the XKB file from stdin, ignore RMLVO options.\n"
71*2b949d04SAndroid Build Coastguard Worker #if ENABLE_PRIVATE_APIS
72*2b949d04SAndroid Build Coastguard Worker            "    This option must not be used with --kccgst.\n"
73*2b949d04SAndroid Build Coastguard Worker #endif
74*2b949d04SAndroid Build Coastguard Worker            " --include\n"
75*2b949d04SAndroid Build Coastguard Worker            "    Add the given path to the include path list. This option is\n"
76*2b949d04SAndroid Build Coastguard Worker            "    order-dependent, include paths given first are searched first.\n"
77*2b949d04SAndroid Build Coastguard Worker            "    If an include path is given, the default include path list is\n"
78*2b949d04SAndroid Build Coastguard Worker            "    not used. Use --include-defaults to add the default include\n"
79*2b949d04SAndroid Build Coastguard Worker            "    paths\n"
80*2b949d04SAndroid Build Coastguard Worker            " --include-defaults\n"
81*2b949d04SAndroid Build Coastguard Worker            "    Add the default set of include directories.\n"
82*2b949d04SAndroid Build Coastguard Worker            "    This option is order-dependent, include paths given first\n"
83*2b949d04SAndroid Build Coastguard Worker            "    are searched first.\n"
84*2b949d04SAndroid Build Coastguard Worker            "\n"
85*2b949d04SAndroid Build Coastguard Worker            "XKB-specific options:\n"
86*2b949d04SAndroid Build Coastguard Worker            " --rules <rules>\n"
87*2b949d04SAndroid Build Coastguard Worker            "    The XKB ruleset (default: '%s')\n"
88*2b949d04SAndroid Build Coastguard Worker            " --model <model>\n"
89*2b949d04SAndroid Build Coastguard Worker            "    The XKB model (default: '%s')\n"
90*2b949d04SAndroid Build Coastguard Worker            " --layout <layout>\n"
91*2b949d04SAndroid Build Coastguard Worker            "    The XKB layout (default: '%s')\n"
92*2b949d04SAndroid Build Coastguard Worker            " --variant <variant>\n"
93*2b949d04SAndroid Build Coastguard Worker            "    The XKB layout variant (default: '%s')\n"
94*2b949d04SAndroid Build Coastguard Worker            " --options <options>\n"
95*2b949d04SAndroid Build Coastguard Worker            "    The XKB options (default: '%s')\n"
96*2b949d04SAndroid Build Coastguard Worker            "\n",
97*2b949d04SAndroid Build Coastguard Worker            argv[0], DEFAULT_XKB_RULES,
98*2b949d04SAndroid Build Coastguard Worker            DEFAULT_XKB_MODEL, DEFAULT_XKB_LAYOUT,
99*2b949d04SAndroid Build Coastguard Worker            DEFAULT_XKB_VARIANT ? DEFAULT_XKB_VARIANT : "<none>",
100*2b949d04SAndroid Build Coastguard Worker            DEFAULT_XKB_OPTIONS ? DEFAULT_XKB_OPTIONS : "<none>");
101*2b949d04SAndroid Build Coastguard Worker }
102*2b949d04SAndroid Build Coastguard Worker 
103*2b949d04SAndroid Build Coastguard Worker static bool
parse_options(int argc,char ** argv,struct xkb_rule_names * names)104*2b949d04SAndroid Build Coastguard Worker parse_options(int argc, char **argv, struct xkb_rule_names *names)
105*2b949d04SAndroid Build Coastguard Worker {
106*2b949d04SAndroid Build Coastguard Worker     enum options {
107*2b949d04SAndroid Build Coastguard Worker         OPT_VERBOSE,
108*2b949d04SAndroid Build Coastguard Worker         OPT_KCCGST,
109*2b949d04SAndroid Build Coastguard Worker         OPT_RMLVO,
110*2b949d04SAndroid Build Coastguard Worker         OPT_FROM_XKB,
111*2b949d04SAndroid Build Coastguard Worker         OPT_INCLUDE,
112*2b949d04SAndroid Build Coastguard Worker         OPT_INCLUDE_DEFAULTS,
113*2b949d04SAndroid Build Coastguard Worker         OPT_RULES,
114*2b949d04SAndroid Build Coastguard Worker         OPT_MODEL,
115*2b949d04SAndroid Build Coastguard Worker         OPT_LAYOUT,
116*2b949d04SAndroid Build Coastguard Worker         OPT_VARIANT,
117*2b949d04SAndroid Build Coastguard Worker         OPT_OPTION,
118*2b949d04SAndroid Build Coastguard Worker     };
119*2b949d04SAndroid Build Coastguard Worker     static struct option opts[] = {
120*2b949d04SAndroid Build Coastguard Worker         {"help",             no_argument,            0, 'h'},
121*2b949d04SAndroid Build Coastguard Worker         {"verbose",          no_argument,            0, OPT_VERBOSE},
122*2b949d04SAndroid Build Coastguard Worker #if ENABLE_PRIVATE_APIS
123*2b949d04SAndroid Build Coastguard Worker         {"kccgst",           no_argument,            0, OPT_KCCGST},
124*2b949d04SAndroid Build Coastguard Worker #endif
125*2b949d04SAndroid Build Coastguard Worker         {"rmlvo",            no_argument,            0, OPT_RMLVO},
126*2b949d04SAndroid Build Coastguard Worker         {"from-xkb",         no_argument,            0, OPT_FROM_XKB},
127*2b949d04SAndroid Build Coastguard Worker         {"include",          required_argument,      0, OPT_INCLUDE},
128*2b949d04SAndroid Build Coastguard Worker         {"include-defaults", no_argument,            0, OPT_INCLUDE_DEFAULTS},
129*2b949d04SAndroid Build Coastguard Worker         {"rules",            required_argument,      0, OPT_RULES},
130*2b949d04SAndroid Build Coastguard Worker         {"model",            required_argument,      0, OPT_MODEL},
131*2b949d04SAndroid Build Coastguard Worker         {"layout",           required_argument,      0, OPT_LAYOUT},
132*2b949d04SAndroid Build Coastguard Worker         {"variant",          required_argument,      0, OPT_VARIANT},
133*2b949d04SAndroid Build Coastguard Worker         {"options",          required_argument,      0, OPT_OPTION},
134*2b949d04SAndroid Build Coastguard Worker         {0, 0, 0, 0},
135*2b949d04SAndroid Build Coastguard Worker     };
136*2b949d04SAndroid Build Coastguard Worker 
137*2b949d04SAndroid Build Coastguard Worker     while (1) {
138*2b949d04SAndroid Build Coastguard Worker         int c;
139*2b949d04SAndroid Build Coastguard Worker         int option_index = 0;
140*2b949d04SAndroid Build Coastguard Worker         c = getopt_long(argc, argv, "h", opts, &option_index);
141*2b949d04SAndroid Build Coastguard Worker         if (c == -1)
142*2b949d04SAndroid Build Coastguard Worker             break;
143*2b949d04SAndroid Build Coastguard Worker 
144*2b949d04SAndroid Build Coastguard Worker         switch (c) {
145*2b949d04SAndroid Build Coastguard Worker         case 'h':
146*2b949d04SAndroid Build Coastguard Worker             usage(argv);
147*2b949d04SAndroid Build Coastguard Worker             exit(0);
148*2b949d04SAndroid Build Coastguard Worker         case OPT_VERBOSE:
149*2b949d04SAndroid Build Coastguard Worker             verbose = true;
150*2b949d04SAndroid Build Coastguard Worker             break;
151*2b949d04SAndroid Build Coastguard Worker         case OPT_KCCGST:
152*2b949d04SAndroid Build Coastguard Worker             output_format = FORMAT_KCCGST;
153*2b949d04SAndroid Build Coastguard Worker             break;
154*2b949d04SAndroid Build Coastguard Worker         case OPT_RMLVO:
155*2b949d04SAndroid Build Coastguard Worker             output_format = FORMAT_RMLVO;
156*2b949d04SAndroid Build Coastguard Worker             break;
157*2b949d04SAndroid Build Coastguard Worker         case OPT_FROM_XKB:
158*2b949d04SAndroid Build Coastguard Worker             output_format = FORMAT_KEYMAP_FROM_XKB;
159*2b949d04SAndroid Build Coastguard Worker             break;
160*2b949d04SAndroid Build Coastguard Worker         case OPT_INCLUDE:
161*2b949d04SAndroid Build Coastguard Worker             if (num_includes >= ARRAY_SIZE(includes)) {
162*2b949d04SAndroid Build Coastguard Worker                 fprintf(stderr, "error: too many includes\n");
163*2b949d04SAndroid Build Coastguard Worker                 exit(EXIT_INVALID_USAGE);
164*2b949d04SAndroid Build Coastguard Worker             }
165*2b949d04SAndroid Build Coastguard Worker             includes[num_includes++] = optarg;
166*2b949d04SAndroid Build Coastguard Worker             break;
167*2b949d04SAndroid Build Coastguard Worker         case OPT_INCLUDE_DEFAULTS:
168*2b949d04SAndroid Build Coastguard Worker             if (num_includes >= ARRAY_SIZE(includes)) {
169*2b949d04SAndroid Build Coastguard Worker                 fprintf(stderr, "error: too many includes\n");
170*2b949d04SAndroid Build Coastguard Worker                 exit(EXIT_INVALID_USAGE);
171*2b949d04SAndroid Build Coastguard Worker             }
172*2b949d04SAndroid Build Coastguard Worker             includes[num_includes++] = DEFAULT_INCLUDE_PATH_PLACEHOLDER;
173*2b949d04SAndroid Build Coastguard Worker             break;
174*2b949d04SAndroid Build Coastguard Worker         case OPT_RULES:
175*2b949d04SAndroid Build Coastguard Worker             names->rules = optarg;
176*2b949d04SAndroid Build Coastguard Worker             break;
177*2b949d04SAndroid Build Coastguard Worker         case OPT_MODEL:
178*2b949d04SAndroid Build Coastguard Worker             names->model = optarg;
179*2b949d04SAndroid Build Coastguard Worker             break;
180*2b949d04SAndroid Build Coastguard Worker         case OPT_LAYOUT:
181*2b949d04SAndroid Build Coastguard Worker             names->layout = optarg;
182*2b949d04SAndroid Build Coastguard Worker             break;
183*2b949d04SAndroid Build Coastguard Worker         case OPT_VARIANT:
184*2b949d04SAndroid Build Coastguard Worker             names->variant = optarg;
185*2b949d04SAndroid Build Coastguard Worker             break;
186*2b949d04SAndroid Build Coastguard Worker         case OPT_OPTION:
187*2b949d04SAndroid Build Coastguard Worker             names->options = optarg;
188*2b949d04SAndroid Build Coastguard Worker             break;
189*2b949d04SAndroid Build Coastguard Worker         default:
190*2b949d04SAndroid Build Coastguard Worker             usage(argv);
191*2b949d04SAndroid Build Coastguard Worker             exit(EXIT_INVALID_USAGE);
192*2b949d04SAndroid Build Coastguard Worker         }
193*2b949d04SAndroid Build Coastguard Worker 
194*2b949d04SAndroid Build Coastguard Worker     }
195*2b949d04SAndroid Build Coastguard Worker 
196*2b949d04SAndroid Build Coastguard Worker     return true;
197*2b949d04SAndroid Build Coastguard Worker }
198*2b949d04SAndroid Build Coastguard Worker 
199*2b949d04SAndroid Build Coastguard Worker static bool
print_rmlvo(struct xkb_context * ctx,const struct xkb_rule_names * rmlvo)200*2b949d04SAndroid Build Coastguard Worker print_rmlvo(struct xkb_context *ctx, const struct xkb_rule_names *rmlvo)
201*2b949d04SAndroid Build Coastguard Worker {
202*2b949d04SAndroid Build Coastguard Worker     printf("rules: \"%s\"\nmodel: \"%s\"\nlayout: \"%s\"\nvariant: \"%s\"\noptions: \"%s\"\n",
203*2b949d04SAndroid Build Coastguard Worker            rmlvo->rules, rmlvo->model, rmlvo->layout,
204*2b949d04SAndroid Build Coastguard Worker            rmlvo->variant ? rmlvo->variant : "",
205*2b949d04SAndroid Build Coastguard Worker            rmlvo->options ? rmlvo->options : "");
206*2b949d04SAndroid Build Coastguard Worker     return true;
207*2b949d04SAndroid Build Coastguard Worker }
208*2b949d04SAndroid Build Coastguard Worker 
209*2b949d04SAndroid Build Coastguard Worker static bool
print_kccgst(struct xkb_context * ctx,const struct xkb_rule_names * rmlvo)210*2b949d04SAndroid Build Coastguard Worker print_kccgst(struct xkb_context *ctx, const struct xkb_rule_names *rmlvo)
211*2b949d04SAndroid Build Coastguard Worker {
212*2b949d04SAndroid Build Coastguard Worker #if ENABLE_PRIVATE_APIS
213*2b949d04SAndroid Build Coastguard Worker         struct xkb_component_names kccgst;
214*2b949d04SAndroid Build Coastguard Worker 
215*2b949d04SAndroid Build Coastguard Worker         if (!xkb_components_from_rules(ctx, rmlvo, &kccgst))
216*2b949d04SAndroid Build Coastguard Worker             return false;
217*2b949d04SAndroid Build Coastguard Worker 
218*2b949d04SAndroid Build Coastguard Worker         printf("xkb_keymap {\n"
219*2b949d04SAndroid Build Coastguard Worker                "  xkb_keycodes { include \"%s\" };\n"
220*2b949d04SAndroid Build Coastguard Worker                "  xkb_types { include \"%s\" };\n"
221*2b949d04SAndroid Build Coastguard Worker                "  xkb_compat { include \"%s\" };\n"
222*2b949d04SAndroid Build Coastguard Worker                "  xkb_symbols { include \"%s\" };\n"
223*2b949d04SAndroid Build Coastguard Worker                "};\n",
224*2b949d04SAndroid Build Coastguard Worker                kccgst.keycodes, kccgst.types, kccgst.compat, kccgst.symbols);
225*2b949d04SAndroid Build Coastguard Worker         free(kccgst.keycodes);
226*2b949d04SAndroid Build Coastguard Worker         free(kccgst.types);
227*2b949d04SAndroid Build Coastguard Worker         free(kccgst.compat);
228*2b949d04SAndroid Build Coastguard Worker         free(kccgst.symbols);
229*2b949d04SAndroid Build Coastguard Worker 
230*2b949d04SAndroid Build Coastguard Worker         return true;
231*2b949d04SAndroid Build Coastguard Worker #else
232*2b949d04SAndroid Build Coastguard Worker         return false;
233*2b949d04SAndroid Build Coastguard Worker #endif
234*2b949d04SAndroid Build Coastguard Worker }
235*2b949d04SAndroid Build Coastguard Worker 
236*2b949d04SAndroid Build Coastguard Worker static bool
print_keymap(struct xkb_context * ctx,const struct xkb_rule_names * rmlvo)237*2b949d04SAndroid Build Coastguard Worker print_keymap(struct xkb_context *ctx, const struct xkb_rule_names *rmlvo)
238*2b949d04SAndroid Build Coastguard Worker {
239*2b949d04SAndroid Build Coastguard Worker     struct xkb_keymap *keymap;
240*2b949d04SAndroid Build Coastguard Worker 
241*2b949d04SAndroid Build Coastguard Worker     keymap = xkb_keymap_new_from_names(ctx, rmlvo, XKB_KEYMAP_COMPILE_NO_FLAGS);
242*2b949d04SAndroid Build Coastguard Worker     if (keymap == NULL)
243*2b949d04SAndroid Build Coastguard Worker         return false;
244*2b949d04SAndroid Build Coastguard Worker 
245*2b949d04SAndroid Build Coastguard Worker     printf("%s\n", xkb_keymap_get_as_string(keymap,
246*2b949d04SAndroid Build Coastguard Worker                                             XKB_KEYMAP_FORMAT_TEXT_V1));
247*2b949d04SAndroid Build Coastguard Worker     xkb_keymap_unref(keymap);
248*2b949d04SAndroid Build Coastguard Worker     return true;
249*2b949d04SAndroid Build Coastguard Worker }
250*2b949d04SAndroid Build Coastguard Worker 
251*2b949d04SAndroid Build Coastguard Worker static bool
print_keymap_from_file(struct xkb_context * ctx)252*2b949d04SAndroid Build Coastguard Worker print_keymap_from_file(struct xkb_context *ctx)
253*2b949d04SAndroid Build Coastguard Worker {
254*2b949d04SAndroid Build Coastguard Worker     struct xkb_keymap *keymap = NULL;
255*2b949d04SAndroid Build Coastguard Worker     char *keymap_string = NULL;
256*2b949d04SAndroid Build Coastguard Worker     FILE *file = NULL;
257*2b949d04SAndroid Build Coastguard Worker     bool success = false;
258*2b949d04SAndroid Build Coastguard Worker 
259*2b949d04SAndroid Build Coastguard Worker     file = tmpfile();
260*2b949d04SAndroid Build Coastguard Worker     if (!file) {
261*2b949d04SAndroid Build Coastguard Worker         fprintf(stderr, "Failed to create tmpfile\n");
262*2b949d04SAndroid Build Coastguard Worker         goto out;
263*2b949d04SAndroid Build Coastguard Worker     }
264*2b949d04SAndroid Build Coastguard Worker 
265*2b949d04SAndroid Build Coastguard Worker     while (true) {
266*2b949d04SAndroid Build Coastguard Worker         char buf[4096];
267*2b949d04SAndroid Build Coastguard Worker         size_t len;
268*2b949d04SAndroid Build Coastguard Worker 
269*2b949d04SAndroid Build Coastguard Worker         len = fread(buf, 1, sizeof(buf), stdin);
270*2b949d04SAndroid Build Coastguard Worker         if (ferror(stdin)) {
271*2b949d04SAndroid Build Coastguard Worker             fprintf(stderr, "Failed to read from stdin\n");
272*2b949d04SAndroid Build Coastguard Worker             goto out;
273*2b949d04SAndroid Build Coastguard Worker         }
274*2b949d04SAndroid Build Coastguard Worker         if (len > 0) {
275*2b949d04SAndroid Build Coastguard Worker             size_t wlen = fwrite(buf, 1, len, file);
276*2b949d04SAndroid Build Coastguard Worker             if (wlen != len) {
277*2b949d04SAndroid Build Coastguard Worker                 fprintf(stderr, "Failed to write to tmpfile\n");
278*2b949d04SAndroid Build Coastguard Worker                 goto out;
279*2b949d04SAndroid Build Coastguard Worker             }
280*2b949d04SAndroid Build Coastguard Worker         }
281*2b949d04SAndroid Build Coastguard Worker         if (feof(stdin))
282*2b949d04SAndroid Build Coastguard Worker             break;
283*2b949d04SAndroid Build Coastguard Worker     }
284*2b949d04SAndroid Build Coastguard Worker     fseek(file, 0, SEEK_SET);
285*2b949d04SAndroid Build Coastguard Worker     keymap = xkb_keymap_new_from_file(ctx, file,
286*2b949d04SAndroid Build Coastguard Worker                                       XKB_KEYMAP_FORMAT_TEXT_V1, 0);
287*2b949d04SAndroid Build Coastguard Worker     if (!keymap) {
288*2b949d04SAndroid Build Coastguard Worker         fprintf(stderr, "Couldn't create xkb keymap\n");
289*2b949d04SAndroid Build Coastguard Worker         goto out;
290*2b949d04SAndroid Build Coastguard Worker     }
291*2b949d04SAndroid Build Coastguard Worker 
292*2b949d04SAndroid Build Coastguard Worker     keymap_string = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
293*2b949d04SAndroid Build Coastguard Worker     if (!keymap_string) {
294*2b949d04SAndroid Build Coastguard Worker         fprintf(stderr, "Couldn't get the keymap string\n");
295*2b949d04SAndroid Build Coastguard Worker         goto out;
296*2b949d04SAndroid Build Coastguard Worker     }
297*2b949d04SAndroid Build Coastguard Worker 
298*2b949d04SAndroid Build Coastguard Worker     fputs(keymap_string, stdout);
299*2b949d04SAndroid Build Coastguard Worker     success = true;
300*2b949d04SAndroid Build Coastguard Worker 
301*2b949d04SAndroid Build Coastguard Worker out:
302*2b949d04SAndroid Build Coastguard Worker     if (file)
303*2b949d04SAndroid Build Coastguard Worker         fclose(file);
304*2b949d04SAndroid Build Coastguard Worker     xkb_keymap_unref(keymap);
305*2b949d04SAndroid Build Coastguard Worker     free(keymap_string);
306*2b949d04SAndroid Build Coastguard Worker 
307*2b949d04SAndroid Build Coastguard Worker     return success;
308*2b949d04SAndroid Build Coastguard Worker }
309*2b949d04SAndroid Build Coastguard Worker 
310*2b949d04SAndroid Build Coastguard Worker int
main(int argc,char ** argv)311*2b949d04SAndroid Build Coastguard Worker main(int argc, char **argv)
312*2b949d04SAndroid Build Coastguard Worker {
313*2b949d04SAndroid Build Coastguard Worker     struct xkb_context *ctx;
314*2b949d04SAndroid Build Coastguard Worker     struct xkb_rule_names names = {
315*2b949d04SAndroid Build Coastguard Worker         .rules = DEFAULT_XKB_RULES,
316*2b949d04SAndroid Build Coastguard Worker         .model = DEFAULT_XKB_MODEL,
317*2b949d04SAndroid Build Coastguard Worker         /* layout and variant are tied together, so we either get user-supplied for
318*2b949d04SAndroid Build Coastguard Worker          * both or default for both, see below */
319*2b949d04SAndroid Build Coastguard Worker         .layout = NULL,
320*2b949d04SAndroid Build Coastguard Worker         .variant = NULL,
321*2b949d04SAndroid Build Coastguard Worker         .options = DEFAULT_XKB_OPTIONS,
322*2b949d04SAndroid Build Coastguard Worker     };
323*2b949d04SAndroid Build Coastguard Worker     int rc = 1;
324*2b949d04SAndroid Build Coastguard Worker 
325*2b949d04SAndroid Build Coastguard Worker     if (argc <= 1) {
326*2b949d04SAndroid Build Coastguard Worker         usage(argv);
327*2b949d04SAndroid Build Coastguard Worker         return EXIT_INVALID_USAGE;
328*2b949d04SAndroid Build Coastguard Worker     }
329*2b949d04SAndroid Build Coastguard Worker 
330*2b949d04SAndroid Build Coastguard Worker     if (!parse_options(argc, argv, &names))
331*2b949d04SAndroid Build Coastguard Worker         return EXIT_INVALID_USAGE;
332*2b949d04SAndroid Build Coastguard Worker 
333*2b949d04SAndroid Build Coastguard Worker     /* Now fill in the layout */
334*2b949d04SAndroid Build Coastguard Worker     if (!names.layout || !*names.layout) {
335*2b949d04SAndroid Build Coastguard Worker         if (names.variant && *names.variant) {
336*2b949d04SAndroid Build Coastguard Worker             fprintf(stderr, "Error: a variant requires a layout\n");
337*2b949d04SAndroid Build Coastguard Worker             return EXIT_INVALID_USAGE;
338*2b949d04SAndroid Build Coastguard Worker         }
339*2b949d04SAndroid Build Coastguard Worker         names.layout = DEFAULT_XKB_LAYOUT;
340*2b949d04SAndroid Build Coastguard Worker         names.variant = DEFAULT_XKB_VARIANT;
341*2b949d04SAndroid Build Coastguard Worker     }
342*2b949d04SAndroid Build Coastguard Worker 
343*2b949d04SAndroid Build Coastguard Worker     ctx = xkb_context_new(XKB_CONTEXT_NO_DEFAULT_INCLUDES);
344*2b949d04SAndroid Build Coastguard Worker     assert(ctx);
345*2b949d04SAndroid Build Coastguard Worker 
346*2b949d04SAndroid Build Coastguard Worker     if (verbose) {
347*2b949d04SAndroid Build Coastguard Worker         xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_DEBUG);
348*2b949d04SAndroid Build Coastguard Worker         xkb_context_set_log_verbosity(ctx, 10);
349*2b949d04SAndroid Build Coastguard Worker     }
350*2b949d04SAndroid Build Coastguard Worker 
351*2b949d04SAndroid Build Coastguard Worker     if (num_includes == 0)
352*2b949d04SAndroid Build Coastguard Worker         includes[num_includes++] = DEFAULT_INCLUDE_PATH_PLACEHOLDER;
353*2b949d04SAndroid Build Coastguard Worker 
354*2b949d04SAndroid Build Coastguard Worker     for (size_t i = 0; i < num_includes; i++) {
355*2b949d04SAndroid Build Coastguard Worker         const char *include = includes[i];
356*2b949d04SAndroid Build Coastguard Worker         if (strcmp(include, DEFAULT_INCLUDE_PATH_PLACEHOLDER) == 0)
357*2b949d04SAndroid Build Coastguard Worker             xkb_context_include_path_append_default(ctx);
358*2b949d04SAndroid Build Coastguard Worker         else
359*2b949d04SAndroid Build Coastguard Worker             xkb_context_include_path_append(ctx, include);
360*2b949d04SAndroid Build Coastguard Worker     }
361*2b949d04SAndroid Build Coastguard Worker 
362*2b949d04SAndroid Build Coastguard Worker     if (output_format == FORMAT_RMLVO) {
363*2b949d04SAndroid Build Coastguard Worker         rc = print_rmlvo(ctx, &names) ? EXIT_SUCCESS : EXIT_FAILURE;
364*2b949d04SAndroid Build Coastguard Worker     } else if (output_format == FORMAT_KEYMAP) {
365*2b949d04SAndroid Build Coastguard Worker         rc = print_keymap(ctx, &names) ? EXIT_SUCCESS : EXIT_FAILURE;
366*2b949d04SAndroid Build Coastguard Worker     } else if (output_format == FORMAT_KCCGST) {
367*2b949d04SAndroid Build Coastguard Worker         rc = print_kccgst(ctx, &names) ? EXIT_SUCCESS : EXIT_FAILURE;
368*2b949d04SAndroid Build Coastguard Worker     } else if (output_format == FORMAT_KEYMAP_FROM_XKB) {
369*2b949d04SAndroid Build Coastguard Worker         rc = print_keymap_from_file(ctx);
370*2b949d04SAndroid Build Coastguard Worker     }
371*2b949d04SAndroid Build Coastguard Worker 
372*2b949d04SAndroid Build Coastguard Worker     xkb_context_unref(ctx);
373*2b949d04SAndroid Build Coastguard Worker 
374*2b949d04SAndroid Build Coastguard Worker     return rc;
375*2b949d04SAndroid Build Coastguard Worker }
376