Branch
Hash :
3203a010
Author :
Date :
2025-08-13T17:06:20
tools: Add internal introspection This tool enables simple analysis of XKB files with a YAML or DOT output: - resolve XKB paths; - list sections of a file; - list the includes of each section; - optionally process each include recursively. Additionally, the RDF Turtle output enables to query using the powerful SPARQL language. The tool is for internal use only for now, so that we can test it in various use cases before deciding if making it public.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
/*
* Copyright © 2025 Pierre Le Marre <dev@wismill.eu>
* SPDX-License-Identifier: MIT
*/
#include "config.h"
#include "xkbcommon/xkbcommon.h"
#include "src/darray.h"
#include "src/scanner-utils.h"
#include "src/utils.h"
#include "ast.h"
XKB_EXPORT_PRIVATE const char *
xkb_file_type_name(enum xkb_file_type type);
XKB_EXPORT_PRIVATE const char *
xkb_merge_mode_name(enum merge_mode type);
XKB_EXPORT_PRIVATE const char *
xkb_map_flags_string_iter(unsigned int *index, enum xkb_map_flags flags);
XKB_EXPORT_PRIVATE FILE *
xkb_resolve_file(struct xkb_context *ctx,
enum xkb_file_type file_type,
const char *path, const char *map,
char *resolved_path, size_t resolved_path_size,
char *resolved_map, size_t resolved_map_size);
/** An atomic include entry */
struct xkb_file_include {
bool valid:1;
bool explicit_section:1;
enum merge_mode merge;
/*
* The following are indices from `xkb_file_section::buffer`
*
* Use `xkb_file_section_get_string()` to retrieve them.
*/
darray_size_t path;
darray_size_t file;
darray_size_t section;
darray_size_t modifier;
/* Flags of the included section, only set if valid = true */
enum xkb_map_flags flags;
};
struct xkb_file_include_group {
darray_size_t start;
darray_size_t end;
};
/** A file section: `xkb_{keycodes,compat,geometry,symbols,types} */
struct xkb_file_section {
darray_size_t name;
enum xkb_file_type file_type;
enum xkb_map_flags flags;
darray(struct xkb_file_include_group) include_groups;
darray(struct xkb_file_include) includes;
/**
* Char array to store all the strings
*
* Use `xkb_file_section_get_string()` to retrieve them.
*/
darray_char buffer;
};
XKB_EXPORT_PRIVATE void
xkb_file_section_init(struct xkb_file_section *section);
XKB_EXPORT_PRIVATE void
xkb_file_section_free(struct xkb_file_section *section);
enum xkb_file_iterator_flags {
XKB_FILE_ITERATOR_NO_FLAG = 0,
/** Include errors are fatal */
XKB_FILE_ITERATOR_FAIL_ON_INCLUDE_ERROR = (1 << 0),
/** Do not list includes */
XKB_FILE_ITERATOR_NO_INCLUDES = (1 << 1)
};
/**
* Parse a single keymap file section
*
* @param[in] ctx The XKB context
* @param[in] iterator_flags The flags used to parse the section
* @param[in] format The keymap format used to parse the keymap file
* @param[in] compile_flags The flags used to parse the keymap file
* @param[in] path The path of the keymap file to parse
* @param[in] map The name of a specific section in the file
* @param[inout] section The resulting section
*
* @returns `true` on success, else `false`
*/
XKB_EXPORT_PRIVATE bool
xkb_file_section_parse(struct xkb_context *ctx,
enum xkb_file_iterator_flags iterator_flags,
enum xkb_keymap_format format,
enum xkb_keymap_compile_flags compile_flags,
unsigned int include_depth,
const char *path, const char *map,
struct xkb_file_section *section);
XKB_EXPORT_PRIVATE const char *
xkb_file_section_get_string(const struct xkb_file_section *section,
darray_size_t idx);
/** Iterator over the sections of a keymap file */
struct xkb_file_iterator {
enum xkb_file_iterator_flags flags;
bool finished;
/** File to analyze */
const char *path;
/** Section to analyze; if NULL then iter over all the sections */
const char *map;
/** File type to check/filter */
enum xkb_file_type type;
/** Scanner of the keymap file */
struct scanner scanner;
/** Current section */
struct xkb_file_section section;
/** Pending XKB file */
XkbFile *pending_xkb_file;
/** Pending component of the XKB file */
XkbFile *pending_section;
struct xkb_context *ctx;
};
/**
* Create a keymap file section iterator from a buffer
*
* @param ctx The XKB context
* @param iterator_flags The flags used to parse the section
* @param format The keymap format used to parse the keymap file
* @param compile_flags The flags used to parse the keymap file
* @param path The path of the keymap file parsed (informative)
* @param map The name of a specific section in the file, else NULL
* to iterate over all the sections of the file.
* @param file_type If the input is a keymap, iterate only over the
* corresponding component; else check that the parsed file type matches.
* @param string The buffer to parse
* @param length The length of the buffer to parse
*
* @returns A `malloc`ed file iterator on success, else `NULL`.
*/
XKB_EXPORT_PRIVATE struct xkb_file_iterator *
xkb_file_iterator_new_from_buffer(struct xkb_context *ctx,
enum xkb_file_iterator_flags iterator_flags,
enum xkb_keymap_format format,
enum xkb_keymap_compile_flags compile_flags,
const char *path, const char *map,
enum xkb_file_type file_type,
const char *string, size_t length);
XKB_EXPORT_PRIVATE void
xkb_file_iterator_free(struct xkb_file_iterator *iter);
XKB_EXPORT_PRIVATE bool
xkb_file_iterator_next(struct xkb_file_iterator *iter,
const struct xkb_file_section **section);