| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738 |
- /*
- * Copyright © 2018 Red Hat, Inc.
- * SPDX-License-Identifier: MIT
- */
- #include "config.h"
- #include <assert.h>
- #include <errno.h>
- #include <getopt.h>
- #include <locale.h>
- #include <stdio.h>
- #include <stdbool.h>
- #include <stdlib.h>
- #include <string.h>
- #include "xkbcommon/xkbcommon-errors.h"
- #include "xkbcommon/xkbcommon.h"
- #include "tools-common.h"
- #include "src/utils.h"
- #include "src/keymap-formats.h"
- #define DEFAULT_INCLUDE_PATH_PLACEHOLDER "__defaults__"
- enum input_format {
- INPUT_FORMAT_AUTO = 0,
- INPUT_FORMAT_RMLVO,
- INPUT_FORMAT_KEYMAP
- };
- enum output_format {
- OUTPUT_FORMAT_KEYMAP = 0,
- OUTPUT_FORMAT_RMLVO,
- OUTPUT_FORMAT_KCCGST,
- OUTPUT_FORMAT_KCCGST_YAML,
- OUTPUT_FORMAT_MODMAPS,
- };
- static bool verbose = false;
- static const char *includes[64] = { 0 };
- static size_t num_includes = 0;
- static bool test = false;
- static void
- usage(FILE *file, const char *progname)
- {
- fprintf(file,
- "Usage: %s [OPTIONS]\n"
- "\n"
- "Compile the given input to a keymap and print it\n"
- "\n"
- "General options:\n"
- " --help\n"
- " Print this help and exit\n"
- " --version\n"
- " Print version information and exit\n"
- " --verbose\n"
- " Enable verbose debugging output\n"
- " --test\n"
- " Test compilation but do not print the keymap.\n"
- "\n"
- "Input options:\n"
- " --include\n"
- " Add the given path to the include path list. This option is\n"
- " order-dependent, include paths given first are searched first.\n"
- " If an include path is given, the default include path list is\n"
- " not used. Use --include-defaults to add the default include\n"
- " paths\n"
- " --include-defaults\n"
- " Add the default set of include directories.\n"
- " This option is order-dependent, include paths given first\n"
- " are searched first.\n"
- " --input-format <format>\n"
- " The keymap format to use for parsing (default: '%s')\n"
- " --format <format>\n"
- " The keymap format to use for both parsing and serializing\n"
- " --input-strict\n"
- " Parse using the strict mode.\n"
- " --strict\n"
- " Parse and serialize using the strict mode.\n"
- " --keymap <file>\n"
- " --from-xkb <file>\n"
- " Load the corresponding XKB file, ignore RMLVO options. If <file>\n"
- " is \"-\" or missing, then load from stdin."
- " This option must not be used with --kccgst.\n"
- " --rules <rules>\n"
- " The XKB ruleset (default: '%s')\n"
- " --model <model>\n"
- " The XKB model (default: '%s')\n"
- " --layout <layout>\n"
- " The XKB layout (default: '%s')\n"
- " --variant <variant>\n"
- " The XKB layout variant (default: '%s')\n"
- " --options <options>\n"
- " The XKB options (default: '%s')\n"
- " --enable-environment-names\n"
- " Allow to set the default RMLVO values via the following environment variables:\n"
- " - XKB_DEFAULT_RULES\n"
- " - XKB_DEFAULT_MODEL\n"
- " - XKB_DEFAULT_LAYOUT\n"
- " - XKB_DEFAULT_VARIANT\n"
- " - XKB_DEFAULT_OPTIONS\n"
- " Note that this option may affect the default values of the previous options.\n"
- " This option must not be used with --keymap.\n"
- "\n"
- "Output options:\n"
- " --output-format <format>\n"
- " The keymap format to use for serializing (default: same as input)\n"
- " --output-strict\n"
- " Serialize using the strict mode\n"
- " --no-pretty\n"
- " Do not pretty-print when serializing a keymap\n"
- " --drop-unused\n"
- " Disable unused bits serialization\n"
- " --explicit-defaults\n"
- " Force serializing default values\n"
- " --explicit-vmods\n"
- " Force serializing virtual modifiers encodings\n"
- " --explicit-keys\n"
- " Force serializing key values\n"
- " --explicit-values\n"
- " Force serializing all values\n"
- " --layouts-mask\n"
- " Hexadecimal mask of the layouts indices to select for serializing\n"
- " --kccgst\n"
- " Print a keymap which only includes the KcCGST component names instead of the full keymap\n"
- " --kccgst-yaml\n"
- " Print the KcCGST component names in YAML format\n"
- " --rmlvo\n"
- " Print the full RMLVO with the defaults filled in for missing elements, in YAML format\n"
- " --modmaps\n"
- " Print real and virtual key modmaps and modifiers encodings in YAML format\n"
- "\n",
- progname,
- xkb_keymap_get_format_label(DEFAULT_INPUT_KEYMAP_FORMAT),
- DEFAULT_XKB_RULES, DEFAULT_XKB_MODEL, DEFAULT_XKB_LAYOUT,
- DEFAULT_XKB_VARIANT ? DEFAULT_XKB_VARIANT : "<none>",
- DEFAULT_XKB_OPTIONS ? DEFAULT_XKB_OPTIONS : "<none>");
- }
- static inline bool
- is_incompatible_with_keymap_input(enum output_format format)
- {
- switch (format) {
- case OUTPUT_FORMAT_KCCGST:
- case OUTPUT_FORMAT_KCCGST_YAML:
- case OUTPUT_FORMAT_RMLVO:
- return true;
- default:
- return false;
- }
- }
- static bool
- parse_options(int argc, char **argv,
- enum input_format *input_format_out,
- enum output_format *output_format_out,
- enum xkb_keymap_format *keymap_input_format,
- enum xkb_keymap_format *keymap_output_format,
- enum xkb_keymap_compile_flags *compile_flags,
- enum xkb_keymap_serialize_flags *serialize_flags,
- xkb_layout_mask_t *layout_mask,
- bool *use_env_names,
- char **path, struct xkb_rule_names *names)
- {
- enum input_format input_format = INPUT_FORMAT_AUTO;
- enum output_format output_format = OUTPUT_FORMAT_KEYMAP;
- enum options {
- /* General */
- OPT_VERBOSE,
- OPT_TEST,
- /* Input */
- OPT_INCLUDE,
- OPT_INCLUDE_DEFAULTS,
- OPT_KEYMAP,
- OPT_ENABLE_ENV_NAMES,
- OPT_KEYMAP_INPUT_FORMAT,
- OPT_KEYMAP_FORMAT,
- OPT_KEYMAP_INPUT_STRICT,
- OPT_KEYMAP_STRICT,
- OPT_RULES,
- OPT_MODEL,
- OPT_LAYOUT,
- OPT_VARIANT,
- OPT_OPTION,
- /* Output */
- OPT_KEYMAP_OUTPUT_FORMAT,
- OPT_KEYMAP_OUTPUT_STRICT,
- OPT_KEYMAP_NO_PRETTY,
- OPT_KEYMAP_DROP_UNUSED,
- OPT_KEYMAP_EXPLICIT_DEFAULTS,
- OPT_KEYMAP_EXPLICIT_VMODS,
- OPT_KEYMAP_EXPLICIT_KEYS,
- OPT_KEYMAP_EXPLICIT,
- OPT_KEYMAP_LAYOUTS,
- OPT_KCCGST,
- OPT_KCCGST_YAML,
- OPT_RMLVO,
- OPT_MODMAPS,
- };
- static struct option opts[] = {
- /*
- * General
- */
- {"help", no_argument, 0, 'h'},
- {"version", no_argument, 0, 'V'},
- {"verbose", no_argument, 0, OPT_VERBOSE},
- {"test", no_argument, 0, OPT_TEST},
- /*
- * Input
- */
- {"include", required_argument, 0, OPT_INCLUDE},
- {"include-defaults", no_argument, 0, OPT_INCLUDE_DEFAULTS},
- {"keymap", optional_argument, 0, OPT_KEYMAP},
- /* Alias maintained for backward compatibility */
- {"from-xkb", optional_argument, 0, OPT_KEYMAP},
- {"input-strict", no_argument, 0, OPT_KEYMAP_INPUT_STRICT},
- {"strict", no_argument, 0, OPT_KEYMAP_STRICT},
- {"enable-environment-names", no_argument, 0, OPT_ENABLE_ENV_NAMES},
- {"input-format", required_argument, 0, OPT_KEYMAP_INPUT_FORMAT},
- {"format", required_argument, 0, OPT_KEYMAP_FORMAT},
- {"rules", required_argument, 0, OPT_RULES},
- {"model", required_argument, 0, OPT_MODEL},
- {"layout", required_argument, 0, OPT_LAYOUT},
- {"variant", required_argument, 0, OPT_VARIANT},
- {"options", required_argument, 0, OPT_OPTION},
- /*
- * Output
- */
- {"output-format", required_argument, 0, OPT_KEYMAP_OUTPUT_FORMAT},
- {"output-strict", no_argument, 0, OPT_KEYMAP_OUTPUT_STRICT},
- {"no-pretty", no_argument, 0, OPT_KEYMAP_NO_PRETTY},
- {"drop-unused", no_argument, 0, OPT_KEYMAP_DROP_UNUSED},
- {"explicit-defaults",no_argument, 0, OPT_KEYMAP_EXPLICIT_DEFAULTS},
- {"explicit-vmods", no_argument, 0, OPT_KEYMAP_EXPLICIT_VMODS},
- {"explicit-keys", no_argument, 0, OPT_KEYMAP_EXPLICIT_KEYS},
- {"explicit-values", no_argument, 0, OPT_KEYMAP_EXPLICIT},
- {"layouts-mask", required_argument, 0, OPT_KEYMAP_LAYOUTS},
- {"kccgst", no_argument, 0, OPT_KCCGST},
- {"kccgst-yaml", no_argument, 0, OPT_KCCGST_YAML},
- {"rmlvo", no_argument, 0, OPT_RMLVO},
- {"modmaps", no_argument, 0, OPT_MODMAPS},
- {0, 0, 0, 0},
- };
- *use_env_names = false;
- int option_index = 0;
- while (1) {
- option_index = 0;
- int c = getopt_long(argc, argv, "hV", opts, &option_index);
- if (c == -1)
- break;
- switch (c) {
- /* General */
- case 'h':
- usage(stdout, argv[0]);
- exit(EXIT_SUCCESS);
- case 'V':
- printf("%s\n", LIBXKBCOMMON_VERSION);
- exit(EXIT_SUCCESS);
- case OPT_VERBOSE:
- verbose = true;
- break;
- case OPT_TEST:
- test = true;
- break;
- /* Input */
- case OPT_INCLUDE:
- if (num_includes >= ARRAY_SIZE(includes))
- goto too_many_includes;
- includes[num_includes++] = optarg;
- break;
- case OPT_INCLUDE_DEFAULTS:
- if (num_includes >= ARRAY_SIZE(includes))
- goto too_many_includes;
- includes[num_includes++] = DEFAULT_INCLUDE_PATH_PLACEHOLDER;
- break;
- case OPT_KEYMAP:
- if (*use_env_names)
- goto keymap_env_error;
- if (input_format == INPUT_FORMAT_RMLVO)
- goto input_format_error;
- if (is_incompatible_with_keymap_input(output_format))
- goto output_incompatible_with_keymap_input_error;
- input_format = INPUT_FORMAT_KEYMAP;
- /* Optional arguments require `=`, but we want to make this
- * requirement optional too, so that both `--keymap=xxx` and
- * `--keymap xxx` work. */
- if (!optarg && argv[optind] &&
- (argv[optind][0] != '-' || strcmp(argv[optind], "-") == 0 )) {
- *path = argv[optind++];
- } else {
- *path = optarg;
- }
- break;
- case OPT_ENABLE_ENV_NAMES:
- if (input_format == INPUT_FORMAT_KEYMAP)
- goto keymap_env_error;
- *use_env_names = true;
- input_format = INPUT_FORMAT_RMLVO;
- break;
- case OPT_KEYMAP_INPUT_FORMAT:
- *keymap_input_format = xkb_keymap_parse_format(optarg);
- if (!(*keymap_input_format)) {
- fprintf(stderr, "ERROR: invalid --input-format: \"%s\"\n", optarg);
- usage(stderr, argv[0]);
- exit(EXIT_INVALID_USAGE);
- }
- break;
- case OPT_KEYMAP_OUTPUT_FORMAT:
- *keymap_output_format = xkb_keymap_parse_format(optarg);
- if (!(*keymap_output_format)) {
- fprintf(stderr, "ERROR: invalid --output-format: \"%s\"\n", optarg);
- usage(stderr, argv[0]);
- exit(EXIT_INVALID_USAGE);
- }
- break;
- case OPT_KEYMAP_FORMAT:
- *keymap_input_format = xkb_keymap_parse_format(optarg);
- if (!(*keymap_input_format)) {
- fprintf(stderr, "ERROR: invalid --format: \"%s\"\n", optarg);
- usage(stderr, argv[0]);
- exit(EXIT_INVALID_USAGE);
- }
- *keymap_output_format = *keymap_input_format;
- break;
- case OPT_KEYMAP_INPUT_STRICT:
- *compile_flags |= XKB_KEYMAP_COMPILE_STRICT_MODE;
- break;
- case OPT_KEYMAP_OUTPUT_STRICT:
- *compile_flags |= XKB_KEYMAP_SERIALIZE_STRICT_MODE;
- break;
- case OPT_KEYMAP_STRICT:
- *compile_flags |= XKB_KEYMAP_COMPILE_STRICT_MODE;
- *serialize_flags |= XKB_KEYMAP_SERIALIZE_STRICT_MODE;
- break;
- case OPT_KEYMAP_NO_PRETTY:
- *serialize_flags &= ~XKB_KEYMAP_SERIALIZE_PRETTY;
- break;
- case OPT_KEYMAP_DROP_UNUSED:
- *serialize_flags &= ~XKB_KEYMAP_SERIALIZE_KEEP_UNUSED;
- break;
- case OPT_KEYMAP_EXPLICIT_DEFAULTS:
- *serialize_flags |= XKB_KEYMAP_SERIALIZE_EXPLICIT_DEFAULT_VALUES;
- break;
- case OPT_KEYMAP_EXPLICIT_VMODS:
- *serialize_flags |= XKB_KEYMAP_SERIALIZE_EXPLICIT_VMODS;
- break;
- case OPT_KEYMAP_EXPLICIT_KEYS:
- *serialize_flags |= XKB_KEYMAP_SERIALIZE_EXPLICIT_KEY_VALUES;
- break;
- case OPT_KEYMAP_EXPLICIT:
- *serialize_flags |= XKB_KEYMAP_SERIALIZE_EXPLICIT_DEFAULT_VALUES
- | XKB_KEYMAP_SERIALIZE_EXPLICIT_VMODS
- | XKB_KEYMAP_SERIALIZE_EXPLICIT_KEY_VALUES;
- break;
- case OPT_KEYMAP_LAYOUTS: {
- uint32_t mask = 0;
- if (!tools_parse_mask(optarg, TOOLS_ARG_REQUIRED, &mask))
- goto invalid_usage;
- *layout_mask = mask;
- break;
- }
- case OPT_RULES:
- if (input_format == INPUT_FORMAT_KEYMAP)
- goto input_format_error;
- names->rules = optarg;
- input_format = INPUT_FORMAT_RMLVO;
- break;
- case OPT_MODEL:
- if (input_format == INPUT_FORMAT_KEYMAP)
- goto input_format_error;
- names->model = optarg;
- input_format = INPUT_FORMAT_RMLVO;
- break;
- case OPT_LAYOUT:
- if (input_format == INPUT_FORMAT_KEYMAP)
- goto input_format_error;
- names->layout = optarg;
- input_format = INPUT_FORMAT_RMLVO;
- break;
- case OPT_VARIANT:
- if (input_format == INPUT_FORMAT_KEYMAP)
- goto input_format_error;
- names->variant = optarg;
- input_format = INPUT_FORMAT_RMLVO;
- break;
- case OPT_OPTION:
- if (input_format == INPUT_FORMAT_KEYMAP)
- goto input_format_error;
- names->options = optarg;
- input_format = INPUT_FORMAT_RMLVO;
- break;
- /* Output */
- case OPT_KCCGST:
- assert(is_incompatible_with_keymap_input(OUTPUT_FORMAT_KCCGST));
- if (input_format == INPUT_FORMAT_KEYMAP)
- goto output_incompatible_with_keymap_input_error;
- if (output_format != OUTPUT_FORMAT_KEYMAP &&
- output_format != OUTPUT_FORMAT_KCCGST)
- goto output_format_error;
- output_format = OUTPUT_FORMAT_KCCGST;
- break;
- case OPT_KCCGST_YAML:
- assert(is_incompatible_with_keymap_input(OUTPUT_FORMAT_KCCGST_YAML));
- if (input_format == INPUT_FORMAT_KEYMAP)
- goto output_incompatible_with_keymap_input_error;
- if (output_format != OUTPUT_FORMAT_KEYMAP &&
- output_format != OUTPUT_FORMAT_KCCGST_YAML)
- goto output_format_error;
- output_format = OUTPUT_FORMAT_KCCGST_YAML;
- break;
- case OPT_RMLVO:
- assert(is_incompatible_with_keymap_input(OUTPUT_FORMAT_RMLVO));
- if (input_format == INPUT_FORMAT_KEYMAP)
- goto output_incompatible_with_keymap_input_error;
- if (output_format != OUTPUT_FORMAT_KEYMAP &&
- output_format != OUTPUT_FORMAT_RMLVO)
- goto output_format_error;
- output_format = OUTPUT_FORMAT_RMLVO;
- break;
- case OPT_MODMAPS:
- assert(!is_incompatible_with_keymap_input(OUTPUT_FORMAT_MODMAPS));
- if (output_format != OUTPUT_FORMAT_KEYMAP &&
- output_format != OUTPUT_FORMAT_MODMAPS)
- goto output_format_error;
- output_format = OUTPUT_FORMAT_MODMAPS;
- break;
- default:
- goto invalid_usage;
- }
- }
- if (optind < argc && !isempty(argv[optind])) {
- /* Some positional arguments left: use as a keymap input */
- if (input_format != INPUT_FORMAT_AUTO ||
- is_incompatible_with_keymap_input(output_format)) {
- goto too_much_arguments;
- }
- input_format = INPUT_FORMAT_KEYMAP;
- *path = argv[optind++];
- if (optind < argc) {
- /* Further positional arguments is an error */
- too_much_arguments:
- fprintf(stderr, "ERROR: Too many positional arguments\n");
- goto invalid_usage;
- }
- } else if (is_pipe_or_regular_file(STDIN_FILENO) &&
- input_format != INPUT_FORMAT_RMLVO &&
- !is_incompatible_with_keymap_input(output_format)) {
- /* No positional argument: detect piping */
- input_format = INPUT_FORMAT_KEYMAP;
- }
- if (isempty(*path) || strcmp(*path, "-") == 0)
- *path = NULL;
- *input_format_out = input_format;
- *output_format_out = output_format;
- return true;
- input_format_error:
- fprintf(stderr, "ERROR: Cannot use RMLVO options with keymap input\n");
- goto invalid_usage;
- keymap_env_error:
- fprintf(stderr, "ERROR: --keymap is not compatible with "
- "--enable-environment-names\n");
- goto invalid_usage;
- output_format_error:
- fprintf(stderr, "ERROR: Cannot mix output formats\n");
- goto invalid_usage;
- output_incompatible_with_keymap_input_error:
- fprintf(stderr, "ERROR: Output format incompatible with keymap input\n");
- goto invalid_usage;
- too_many_includes:
- fprintf(stderr, "ERROR: too many includes (max: %zu)\n",
- ARRAY_SIZE(includes));
- invalid_usage:
- usage(stderr, argv[0]);
- exit(EXIT_INVALID_USAGE);
- }
- static const char success_text[] = "Success!";
- static int
- print_rmlvo(struct xkb_context *ctx, struct xkb_rule_names *rmlvo)
- {
- /* Resolve default RMLVO values */
- struct xkb_rule_names resolved = { NULL };
- if (!xkb_components_names_from_rules(ctx, rmlvo, &resolved, NULL)) {
- fprintf(stderr, "ERROR: failed to get RMLVO names from rules\n");
- return EXIT_FAILURE;
- } else if (test) {
- fprintf(stderr, "%s\n", success_text);
- return EXIT_SUCCESS;
- }
- printf("rules: \"%s\"\nmodel: \"%s\"\nlayout: \"%s\"\nvariant: \"%s\"\n"
- "options: \"%s\"\n",
- resolved.rules, resolved.model, resolved.layout,
- resolved.variant ? resolved.variant : "",
- resolved.options ? resolved.options : "");
- return EXIT_SUCCESS;
- }
- static int
- print_kccgst(struct xkb_context *ctx, struct xkb_rule_names *rmlvo, bool yaml)
- {
- struct xkb_component_names kccgst = { 0 };
- int rc = EXIT_SUCCESS;
- /* Resolve missing RMLVO values, then resolve the RMLVO names to
- * KcCGST components */
- if (!xkb_components_names_from_rules(ctx, rmlvo, NULL, &kccgst)) {
- fprintf(stderr, "ERROR: failed to get KcCGST components from rules\n");
- rc = EXIT_FAILURE;
- goto out;
- } else if (test) {
- fprintf(stderr, "%s\n", success_text);
- goto out;
- }
- if (yaml) {
- printf("keycodes: \"%s\"\n"
- "types: \"%s\"\n"
- "compat: \"%s\"\n"
- "symbols: \"%s\"\n",
- kccgst.keycodes, kccgst.types, kccgst.compatibility,
- kccgst.symbols);
- /* Contrary to the previous components, geometry can be empty */
- if (!isempty(kccgst.geometry)) {
- printf("geometry: \"%s\"\n", kccgst.geometry);
- }
- } else {
- printf("xkb_keymap {\n"
- " xkb_keycodes { include \"%s\" };\n"
- " xkb_types { include \"%s\" };\n"
- " xkb_compat { include \"%s\" };\n"
- " xkb_symbols { include \"%s\" };\n",
- kccgst.keycodes, kccgst.types, kccgst.compatibility,
- kccgst.symbols);
- /* Contrary to the previous components, geometry can be empty */
- if (!isempty(kccgst.geometry)) {
- printf(" xkb_geometry { include \"%s\" };\n", kccgst.geometry);
- }
- printf("};\n");
- }
- out:
- free(kccgst.keycodes);
- free(kccgst.types);
- free(kccgst.compatibility);
- free(kccgst.symbols);
- free(kccgst.geometry);
- return rc;
- }
- static struct xkb_keymap*
- load_keymap(struct xkb_context *ctx, enum xkb_keymap_format keymap_input_format,
- enum xkb_keymap_compile_flags compile_flags, enum input_format format,
- const struct xkb_rule_names *rmlvo,
- const char *path)
- {
- if (format == INPUT_FORMAT_KEYMAP) {
- FILE *file = NULL;
- if (path) {
- /* Read from regular file */
- file = fopen(path, "rb");
- } else {
- /* Read from stdin */
- file = tools_read_stdin();
- }
- if (!file) {
- fprintf(stderr, "ERROR: Failed to open keymap file \"%s\": %s\n",
- path ? path : "stdin", strerror(errno));
- return NULL;
- }
- return xkb_keymap_new_from_file(ctx, file,
- keymap_input_format,
- compile_flags);
- } else {
- return xkb_keymap_new_from_names2(ctx, rmlvo, keymap_input_format,
- compile_flags);
- }
- }
- static int
- print_keymap(struct xkb_context *ctx,
- enum xkb_keymap_format keymap_input_format,
- enum xkb_keymap_compile_flags compile_flags,
- enum input_format format,
- const struct xkb_rule_names *rmlvo, const char *path,
- const struct xkb_keymap_serialize_config *config)
- {
- int ret = EXIT_SUCCESS;
- struct xkb_keymap *keymap = load_keymap(ctx, keymap_input_format,
- compile_flags, format, rmlvo, path);
- if (!keymap) {
- fprintf(stderr, "ERROR: Couldn't create xkb keymap\n");
- ret = EXIT_FAILURE;
- } else if (test) {
- fprintf(stderr, "%s\n", success_text);
- } else {
- struct xkb_keymap_serialize_result result = { .size = sizeof(result) };
- const enum xkb_error_code error =
- xkb_keymap_serialize(keymap, config, &result);
- if (error != XKB_SUCCESS) {
- fprintf(stderr, "ERROR %d: Couldn't get the keymap string\n", error);
- ret = EXIT_FAILURE;
- } else {
- fputs(result.serialized, stdout);
- free(result.serialized);
- }
- }
- xkb_keymap_unref(keymap);
- return ret;
- }
- static int
- print_modmaps(struct xkb_context *ctx,
- enum xkb_keymap_format keymap_input_format,
- enum xkb_keymap_compile_flags compile_flags,
- enum input_format format, const struct xkb_rule_names *rmlvo,
- const char *path)
- {
- int ret = EXIT_SUCCESS;
- struct xkb_keymap *keymap = load_keymap(ctx, keymap_input_format,
- compile_flags, format, rmlvo, path);
- if (!keymap) {
- fprintf(stderr, "ERROR: Couldn't create xkb keymap\n");
- ret = EXIT_FAILURE;
- } else if (test) {
- fprintf(stderr, "%s\n", success_text);
- } else {
- print_modifiers_encodings(keymap);
- printf("\n");
- print_keys_modmaps(keymap);
- }
- xkb_keymap_unref(keymap);
- return ret;
- }
- int
- main(int argc, char **argv)
- {
- struct xkb_context *ctx;
- char *keymap_path = NULL;
- struct xkb_rule_names names = { 0 };
- bool use_env_names = false;
- enum xkb_keymap_format keymap_input_format = DEFAULT_INPUT_KEYMAP_FORMAT;
- static_assert(DEFAULT_OUTPUT_KEYMAP_FORMAT == XKB_KEYMAP_USE_ORIGINAL_FORMAT,
- "Out of sync usage()");
- enum xkb_keymap_format keymap_output_format = DEFAULT_OUTPUT_KEYMAP_FORMAT;
- enum xkb_keymap_compile_flags compile_flags =
- (enum xkb_keymap_compile_flags) DEFAULT_KEYMAP_COMPILE_FLAGS;
- enum xkb_keymap_serialize_flags serialize_flags =
- (enum xkb_keymap_serialize_flags) DEFAULT_KEYMAP_SERIALIZE_FLAGS;
- xkb_layout_mask_t layout_mask = 0; /* all layouts by default */
- setlocale(LC_ALL, "");
- if (argc < 1) {
- usage(stderr, argv[0]);
- return EXIT_INVALID_USAGE;
- }
- enum input_format input_format = INPUT_FORMAT_AUTO;
- enum output_format output_format = OUTPUT_FORMAT_KEYMAP;
- if (!parse_options(argc, argv, &input_format, &output_format,
- &keymap_input_format, &keymap_output_format,
- &compile_flags, &serialize_flags, &layout_mask,
- &use_env_names, &keymap_path, &names))
- return EXIT_INVALID_USAGE;
- enum xkb_context_flags ctx_flags = XKB_CONTEXT_NO_DEFAULT_INCLUDES;
- if (!use_env_names)
- ctx_flags |= XKB_CONTEXT_NO_ENVIRONMENT_NAMES;
- ctx = xkb_context_new(ctx_flags);
- if (!ctx) {
- fprintf(stderr, "ERROR: cannot create xkb context\n");
- return EXIT_FAILURE;
- }
- if (verbose)
- tools_enable_verbose_logging(ctx);
- if (num_includes == 0)
- includes[num_includes++] = DEFAULT_INCLUDE_PATH_PLACEHOLDER;
- for (size_t i = 0; i < num_includes; i++) {
- const char *include = includes[i];
- if (strcmp(include, DEFAULT_INCLUDE_PATH_PLACEHOLDER) == 0)
- xkb_context_include_path_append_default(ctx);
- else
- xkb_context_include_path_append(ctx, include);
- }
- int rc = EXIT_FAILURE;
- switch (output_format) {
- case OUTPUT_FORMAT_RMLVO:
- assert(input_format != INPUT_FORMAT_KEYMAP);
- rc = print_rmlvo(ctx, &names);
- break;
- case OUTPUT_FORMAT_KCCGST:
- assert(input_format != INPUT_FORMAT_KEYMAP);
- rc = print_kccgst(ctx, &names, false);
- break;
- case OUTPUT_FORMAT_KCCGST_YAML:
- assert(input_format != INPUT_FORMAT_KEYMAP);
- rc = print_kccgst(ctx, &names, true);
- break;
- case OUTPUT_FORMAT_MODMAPS:
- rc = print_modmaps(ctx, keymap_input_format,
- compile_flags, input_format, &names, keymap_path);
- break;
- default: {
- struct xkb_keymap_serialize_config config = {
- .size = sizeof(config),
- .flags = serialize_flags,
- .format = keymap_output_format,
- .layouts = layout_mask,
- };
- rc = print_keymap(ctx, keymap_input_format, compile_flags, input_format,
- &names, keymap_path, &config);
- }
- }
- xkb_context_unref(ctx);
- return rc;
- }
|