Tools: Add bash completions for xkbcli
[platform/upstream/libxkbcommon.git] / tools / compile-keymap.c
index e090de1..f49aa3c 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
+#include "xkbcommon/xkbcommon.h"
+#if ENABLE_PRIVATE_APIS
 #include "xkbcomp/xkbcomp-priv.h"
 #include "xkbcomp/rules.h"
-#include "xkbcommon/xkbcommon.h"
+#endif
+#include "tools-common.h"
 
 #define DEFAULT_INCLUDE_PATH_PLACEHOLDER "__defaults__"
 
@@ -44,7 +47,8 @@ static enum output_format {
     FORMAT_KCCGST,
     FORMAT_KEYMAP_FROM_XKB,
 } output_format = FORMAT_KEYMAP;
-static darray(const char *) includes;
+static const char *includes[64];
+static size_t num_includes = 0;
 
 static void
 usage(char **argv)
@@ -54,15 +58,21 @@ usage(char **argv)
            "Compile the given RMLVO to a keymap and print it\n"
            "\n"
            "Options:\n"
+           " --help\n"
+           "    Print this help and exit\n"
            " --verbose\n"
            "    Enable verbose debugging output\n"
+#if ENABLE_PRIVATE_APIS
            " --kccgst\n"
            "    Print a keymap which only includes the KcCGST component names instead of the full keymap\n"
+#endif
            " --rmlvo\n"
            "    Print the full RMLVO with the defaults filled in for missing elements\n"
            " --from-xkb\n"
-           "    Load the XKB file from stdin, ignore RMLVO options. This option\n"
-           "    must not be used with --kccgst.\n"
+           "    Load the XKB file from stdin, ignore RMLVO options.\n"
+#if ENABLE_PRIVATE_APIS
+           "    This option must not be used with --kccgst.\n"
+#endif
            " --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"
@@ -111,7 +121,9 @@ parse_options(int argc, char **argv, struct xkb_rule_names *names)
     static struct option opts[] = {
         {"help",             no_argument,            0, 'h'},
         {"verbose",          no_argument,            0, OPT_VERBOSE},
+#if ENABLE_PRIVATE_APIS
         {"kccgst",           no_argument,            0, OPT_KCCGST},
+#endif
         {"rmlvo",            no_argument,            0, OPT_RMLVO},
         {"from-xkb",         no_argument,            0, OPT_FROM_XKB},
         {"include",          required_argument,      0, OPT_INCLUDE},
@@ -148,10 +160,18 @@ parse_options(int argc, char **argv, struct xkb_rule_names *names)
             output_format = FORMAT_KEYMAP_FROM_XKB;
             break;
         case OPT_INCLUDE:
-            darray_append(includes, optarg);
+            if (num_includes >= ARRAY_SIZE(includes)) {
+                fprintf(stderr, "error: too many includes\n");
+                exit(EXIT_INVALID_USAGE);
+            }
+            includes[num_includes++] = optarg;
             break;
         case OPT_INCLUDE_DEFAULTS:
-            darray_append(includes, DEFAULT_INCLUDE_PATH_PLACEHOLDER);
+            if (num_includes >= ARRAY_SIZE(includes)) {
+                fprintf(stderr, "error: too many includes\n");
+                exit(EXIT_INVALID_USAGE);
+            }
+            includes[num_includes++] = DEFAULT_INCLUDE_PATH_PLACEHOLDER;
             break;
         case OPT_RULES:
             names->rules = optarg;
@@ -170,7 +190,7 @@ parse_options(int argc, char **argv, struct xkb_rule_names *names)
             break;
         default:
             usage(argv);
-            exit(1);
+            exit(EXIT_INVALID_USAGE);
         }
 
     }
@@ -191,6 +211,7 @@ print_rmlvo(struct xkb_context *ctx, const struct xkb_rule_names *rmlvo)
 static bool
 print_kccgst(struct xkb_context *ctx, const struct xkb_rule_names *rmlvo)
 {
+#if ENABLE_PRIVATE_APIS
         struct xkb_component_names kccgst;
 
         if (!xkb_components_from_rules(ctx, rmlvo, &kccgst))
@@ -209,6 +230,9 @@ print_kccgst(struct xkb_context *ctx, const struct xkb_rule_names *rmlvo)
         free(kccgst.symbols);
 
         return true;
+#else
+        return false;
+#endif
 }
 
 static bool
@@ -290,22 +314,33 @@ main(int argc, char **argv)
 {
     struct xkb_context *ctx;
     struct xkb_rule_names names = {
-        .rules = NULL,
-        .model = NULL,
+        .rules = DEFAULT_XKB_RULES,
+        .model = DEFAULT_XKB_MODEL,
+        /* layout and variant are tied together, so we either get user-supplied for
+         * both or default for both, see below */
         .layout = NULL,
         .variant = NULL,
-        .options = NULL,
+        .options = DEFAULT_XKB_OPTIONS,
     };
     int rc = 1;
-    const char **path;
 
-    if (argc <= 1) {
+    if (argc < 1) {
         usage(argv);
-        return 1;
+        return EXIT_INVALID_USAGE;
     }
 
     if (!parse_options(argc, argv, &names))
-        return 1;
+        return EXIT_INVALID_USAGE;
+
+    /* Now fill in the layout */
+    if (!names.layout || !*names.layout) {
+        if (names.variant && *names.variant) {
+            fprintf(stderr, "Error: a variant requires a layout\n");
+            return EXIT_INVALID_USAGE;
+        }
+        names.layout = DEFAULT_XKB_LAYOUT;
+        names.variant = DEFAULT_XKB_VARIANT;
+    }
 
     ctx = xkb_context_new(XKB_CONTEXT_NO_DEFAULT_INCLUDES);
     assert(ctx);
@@ -315,15 +350,15 @@ main(int argc, char **argv)
         xkb_context_set_log_verbosity(ctx, 10);
     }
 
-    xkb_context_sanitize_rule_names(ctx, &names);
-    if (darray_empty(includes))
-        darray_append(includes, DEFAULT_INCLUDE_PATH_PLACEHOLDER);
+    if (num_includes == 0)
+        includes[num_includes++] = DEFAULT_INCLUDE_PATH_PLACEHOLDER;
 
-    darray_foreach(path, includes) {
-        if (streq(*path, 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, *path);
+            xkb_context_include_path_append(ctx, include);
     }
 
     if (output_format == FORMAT_RMLVO) {