registry-list.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. * Copyright © 2020 Red Hat, Inc.
  3. * SPDX-License-Identifier: MIT
  4. */
  5. #include "config.h"
  6. #include <assert.h>
  7. #include <getopt.h>
  8. #include <locale.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include "xkbcommon/xkbregistry.h"
  12. static void
  13. usage(const char *progname, FILE *fp)
  14. {
  15. fprintf(fp,
  16. "Usage: %s [OPTIONS] [/path/to/xkb_base_directory [/path2]...]\n"
  17. "\n"
  18. "Options:\n"
  19. " --verbose, -v .......... Increase verbosity, use multiple times for debugging output\n"
  20. " --ruleset=foo .......... Load the 'foo' ruleset\n"
  21. " --skip-default-paths ... Do not load the default XKB paths\n"
  22. " --load-exotic .......... Load the exotic (extra) rulesets\n"
  23. " --help ................. Print this help and exit\n"
  24. " --version .............. Print version information and exit\n"
  25. "\n"
  26. "Trailing arguments are treated as XKB base directory installations.\n",
  27. progname);
  28. }
  29. int
  30. main(int argc, char **argv)
  31. {
  32. int rc = 1;
  33. struct rxkb_context *ctx = NULL;
  34. struct rxkb_model *m;
  35. struct rxkb_layout *l;
  36. struct rxkb_option_group *g;
  37. enum rxkb_context_flags flags = RXKB_CONTEXT_NO_FLAGS;
  38. bool load_defaults = true;
  39. int verbosity = 0;
  40. const char *ruleset = DEFAULT_XKB_RULES;
  41. static const struct option opts[] = {
  42. {"help", no_argument, 0, 'h'},
  43. {"version", no_argument, 0, 'V'},
  44. {"verbose", no_argument, 0, 'v'},
  45. {"load-exotic", no_argument, 0, 'e'},
  46. {"skip-default-paths", no_argument, 0, 'd'},
  47. {"ruleset", required_argument, 0, 'r'},
  48. {0, 0, 0, 0},
  49. };
  50. setlocale(LC_ALL, "");
  51. while (1) {
  52. int c;
  53. int option_index = 0;
  54. c = getopt_long(argc, argv, "hedrvV", opts, &option_index);
  55. if (c == -1)
  56. break;
  57. switch (c) {
  58. case 'h':
  59. usage(argv[0], stdout);
  60. return EXIT_SUCCESS;
  61. case 'd':
  62. load_defaults = false;
  63. break;
  64. case 'e':
  65. flags |= RXKB_CONTEXT_LOAD_EXOTIC_RULES;
  66. break;
  67. case 'r':
  68. ruleset = optarg;
  69. break;
  70. case 'v':
  71. verbosity++;
  72. break;
  73. case 'V':
  74. printf("%s\n", LIBXKBCOMMON_VERSION);
  75. exit(EXIT_SUCCESS);
  76. default:
  77. usage(argv[0], stderr);
  78. return EXIT_INVALID_USAGE;
  79. }
  80. }
  81. if (optind < argc)
  82. flags |= RXKB_CONTEXT_NO_DEFAULT_INCLUDES;
  83. ctx = rxkb_context_new(flags);
  84. if (!ctx) {
  85. fprintf(stderr, "Failed to create a registry context\n");
  86. rc = EXIT_FAILURE;
  87. goto err;
  88. }
  89. switch (verbosity) {
  90. case 0:
  91. rxkb_context_set_log_level(ctx, RXKB_LOG_LEVEL_ERROR);
  92. break;
  93. case 1:
  94. rxkb_context_set_log_level(ctx, RXKB_LOG_LEVEL_INFO);
  95. break;
  96. default:
  97. rxkb_context_set_log_level(ctx, RXKB_LOG_LEVEL_DEBUG);
  98. break;
  99. }
  100. if (optind < argc) {
  101. for (int i = optind; i < argc; i++) {
  102. if (!rxkb_context_include_path_append(ctx, argv[i])) {
  103. fprintf(stderr, "Failed to append include path '%s'\n",
  104. argv[i]);
  105. goto err;
  106. }
  107. }
  108. if (load_defaults) {
  109. if (!rxkb_context_include_path_append_default(ctx)) {
  110. fprintf(stderr, "Failed to include default paths.\n");
  111. goto err;
  112. }
  113. }
  114. }
  115. if (!rxkb_context_parse(ctx, ruleset)) {
  116. fprintf(stderr, "Failed to parse XKB descriptions.\n");
  117. goto err;
  118. }
  119. printf("models:\n");
  120. m = rxkb_model_first(ctx);
  121. assert(m); /* Empty model list is usually a bug or a bad xml file */
  122. while (m) {
  123. const char *vendor = rxkb_model_get_vendor(m);
  124. printf("- name: %s\n"
  125. " vendor: %s\n"
  126. " description: %s\n",
  127. rxkb_model_get_name(m),
  128. vendor ? vendor : "''",
  129. rxkb_model_get_description(m));
  130. m = rxkb_model_next(m);
  131. }
  132. printf("\n");
  133. printf("layouts:\n");
  134. l = rxkb_layout_first(ctx);
  135. assert(l); /* Empty layout list is usually a bug or a bad xml file */
  136. while (l) {
  137. struct rxkb_iso639_code *iso639;
  138. struct rxkb_iso3166_code *iso3166;
  139. const char *variant = rxkb_layout_get_variant(l);
  140. const char *brief = rxkb_layout_get_brief(l);
  141. printf("- layout: '%s'\n"
  142. " variant: '%s'\n"
  143. " brief: '%s'\n"
  144. " description: %s\n",
  145. rxkb_layout_get_name(l),
  146. variant ? variant : "",
  147. brief ? brief : "''",
  148. rxkb_layout_get_description(l));
  149. printf(" iso639: [");
  150. iso639 = rxkb_layout_get_iso639_first(l);
  151. if (iso639) {
  152. const char *sep = "";
  153. while (iso639) {
  154. printf("%s'%s'", sep, rxkb_iso639_code_get_code(iso639));
  155. iso639 = rxkb_iso639_code_next(iso639);
  156. sep = ", ";
  157. }
  158. }
  159. printf("]\n");
  160. printf(" iso3166: [");
  161. iso3166 = rxkb_layout_get_iso3166_first(l);
  162. if (iso3166) {
  163. const char *sep = "";
  164. while (iso3166) {
  165. printf("%s'%s'", sep, rxkb_iso3166_code_get_code(iso3166));
  166. iso3166 = rxkb_iso3166_code_next(iso3166);
  167. sep = ", ";
  168. }
  169. }
  170. printf("]\n");
  171. l = rxkb_layout_next(l);
  172. }
  173. printf("\n");
  174. printf("option_groups:\n");
  175. g = rxkb_option_group_first(ctx);
  176. assert(g); /* Empty option goups list is usually a bug or a bad xml file */
  177. while (g) {
  178. struct rxkb_option *o;
  179. printf("- name: '%s'\n"
  180. " description: %s\n"
  181. " allows_multiple: %s\n"
  182. " options:\n",
  183. rxkb_option_group_get_name(g),
  184. rxkb_option_group_get_description(g),
  185. rxkb_option_group_allows_multiple(g) ? "true" : "false");
  186. o = rxkb_option_first(g);
  187. assert(o); /* Empty option list is usually a bug or a bad xml file */
  188. while (o) {
  189. const char *brief = rxkb_option_get_brief(o);
  190. printf(" - name: '%s'\n"
  191. " brief: '%s'\n"
  192. " description: '%s'\n"
  193. " layout-specific: %s\n",
  194. rxkb_option_get_name(o),
  195. brief ? brief : "",
  196. rxkb_option_get_description(o),
  197. rxkb_option_is_layout_specific(o) ? "true" : "false");
  198. o = rxkb_option_next(o);
  199. }
  200. g = rxkb_option_group_next(g);
  201. }
  202. rc = EXIT_SUCCESS;
  203. err:
  204. rxkb_context_unref(ctx);
  205. return rc;
  206. }