Update Native Libraries (#1)

* Update libxkbcommon

* Squash bugs

* Update xkbcommon to latest master

* Update parser definitions

* Bug fixes
This commit is contained in:
Suhan G Paradkar 2021-07-03 12:15:43 +05:30 committed by Wisest_wizard
parent 7c1bfbc9d6
commit afe1e33f3e
241 changed files with 60786 additions and 103451 deletions

View File

@ -35,13 +35,13 @@ LOCAL_SRC_FILES := \
xkbcommon/src/utf8.c \
xkbcommon/src/utils.c
LOCAL_CFLAGS := \
-std=c99 -Wall -Werror -Wno-unused-parameter -Wno-missing-field-initializers \
-std=c99 -Wall -Werror -Wno-unused-parameter -Wno-missing-field-initializers -Wimplicit-function-declaration \
-D_GNU_SOURCE \
-DXLOCALEDIR=\"/data/data/com.termux/files/usr/share/X11/locale\" \
-DDEFAULT_XKB_LAYOUT=\"us\" \
-DDEFAULT_XKB_MODEL=\"pc105\" \
-DDEFAULT_XKB_RULES=\"evdev\" \
-DDFLT_XKB_CONFIG_ROOT=\"/data/data/com.termux/files/usr/share/X11/xkb\"
LOCAL_C_INCLUDES := $(LOCAL_PATH)/xkbcommon $(LOCAL_PATH)/xkbcommon/src
LOCAL_C_INCLUDES := $(LOCAL_PATH)/xkbcommon $(LOCAL_PATH)/xkbcommon/src $(LOCAL_PATH)/xkbcommon/include
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/xkbcommon/
include $(BUILD_SHARED_LIBRARY)

View File

@ -1,3 +0,0 @@
begin-language: "Autoconf-without-aclocal-m4"
args: --cache=build-aux
end-language: "Autoconf-without-aclocal-m4"

View File

@ -0,0 +1,14 @@
root = true
[*]
charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = space
indent_size = 4
max_line_length = 80
[*.yml]
indent_style = space
indent_size = 2

View File

@ -1,12 +0,0 @@
language: c
before_install:
- sudo apt-get update -qq
- sudo apt-get install xutils-dev
compiler:
- gcc
- clang
# libxcb too old -- should enable when possible.
script: ./autogen.sh --disable-x11 && make && make check

View File

@ -20,7 +20,7 @@ BEGINNING OF SOFTWARE COPYRIGHT/LICENSE STATEMENTS:
-------------------------------------------------------------------------------
Copyright © 2009-2012 Daniel Stone
Copyright © 2009-2012, 2016 Daniel Stone
Copyright © 2012 Ran Benita <ran234@gmail.com>
Copyright © 2010, 2012 Intel Corporation
Copyright © 2008, 2009 Dan Nicholson

View File

@ -1,309 +0,0 @@
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = xkbcommon.pc
EXTRA_DIST = \
makekeys.py \
src/xkbcomp/keywords.gperf \
test/data \
README.md \
doc/quick-guide.md \
doc/compat.md \
doc/keymap-format-text-v1.txt \
doc/rules-format.txt \
doc/doxygen-extra.css \
xkbcommon.map \
xkbcommon-x11.map \
PACKAGING
AM_CPPFLAGS = \
-DDFLT_XKB_CONFIG_ROOT='"$(XKBCONFIGROOT)"' \
-DXLOCALEDIR='"$(XLOCALEDIR)"' \
-I$(top_srcdir)/src \
-I$(top_srcdir)/src/xkbcomp \
-I$(top_builddir)/src/xkbcomp \
-include $(top_builddir)/src/config.h
AM_CFLAGS = $(BASE_CFLAGS)
AM_LDFLAGS = -no-undefined
if HAVE_NO_UNDEFINED
AM_LDFLAGS += -Wl,--no-undefined
endif
AM_YFLAGS = -d -p _xkbcommon_
xkbcommonincludedir = $(includedir)/xkbcommon
xkbcommoninclude_HEADERS = \
xkbcommon/xkbcommon.h \
xkbcommon/xkbcommon-compat.h \
xkbcommon/xkbcommon-compose.h \
xkbcommon/xkbcommon-keysyms.h \
xkbcommon/xkbcommon-names.h
lib_LTLIBRARIES = libxkbcommon.la
libxkbcommon_la_SOURCES = \
src/compose/parser.c \
src/compose/parser.h \
src/compose/paths.c \
src/compose/paths.h \
src/compose/state.c \
src/compose/table.c \
src/compose/table.h \
src/xkbcomp/action.c \
src/xkbcomp/action.h \
src/xkbcomp/ast.h \
src/xkbcomp/ast-build.c \
src/xkbcomp/ast-build.h \
src/xkbcomp/compat.c \
src/xkbcomp/expr.c \
src/xkbcomp/expr.h \
src/xkbcomp/include.c \
src/xkbcomp/include.h \
src/xkbcomp/keycodes.c \
src/xkbcomp/keymap.c \
src/xkbcomp/keymap-dump.c \
src/xkbcomp/keywords.c \
src/xkbcomp/parser.y \
src/xkbcomp/parser-priv.h \
src/xkbcomp/rules.c \
src/xkbcomp/rules.h \
src/xkbcomp/scanner.c \
src/xkbcomp/symbols.c \
src/xkbcomp/types.c \
src/xkbcomp/vmod.c \
src/xkbcomp/vmod.h \
src/xkbcomp/xkbcomp.c \
src/xkbcomp/xkbcomp-priv.h \
src/atom.c \
src/atom.h \
src/context.c \
src/context.h \
src/context-priv.c \
src/darray.h \
src/keysym.c \
src/keysym.h \
src/keysym-utf.c \
src/ks_tables.h \
src/keymap.c \
src/keymap.h \
src/keymap-priv.c \
src/scanner-utils.h \
src/state.c \
src/text.c \
src/text.h \
src/utf8.c \
src/utf8.h \
src/utils.c \
src/utils.h
libxkbcommon_la_LDFLAGS = -Wl,--version-script=${srcdir}/xkbcommon.map
if ENABLE_X11
pkgconfig_DATA += xkbcommon-x11.pc
xkbcommon_x11includedir = $(xkbcommonincludedir)
xkbcommon_x11include_HEADERS = \
xkbcommon/xkbcommon-x11.h
lib_LTLIBRARIES += libxkbcommon-x11.la
libxkbcommon_x11_la_CFLAGS = $(AM_CFLAGS) $(XCB_XKB_CFLAGS)
libxkbcommon_x11_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/x11
libxkbcommon_x11_la_LIBADD = libxkbcommon.la $(XCB_XKB_LIBS)
libxkbcommon_x11_la_LDFLAGS = -Wl,--version-script=${srcdir}/xkbcommon-x11.map
libxkbcommon_x11_la_SOURCES = \
src/x11/keymap.c \
src/x11/state.c \
src/x11/util.c \
src/x11/x11-priv.h \
src/context.h \
src/context-priv.c \
src/keymap.h \
src/keymap-priv.c \
src/atom.h \
src/atom.c
endif ENABLE_X11
BUILT_SOURCES = \
src/xkbcomp/parser.c \
src/xkbcomp/parser.h
CLEANFILES = $(BUILT_SOURCES)
src/xkbcomp/parser.c: $(top_builddir)/src/$(am__dirstamp) $(top_builddir)/src/xkbcomp/$(am__dirstamp)
src/xkbcomp/parser.h: $(top_builddir)/src/$(am__dirstamp) $(top_builddir)/src/xkbcomp/$(am__dirstamp)
##
# Documentation
##
if ENABLE_DOCS
if HAVE_DOXYGEN
doc: doc/stamp-doxygen
clean-doc: clean-doxygen
all-local:: doc
clean-local:: clean-doc
doc/stamp-doxygen: $(top_srcdir)/xkbcommon/*.h
$(AM_V_GEN)$(DOXYGEN) doc/Doxyfile
touch $@
clean-doxygen:
rm -rf doc/html doc/stamp-doxygen
install-data-local:: doc
$(MKDIR_P) $(DESTDIR)$(htmldir)
$(INSTALL_DATA) doc/html/* $(DESTDIR)$(htmldir)
uninstall-local::
rm -rf $(DESTDIR)$(htmldir)
endif HAVE_DOXYGEN
endif ENABLE_DOCS
##
# Tests
##
# Some tests need to use unexported symbols, so we link them against
# a private copy of libxkbcommon with all symbols exposed.
check_LTLIBRARIES = libtest.la
libtest_la_SOURCES = \
$(libxkbcommon_la_SOURCES) \
test/common.c \
test/test.h \
test/evdev-scancodes.h
AM_TESTS_ENVIRONMENT = \
XKB_LOG_LEVEL=debug; export XKB_LOG_LEVEL; \
XKB_LOG_VERBOSITY=10; export XKB_LOG_VERBOSITY; \
$(XORG_MALLOC_DEBUG_ENV)
TESTS = \
test/keysym \
test/filecomp \
test/context \
test/rules-file \
test/stringcomp \
test/buffercomp \
test/log \
test/atom \
test/utf8 \
test/state \
test/keyseq \
test/rulescomp \
test/compose
check_PROGRAMS = \
test/rmlvo-to-kccgst \
test/print-compiled-keymap
TESTS_LDADD = libtest.la
test_keysym_LDADD = $(TESTS_LDADD)
test_filecomp_LDADD = $(TESTS_LDADD)
test_context_LDADD = $(TESTS_LDADD)
test_rules_file_CFLAGS = $(AM_CFLAGS) -Wno-declaration-after-statement
test_rules_file_LDADD = $(TESTS_LDADD)
test_stringcomp_LDADD = $(TESTS_LDADD)
test_buffercomp_LDADD = $(TESTS_LDADD)
test_log_LDADD = $(TESTS_LDADD)
test_atom_LDADD = $(TESTS_LDADD)
test_utf8_LDADD = $(TESTS_LDADD)
test_state_LDADD = $(TESTS_LDADD)
test_keyseq_LDADD = $(TESTS_LDADD)
test_rulescomp_LDADD = $(TESTS_LDADD)
test_rmlvo_to_kccgst_LDADD = $(TESTS_LDADD)
test_print_compiled_keymap_LDADD = $(TESTS_LDADD)
test_compose_LDADD = $(TESTS_LDADD) $(RT_LIBS)
if BUILD_LINUX_TESTS
check_PROGRAMS += \
test/interactive-evdev
test_interactive_evdev_LDADD = $(TESTS_LDADD)
endif BUILD_LINUX_TESTS
if ENABLE_X11
TESTS += \
test/x11 \
test/x11comp
check_PROGRAMS += \
test/interactive-x11
TESTS_X11_LDADD = $(XCB_XKB_LIBS) $(TESTS_LDADD) libxkbcommon-x11.la
TESTS_X11_CFLAGS = $(XCB_XKB_CFLAGS)
test_x11_LDADD = $(TESTS_X11_LDADD)
test_x11_CFLAGS = $(TESTS_X11_CFLAGS)
test_x11comp_LDADD = $(TESTS_X11_LDADD)
test_x11comp_CFLAGS = $(TESTS_X11_CFLAGS)
test_interactive_x11_LDADD = $(TESTS_X11_LDADD)
test_interactive_x11_CFLAGS = $(TESTS_X11_CFLAGS)
endif ENABLE_X11
check_PROGRAMS += $(TESTS)
##
# Benchmarks
##
BENCH_LDADD = $(TESTS_LDADD) $(RT_LIBS)
check_PROGRAMS += \
bench/key-proc \
bench/rules \
bench/rulescomp \
bench/compose
bench_key_proc_LDADD = $(BENCH_LDADD)
bench_rules_LDADD = $(BENCH_LDADD)
bench_rulescomp_LDADD = $(BENCH_LDADD)
bench_compose_LDADD = $(BENCH_LDADD)
##
# Custom targets
##
# This sed script strips out lines that start with '#define _' which
# removes #define _OSF_Keysyms and such. The XK_Ydiaeresis case is to
# handle a duplicate definition in HPkeysyms.h which kicks in if it's
# not already defined.
X11_INCLUDEDIR = /usr/include/X11
KEYSYMDEFS = \
$(X11_INCLUDEDIR)/keysymdef.h \
$(X11_INCLUDEDIR)/XF86keysym.h \
$(X11_INCLUDEDIR)/Sunkeysym.h \
$(X11_INCLUDEDIR)/DECkeysym.h \
$(X11_INCLUDEDIR)/HPkeysym.h
update-keysyms:
echo -en '#ifndef _XKBCOMMON_KEYSYMS_H\n#define _XKBCOMMON_KEYSYMS_H\n\n' > $(top_srcdir)/xkbcommon/xkbcommon-keysyms.h
echo -en '/* This file is autogenerated from Makefile.am; please do not commit directly. */\n\n' >> $(top_srcdir)/xkbcommon/xkbcommon-keysyms.h
echo -en '#define XKB_KEY_NoSymbol 0x000000 /* Special KeySym */\n\n' >> $(top_srcdir)/xkbcommon/xkbcommon-keysyms.h
sed -e '/XK_Ydiaeresis\s*0x100000ee/d' \
-e '/#define _/d' \
-e 's/#define\s*\(\w*\)XK_/#define XKB_KEY_\1/' \
-e '/\(#ifdef\|#ifndef\|#endif\)/d' $(KEYSYMDEFS) >> $(top_srcdir)/xkbcommon/xkbcommon-keysyms.h
echo -en '\n\n#endif\n' >> $(top_srcdir)/xkbcommon/xkbcommon-keysyms.h
LC_CTYPE=C python $(top_srcdir)/makekeys.py $(top_srcdir)/xkbcommon/xkbcommon-keysyms.h > $(top_srcdir)/src/ks_tables.h
# Run this if you add/remove a new keyword to the xkbcomp scanner,
# or just want to regenerate the gperf file.
update-keywords:
$(AM_V_GEN)gperf < $(top_srcdir)/src/xkbcomp/keywords.gperf > $(top_srcdir)/src/xkbcomp/keywords.c
##
# Android stuff
##
Android_build.mk: Makefile $(BUILT_SOURCES)
androgenizer \
-:PROJECT libxkbcommon \
-:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
\
-:STATIC libxkbcommon \
-:TAGS eng debug \
-:SOURCES $(filter-out %.l %.y,$(libxkbcommon_la_SOURCES)) $(BUILT_SOURCES) \
-:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(AM_CPPFLAGS) $(AM_CFLAGS) \
-:LDFLAGS $(AM_LDFLAGS) \
\
-:PASSTHROUGH 'libxkbcommon-clean: clean-libxkbcommon' \
> $@

View File

@ -1,3 +1,550 @@
libxkbcommon 1.3.0 - 2021-05-01
==================
- Change `xkbcli list` to output YAML, instead of the previous ad-hoc format.
This allows to more easily process the information in a programmetic way, for
example
xkbcli list | yq -r ".layouts[].layout"
Contributed by Peter Hutterer.
- Optimize a certain part of keymap compilation (atom interning).
- Fix segmentation fault in case-insensitive `xkb_keysym_from_name` for certain
values like the empty string.
Contributed by Isaac Freund.
- Support building libxkbcommon as a meson subproject.
Contributed by Adrian Perez de Castro.
- Add `ftruncate` fallback for `posix_fallocate` in `xkbcli interactive-wayland`
for FreeBSD.
Contributed by Evgeniy Khramtsov.
- Properly export library symbols in MSVC.
Contributed by Adrian Perez de Castro.
libxkbcommon 1.2.1 - 2021-04-07
==================
- Fix `xkb_x11_keymap_new_from_device()` failing when the keymap contains key
types with missing level names, like the one used by the `numpad:mac` option
in xkeyboard-config. Regressed in 1.2.0.
libxkbcommon 1.2.0 - 2021-04-03
==================
- `xkb_x11_keymap_new_from_device()` is much faster. It now performs only 2
roundtrips to the X server, instead of dozens (in first-time calls).
Contributed by Uli Schlachter.
- Case-sensitive `xkb_keysym_from_name()` is much faster.
- Keysym names of the form `0x12AB` and `U12AB` are parsed more strictly.
Previously the hexadecimal part was parsed with `strtoul()`, now only up
to 8 hexadecimal digits (0-9A-Fa-f) are allowed.
- Compose files now have a size limit (65535 internal nodes). Further sequences
are discared and a warning is issued.
- Compose table loading (`xkb_compose_table_new_from_locale()` and similar) is
much faster.
- Use `poll()` instead of `epoll()` for `xlbcli interactive-evdev`, making it
portable to FreeBSD which provides evdev but not epoll. On FreeBSD, remember
to install the `evdev-proto` package to get the evdev headers.
- The build now requires a C11 compiler (uses anonymous structs/unions).
libxkbcommon 1.1.0 - 2021-02-27
==================
- Publish the `xkb-format-text-v1.md` file in the HTML documentation. This file
existed for a long time but only in the Git repository.
Link: https://xkbcommon.org/doc/current/md_doc_keymap_format_text_v1.html
- Add partial documentation for xkb_symbols to xkb-format-text-v1.md.
Contributed by Simon Zeni.
- Update keysym definitions to latest xorgproto. In particular, this adds many
special keysyms corresponding to Linux evdev keycodes.
Contributed by Peter Hutterer <@who-t.net>.
- New API:
Too many XKB_KEY_* definitions to list here.
libxkbcommon 1.0.3 - 2020-11-23
==================
- Fix (hopefully) a segfault in xkb_x11_keymap_new_from_device() in some
unclear situation (bug introduced in 1.0.2).
- Fix keymaps created with xkb_x11_keymap_new_from_device() don't have level
names (bug introduced in 0.8.0).
libxkbcommon 1.0.2 - 2020-11-20
==================
- Fix a bug where a keysym that cannot be resolved in a keymap gets compiled to
a garbage keysym. Now it is set to XKB_KEY_NoSymbol instead.
- Improve the speed of xkb_x11_keymap_new_from_device() on repeated calls in the
same xkb_context().
libxkbcommon 1.0.1 - 2020-09-11
==================
- Fix the tool-option-parsing test failing.
- Remove requirement for pytest in the tool-option-parsing test.
- Make the table output of `xkbcli how-to-type` aligned.
- Some portability and test isolation fixes.
libxkbcommon 1.0.0 - 2020-09-05
==================
Note: this release is API and ABI compatible with previous releases -- the
major version bump is only an indication of stability.
- Add libxkbregistry as configure-time optional library. libxkbregistry is a C
library that lists available XKB models, layouts and variants for a given
ruleset. This is a separate library (libxkbregistry.so, pkgconfig file
xkbregistry.pc) and aimed at tools that provide a listing of available
keyboard layouts to the user. See the Documentation for details on the API.
Contributed by Peter Hutterer <@who-t.net>.
- Better support custom user configuration:
* Allow including XKB files from other paths.
Previously, a 'symbols/us' file in path A would shadow the same file in
path B. This is suboptimal, we rarely need to hide the system files - we
care mostly about *extending* them. By continuing to check other lookup
paths, we make it possible for a XDG_CONFIG_HOME/xkb/symbols/us file to
have sections including those from /usr/share/X11/xkb/symbols/us.
Note that this is not possible for rules files, which need to be manually
controlled to get the right bits resolved.
* Add /etc/xkb as extra lookup path for system data files.
This completes the usual triplet of configuration locations available for
most processes:
- vendor-provided data files in /usr/share/X11/xkb
- system-specific data files in /etc/xkb
- user-specific data files in $XDG_CONFIG_HOME/xkb
The default lookup order user, system, vendor, just like everything else
that uses these conventions.
For include directives in rules files, the '%E' resolves to that path.
* Add a new section to the documentation for custom user configuration.
Contributed by Peter Hutterer <@who-t.net>.
- Add an `xkbcli` command-line utility.
This tool offers various subcommands for introspection and debugging.
Currently the available subcommands are:
list
List available rules, models, layouts, variants and options
interactive-wayland
Interactive debugger for XKB keymaps for Wayland
interactive-x11
Interactive debugger for XKB keymaps for X11
interactive-evdev
Interactive debugger for XKB keymaps for evdev (Linux)
compile-keymap
Compile an XKB keymap
how-to-type
See separate entry below.
See the manpages for usage information.
Contributed by Peter Hutterer <@who-t.net>.
- Add `xkb_utf32_to_keysym()` to translate a Unicode codepoint to a keysym.
When a special keysym (`XKB_KEY_` constant) for the codepoint exists, it is
returned, otherwise the direct encoding is used, if permissible.
Contributed by Jaroslaw Kubik <@froglogic.com>.
- Add `xkb_keymap_key_get_mods_for_level()` which retrieves sets of modifiers
which produce a given shift level in a given key+layout.
Contributed by Jaroslaw Kubik <@froglogic.com>.
- Add `xkbcli how-to-type` command, which, using `xkb_utf32_to_keysym()`
and `xkb_keymap_key_get_mods_for_level()` and other APIs, prints out all
the ways to produce a given keysym.
For example, how to type `?` (codepoint 63) in a us,de keymap?
$ xkbcli how-to-type --layout us,de 63 | column -ts $'\t'
keysym: question (0x3f)
KEYCODE KEY NAME LAYOUT# LAYOUT NAME LEVEL# MODIFIERS
20 AE11 2 German 2 [ Shift ]
20 AE11 2 German 2 [ Shift Lock ]
61 AB10 1 English (US) 2 [ Shift ]
- Add a new section to the documentation describing the format of the XKB
rules file.
- Search for Compose in $XDG_CONFIG_HOME/XCompose (fallback to
~/.config/XCompose) before trying $HOME/.XCompose.
Note that libX11 still only searches in $HOME/.XCompose.
Contributed by Emmanuel Gil Peyrot <@linkmauve.fr>.
- Bump meson requirement to >= 0.49.0.
- Fix build with byacc.
- Fix building X11 tests on PE targets.
Contributed by Jon Turney <@dronecode.org.uk>
- The tests no longer rely on bash, only Python (which is already used by
meson).
- New API:
xkb_utf32_to_keysym
xkb_keymap_key_get_mods_for_level
XKB_KEY_XF86FullScreen
libxkbcommon 0.10.0 - 2020-01-18
===================
- (security) Fix quadratic complexity in the XKB file parser. See commit
message 7c42945e04a2107827a057245298dedc0475cc88 for details.
- Add $XDG_CONFIG_HOME/xkb to the default search path. If $XDG_CONFIG_HOME
is not set, $HOME/.config/xkb is used. If $HOME is not set, the path is not
added.
The XDG path is looked up before the existing default search path $HOME/.xkb.
Contributed by Peter Hutterer <@who-t.net>.
- Add support for include statements in XKB rules files.
This is a step towards making local XKB customizations more tenable and
convenient, without modifying system files.
You can now include other rules files like this:
! include %S/evdev
Two directives are supported, %H to $HOME and %S for the system-installed
rules directory (usually /usr/share/X11/xkb/rules).
See commit message ca033a29d2ca910fd17b1ae287cb420205bdddc8 and
doc/rules-format.txt in the xkbcommon source code for more information.
Contributed by Peter Hutterer <@who-t.net>.
- Downgrade "Symbol added to modifier map for multiple modifiers" log to a
warning.
This error message was too annoying to be shown by default. When working on
keymaps, set `XKB_LOG_LEVEL=debug XKB_LOG_VERBOSITY=10` to see all possible
messages.
- Support building on Windows using the meson MSVC backend.
Contributed by Adrian Perez de Castro <@igalia.com>.
- Fix bug where the merge mode only applied to the first vmod in a
`virtual_modifiers` statement. Given
augment virtual_modifiers NumLock,Alt,LevelThree
Previously it was incorrectly treated as
augment virtual_modifiers NumLock;
virtual_modifiers Alt;
virtual_modifiers LevelThree;
Now it is treated as
augment virtual_modifiers NumLock;
augment virtual_modifiers Alt;
augment virtual_modifiers LevelThree;
- Reject interpret modifier predicate with more than one value. Given
interpret ISO_Level3_Shift+AnyOf(all,extraneous) { ... };
Previously, extraneous (and further) was ignored. Now it's rejected.
- Correctly handle capitalization of the ssharp keysym.
- Speed up and improve the internal `xkeyboard-config` tool. This tool
compiles all layout/variant combinations in the xkeyboard-config dataset
and reports any issues it finds.
Contributed by Peter Hutterer <@who-t.net>.
- Speed up "atoms" (string interning). This code goes back at least to X11R1
(released 1987).
libxkbcommon 0.9.1 - 2019-10-19
==================
- Fix context creation failing when run in privileged processes as defined by
`secure_getenv(3)`, e.g. GDM.
libxkbcommon 0.9.0 - 2019-10-19
==================
- Move ~/.xkb to before XKB_CONFIG_ROOT (the system XKB path, usually
/usr/share/X11/xkb) in the default include path. This enables the user
to have full control of the keymap definitions, instead of only augmenting
them.
- Remove the Autotools build system. Use the meson build system instead.
- Fix invalid names used for levels above 8 when dumping keymaps. Previously,
e.g. "Level20" was dumped, but only up to "Level8" is accepted by the
parser. Now "20" is dumped.
- Change level references to always be dumped as e.g. "5" instead of "Level5".
Change group references to always be dumped capitalized e.g. "Group3" instead
of "group3". Previously it was inconsistent.
These changes affect the output of xkb_keymap_get_as_string().
- Fix several build issues on macOS/Darwin, Solaris, NetBSD, cross compilation.
- Port the interactive-wayland test program to the stable version of xdg-shell.
libxkbcommon 0.8.4 - 2019-02-22
==================
- Fix build of xkbcommon-x11 static library with meson.
- Fix building using meson from the tarball generated by autotools.
libxkbcommon 0.8.3 - 2019-02-08
==================
- Fix build of static libraries with meson.
(Future note: xkbcommon-x11 was *not* fixed in this release.)
- New API:
XKB_KEY_XF86MonBrightnessCycle
XKB_KEY_XF86RotationLockToggle
libxkbcommon 0.8.2 - 2018-08-05
==================
- Fix various problems found with fuzzing (see commit messages for
more details):
- Fix a few NULL-dereferences, out-of-bounds access and undefined behavior
in the XKB text format parser.
libxkbcommon 0.8.1 - 2018-08-03
==================
- Fix various problems found in the meson build (see commit messages for more
details):
- Fix compilation on Darwin.
- Fix compilation of the x11 tests and demos when XCB is installed in a
non-standard location.
- Fix xkbcommon-x11.pc missing the Requires specification.
- Fix various problems found with fuzzing and Coverity (see commit messages for
more details):
- Fix stack overflow in the XKB text format parser when evaluating boolean
negation.
- Fix NULL-dereferences in the XKB text format parser when some unsupported
tokens appear (the tokens are still parsed for backward compatibility).
- Fix NULL-dereference in the XKB text format parser when parsing an
xkb_geometry section.
- Fix an infinite loop in the Compose text format parser on some inputs.
- Fix an invalid free() when using multiple keysyms.
- Replace the Unicode characters for the leftanglebracket and rightanglebracket
keysyms from the deprecated LEFT/RIGHT-POINTING ANGLE BRACKET to
MATHEMATICAL LEFT/RIGHT ANGLE BRACKET.
- Reject out-of-range Unicode codepoints in xkb_keysym_to_utf8 and
xkb_keysym_to_utf32.
libxkbcommon 0.8.0 - 2017-12-15
==================
- Added xkb_keysym_to_{upper,lower} to perform case-conversion directly on
keysyms. This is useful in some odd cases, but working with the Unicode
representations should be preferred when possible.
- Added Unicode conversion rules for the signifblank and permille keysyms.
- Fixed a bug in the parsing of XKB key type definitions where the number
of levels were determined by the number of level *names*. Keymaps which
omit level names were hence miscompiled.
This regressed in version 0.4.3. Keymaps from xkeyboard-config were not
affected since they don't omit level names.
- New API:
xkb_keysym_to_upper()
xkb_keysym_to_lower()
libxkbcommon 0.7.2 - 2017-08-04
==================
- Added a Meson build system as an alternative to existing autotools build
system.
The intent is to remove the autotools build in one of the next releases.
Please try to convert to it and report any problems.
See http://mesonbuild.com/Quick-guide.html for basic usage, the
meson_options.txt for the project-specific configuration options,
and the PACKAGING file for more details.
There are some noteworthy differences compared to the autotools build:
- Feature auto-detection is not performed. By default, all features are
enabled (currently: docs, x11, wayland). The build fails if any of
the required dependencies are not available. To disable a feature,
pass -Denable-<feature>=false to meson.
- The libraries are either installed as shared or static, as specified
by the -Ddefault_library=shared/static option. With autotools, both
versions are installed by default.
- xorg-util-macros is not used.
- A parser generator (bison/byacc) is always required - there is no
fallback to pre-generated output bundled in the tarball, as there is
in autotools.
- Removed Android.mk support.
- Removed the *-uninstalled.pc pkgconfig files.
- Ported the interactive-wayland demo program to v6 of the xdg-shell
protocol.
- Added new keysym definitions from xproto.
- New API:
XKB_KEY_XF86Keyboard
XKB_KEY_XF86WWAN
XKB_KEY_XF86RFKill
XKB_KEY_XF86AudioPreset
libxkbcommon 0.7.1 - 2017-01-18
==================
- Fixed various reported problems when the current locale is tr_TR.UTF-8.
The function xkb_keysym_from_name() used to perform case-insensitive
string comparisons in a locale-dependent way, but required it to to
work as in the C/ASCII locale (the so called "Turkish i problem").
The function is now no longer affected by the current locale.
- Fixed compilation in NetBSD.
libxkbcommon 0.7.0 - 2016-11-11
==================
- Added support for different "modes" of calculating consumed modifiers.
The existing mode, based on the XKB standard, has proven to be
unintuitive in various shortcut implementations.
A new mode, based on the calculation used by the GTK toolkit, is added.
This mode is less eager to declare a modifier as consumed.
- Added a new interactive demo program using the Wayland protocol.
See the PACKAGING file for the new (optional) test dependencies.
- Fixed a compilation error on GNU Hurd.
- New API:
enum xkb_consumed_mode
XKB_CONSUMED_MODE_XKB
XKB_CONSUMED_MODE_GTK
xkb_state_key_get_consumed_mods2
xkb_state_mod_index_is_consumed2
libxkbcommon 0.6.1 - 2016-04-08
==================
- Added LICENSE to distributed files in tarball releases.
- Minor typo fix in xkb_keymap_get_as_string() documentation.
libxkbcommon 0.6.0 - 2016-03-16
==================
- If the XKB_CONFIG_ROOT environment variable is set, it is used as the XKB
configuration root instead of the path determined at build time.
- Tests and benchmarks now build correctly on OSX.
- An XKB keymap provides a name for each key it defines. Traditionally,
these names are limited to at most 4 characters, and are thus somewhat
obscure, but might still be useful (xkbcommon lifts the 4 character limit).
The new functions xkb_keymap_key_get_name() and xkb_keymap_key_by_name()
can be used to get the name of a key or find a key by name. Note that
a key may have aliases.
- Documentation improvements.
- New API:
xkb_keymap_key_by_name()
xkb_keymap_key_get_name()
libxkbcommon 0.5.0 - 2014-10-18
==================
@ -42,6 +589,7 @@ libxkbcommon 0.5.0 - 2014-10-18
XKB_COMPOSE_*
xkb_compose_*
libxkbcommon 0.4.3 - 2014-08-19
==================
@ -65,6 +613,7 @@ libxkbcommon 0.4.3 - 2014-08-19
- Fixed memory leaks after parse errors in the XKB yacc parser.
The fix required changes which are currently incompatible with byacc.
libxkbcommon 0.4.2 - 2014-05-15
==================
@ -87,6 +636,7 @@ libxkbcommon 0.4.2 - 2014-05-15
Note: it seems impossible to trigger in the current code since the input
size cannot exceed the required size.
libxkbcommon 0.4.1 - 2014-03-27
==================
@ -104,7 +654,7 @@ libxkbcommon 0.4.1 - 2014-03-27
is converted to an appropriate control character.
This matches the behavior of libX11's XLookupString(3), and
required by the XKB specification:
http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier
https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier
https://bugs.freedesktop.org/show_bug.cgi?id=75892
@ -130,6 +680,7 @@ libxkbcommon 0.4.1 - 2014-03-27
- Bug fixes.
libxkbcommon 0.4.0 - 2014-02-02
==================
@ -166,7 +717,7 @@ libxkbcommon 0.3.2 - 2013-11-22
- Apply capitalization transformation on keysyms in
xkb_keysym_get_one_sym(), to match the behavior specified in the XKB
specification:
http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier
https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier
- Support byacc for generating the parser, in addition to Bison.

View File

@ -1,26 +1,30 @@
libxkbcommon consists of two shared libraries, libxkbcommon (the main
library) and libxkbcommon-x11 (an addon library for XCB clients).
libxkbcommon consists of three shared libraries, libxkbcommon (the main
library), libxkbcommon-x11 (an addon library for XCB clients) and libxkbregistry
(a library to list available RMLVO options).
The files for libxkbcommon-x11 are:
libxkbcommon-x11.a libxkbcommon.so* xkbcommon/xkbcommon-x11.h
libxkbcommon-x11.a libxkbcommon-x11.so* xkbcommon/xkbcommon-x11.h
xkbcommon-x11.map xkbcommon-x11.pc
libxkbcommon-x11 can be disabled with --disable-x11 (see
`./configure --help` for other options/variables).
libxkbcommon-x11 can be disabled with -Denable-x11=false (see
`meson configure build` for other options/variables).
The files for libxkbregistry are:
libxkbregistry.a libxkbregistry.so* xkbcommon/xkbregistry.h
xkbregistry.map xkbregistry.pc
libxkbregistry can be disabled with -Denable-xkbregistry=false (see
`meson configure build` for other options/variables).
Dependencies for libxkbcommon:
- C compiler, autoconf, automake, pkg-config, libc, etc.
- C compiler, meson, pkg-config, libc.
- (build optional) xorg-util-macros.
Output included in tarball.
- (build optional) bison (preferred) or byacc>=20141006.
Output included in tarball.
- (build) bison (preferred), win_bison or byacc>=20141006.
byacc must be configured with --enable-btyacc.
- (build optional, runtime) xkeyboard-config.
- (build optional, runtime required) xkeyboard-config.
During build, for automatically detecting the value of
--with-xkb-config-root instead of guessing (/usr/share/X11/xkb).
-Dxkb-config-root instead of guessing (/usr/share/X11/xkb).
During runtime, not strictly needed, but most users of the library
would need it.
@ -30,10 +34,14 @@ Dependencies for libxkbcommon:
- (build optional) doxygen.
For generating the HTML documentation.
To disable, use -Denable-docs=false.
- (build optional) gperf.
Output included in git and tarball. To regenerate, use
`make update-keywords`.
`./scripts/update-keywords`.
Dependencies for xkbcli:
- libxkbcommon.
Dependencies for libxkbcommon-x11:
- libxkbcommon.
@ -44,7 +52,25 @@ Dependencies for libxkbcommon-x11 tests:
- xkbcomp, Xvfb.
If they are not available, the relevant tests are skipped.
Dependencies for libxkbregistry:
- libxkbregistry is a sublibrary of libxkbcommon and cannot be built without
building libxbkcommon. The files produced are otherwise independent.
- libxml2
- (build optional, runtime requirement) xkeyboard-config
During build, for automatically detecting the value of
-Dxkb-config-root instead of guessing (/usr/share/X11/xkb).
Dependencies for Wayland tests:
- wayland-client>=1.2.0, wayland-scanner, wayland-protocols>=1.0.
To disable, use -Denable-wayland=false.
Unless libxcb is always available as part of the system, it is preferred
that libxkbcommon and libxkbcommon-x11 be split into separate packages,
such that the main library does not depend on libxcb. This avoids a
transitive dependency of Wayland clients on X libraries.
It is perferred that libxkbregistry be split into a separate packages as most
clients that require libxkbcommon do not require libxkbregistry and clients
requiring libxkbregistry may not need libxkbcommon.

View File

@ -3,19 +3,35 @@
libxkbcommon is a keyboard keymap compiler and support library which
processes a reduced subset of keymaps as defined by the XKB (X Keyboard
Extension) specification. It also contains a module for handling Compose
and dead keys.
and dead keys and a separate library for listing available keyboard layouts.
## Quick Guide
See [Quick Guide](doc/quick-guide.md).
## Building
libxkbcommon is built with [Meson](http://mesonbuild.com/):
meson setup build
ninja -C build
To build for use with Wayland, you can disable X11 support while still
using the X11 keyboard configuration resource files thusly:
meson setup build \
-Denable-x11=false \
-Dxkb-config-root=/usr/share/X11/xkb \
-Dx-locale-root=/usr/share/X11/locale
ninja -C build
## API
While libxkbcommon's API is somewhat derived from the classic XKB API as found
in X11/extensions/XKB.h and friends, it has been substantially reworked to
expose fewer internal details to clients.
See the [API Documentation](http://xkbcommon.org/doc/current/modules.html).
See the [API Documentation](https://xkbcommon.org/doc/current/modules.html).
## Dataset
@ -23,7 +39,7 @@ libxkbcommon does not distribute a keymap dataset itself, other than for
testing purposes. The most common dataset is xkeyboard-config, which is used
by all current distributions for their X11 XKB data. More information on
xkeyboard-config is available here:
http://www.freedesktop.org/wiki/Software/XKeyboardConfig
https://www.freedesktop.org/wiki/Software/XKeyboardConfig
The dataset for Compose is distributed in libX11, as part of the X locale
data.
@ -35,23 +51,21 @@ See [Compatibility](doc/compat.md) notes.
## Development
An extremely rudimentary homepage can be found at
http://xkbcommon.org
https://xkbcommon.org
xkbcommon is maintained in git at
https://github.com/xkbcommon/libxkbcommon
Patches are always welcome, and may be sent to either
<xorg-devel@lists.x.org> or <wayland-devel@lists.freedesktop.org>
or through github.
or in a [GitHub](https://github.com/xkbcommon/libxkbcommon) pull request.
Bugs are also welcome, and may be reported either at
Bugzilla https://bugs.freedesktop.org/describecomponents.cgi?product=libxkbcommon
or
Github https://github.com/xkbcommon/libxkbcommon/issues
Bug reports (and usage questions) are also welcome, and may be filed at
[GitHub](https://github.com/xkbcommon/libxkbcommon/issues).
The maintainers are
- Daniel Stone <daniel@fooishbar.org>
- Ran Benita <ran234@gmail.com>
- Ran Benita <ran@unusedvar.com>
## Credits

View File

@ -1,14 +0,0 @@
#!/bin/sh -e
srcdir=`dirname "$0"`
test -z "$srcdir" && srcdir=.
ORIGDIR=`pwd`
cd "$srcdir"
autoreconf --verbose --install --force --warnings=all
cd "$ORIGDIR"
if test -z "$NOCONFIGURE"; then
exec "$srcdir/configure" "$@"
fi

View File

@ -1,4 +0,0 @@
key-proc
rules
rulescomp
compose

View File

@ -0,0 +1,93 @@
/*
* Copyright © 2021 Ran Benita <ran@unusedvar.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "atom.h"
#include "bench.h"
#include "darray.h"
#define BENCHMARK_ITERATIONS 100
int
main(void)
{
FILE *file;
char wordbuf[1024];
darray(char *) words;
char **worditer;
struct atom_table *table;
xkb_atom_t atom;
const char *text;
struct bench bench;
char *elapsed;
darray_init(words);
file = fopen("/usr/share/dict/words", "rb");
if (file == NULL) {
perror("/usr/share/dict/words");
return -1;
}
while (fgets(wordbuf, sizeof(wordbuf), file)) {
size_t len = strlen(wordbuf);
if (len > 0 && wordbuf[len - 1] == '\n')
wordbuf[len - 1] = '\0';
darray_append(words, strdup(wordbuf));
}
fclose(file);
bench_start(&bench);
for (int i = 0; i < BENCHMARK_ITERATIONS; i++) {
table = atom_table_new();
assert(table);
darray_foreach(worditer, words) {
atom = atom_intern(table, *worditer, strlen(*worditer) - 1, true);
assert(atom != XKB_ATOM_NONE);
text = atom_text(table, atom);
assert(text != NULL);
}
atom_table_free(table);
}
bench_stop(&bench);
elapsed = bench_elapsed_str(&bench);
fprintf(stderr, "%d iterations in %ss\n",
BENCHMARK_ITERATIONS, elapsed);
free(elapsed);
darray_foreach(worditer, words) {
free(*worditer);
}
darray_free(words);
return 0;
}

View File

@ -0,0 +1,108 @@
/*
* Copyright © 2015 Kazunobu Kuriyama <kazunobu.kuriyama@nifty.com>
* Ran Benita <ran234@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include <assert.h>
#include <stdio.h>
#include "bench.h"
#include "../src/utils.h"
#ifndef _MSC_VER
#include <sys/time.h>
#else
#include <windows.h>
#include <stdint.h>
struct timeval {
long tv_sec, tv_usec;
};
static int
gettimeofday(struct timeval *tv, void *unused)
{
static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL);
SYSTEMTIME system_time;
FILETIME file_time;
uint64_t t;
GetSystemTime(&system_time);
SystemTimeToFileTime(&system_time, &file_time);
t = (uint64_t) file_time.dwLowDateTime;
t += ((uint64_t) file_time.dwHighDateTime) << 32;
tv->tv_sec = (long) ((t - EPOCH) / 10000000L);
tv->tv_usec = (long) (system_time.wMilliseconds * 1000);
return 0;
}
#endif
void
bench_start(struct bench *bench)
{
struct timeval val;
(void) gettimeofday(&val, NULL);
bench->start = (struct bench_time) {
.seconds = val.tv_sec,
.microseconds = val.tv_usec,
};
}
void
bench_stop(struct bench *bench)
{
struct timeval val;
(void) gettimeofday(&val, NULL);
bench->stop = (struct bench_time) {
.seconds = val.tv_sec,
.microseconds = val.tv_usec,
};
}
void
bench_elapsed(const struct bench *bench, struct bench_time *result)
{
result->seconds = bench->stop.seconds - bench->start.seconds;
result->microseconds = bench->stop.microseconds - bench->start.microseconds;
if (result->microseconds < 0) {
result->microseconds += 1000000;
result->seconds--;
}
}
char *
bench_elapsed_str(const struct bench *bench)
{
struct bench_time elapsed;
char *buf;
int ret;
bench_elapsed(bench, &elapsed);
ret = asprintf(&buf, "%ld.%06ld", elapsed.seconds, elapsed.microseconds);
assert(ret >= 0);
return buf;
}

View File

@ -0,0 +1,49 @@
/*
* Copyright © 2015 Kazunobu Kuriyama <kazunobu.kuriyama@nifty.com>
* Ran Benita <ran234@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef LIBXKBCOMMON_BENCH_H
#define LIBXKBCOMMON_BENCH_H
struct bench_time {
long seconds;
long microseconds;
};
struct bench {
struct bench_time start;
struct bench_time stop;
};
void
bench_start(struct bench *bench);
void
bench_stop(struct bench *bench);
void
bench_elapsed(const struct bench *bench, struct bench_time *result);
/* The caller is responsibile to free() the returned string. */
char *
bench_elapsed_str(const struct bench *bench);
#endif /* LIBXKBCOMMON_BENCH_H */

View File

@ -21,11 +21,14 @@
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include <time.h>
#include "xkbcommon/xkbcommon-compose.h"
#include "../test/test.h"
#include "bench.h"
#define BENCHMARK_ITERATIONS 1000
@ -33,21 +36,28 @@ int
main(void)
{
struct xkb_context *ctx;
struct timespec start, stop, elapsed;
char *path;
FILE *file;
struct xkb_compose_table *table;
struct bench bench;
char *elapsed;
ctx = test_get_context(CONTEXT_NO_FLAG);
assert(ctx);
path = test_get_path("compose/en_US.UTF-8/Compose");
file = fopen(path, "r");
path = test_get_path("locale/en_US.UTF-8/Compose");
file = fopen(path, "rb");
if (file == NULL) {
perror(path);
free(path);
xkb_context_unref(ctx);
return -1;
}
xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_CRITICAL);
xkb_context_set_log_verbosity(ctx, 0);
clock_gettime(CLOCK_MONOTONIC, &start);
bench_start(&bench);
for (int i = 0; i < BENCHMARK_ITERATIONS; i++) {
rewind(file);
table = xkb_compose_table_new_from_file(ctx, file, "",
@ -56,20 +66,15 @@ main(void)
assert(table);
xkb_compose_table_unref(table);
}
clock_gettime(CLOCK_MONOTONIC, &stop);
bench_stop(&bench);
fclose(file);
free(path);
elapsed.tv_sec = stop.tv_sec - start.tv_sec;
elapsed.tv_nsec = stop.tv_nsec - start.tv_nsec;
if (elapsed.tv_nsec < 0) {
elapsed.tv_nsec += 1000000000;
elapsed.tv_sec--;
}
fprintf(stderr, "compiled %d compose tables in %ld.%09lds\n",
BENCHMARK_ITERATIONS, elapsed.tv_sec, elapsed.tv_nsec);
elapsed = bench_elapsed_str(&bench);
fprintf(stderr, "compiled %d compose tables in %ss\n",
BENCHMARK_ITERATIONS, elapsed);
free(elapsed);
xkb_context_unref(ctx);
return 0;

View File

@ -21,15 +21,18 @@
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include <stdlib.h>
#include <time.h>
#include "../test/test.h"
#include "bench.h"
#define BENCHMARK_ITERATIONS 20000000
static void
bench(struct xkb_state *state)
bench_key_proc(struct xkb_state *state)
{
int8_t keys[256] = { 0 };
xkb_keycode_t keycode;
@ -56,7 +59,8 @@ main(void)
struct xkb_context *ctx;
struct xkb_keymap *keymap;
struct xkb_state *state;
struct timespec start, stop, elapsed;
struct bench bench;
char *elapsed;
ctx = test_get_context(0);
assert(ctx);
@ -71,21 +75,16 @@ main(void)
xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_CRITICAL);
xkb_context_set_log_verbosity(ctx, 0);
srand(time(NULL));
srand((unsigned) time(NULL));
clock_gettime(CLOCK_MONOTONIC, &start);
bench(state);
clock_gettime(CLOCK_MONOTONIC, &stop);
bench_start(&bench);
bench_key_proc(state);
bench_stop(&bench);
elapsed.tv_sec = stop.tv_sec - start.tv_sec;
elapsed.tv_nsec = stop.tv_nsec - start.tv_nsec;
if (elapsed.tv_nsec < 0) {
elapsed.tv_nsec += 1000000000;
elapsed.tv_sec--;
}
fprintf(stderr, "ran %d iterations in %ld.%09lds\n",
BENCHMARK_ITERATIONS, elapsed.tv_sec, elapsed.tv_nsec);
elapsed = bench_elapsed_str(&bench);
fprintf(stderr, "ran %d iterations in %ss\n",
BENCHMARK_ITERATIONS, elapsed);
free(elapsed);
xkb_state_unref(state);
xkb_keymap_unref(keymap);

View File

@ -21,11 +21,14 @@
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include <time.h>
#include "../test/test.h"
#include "xkbcomp-priv.h"
#include "rules.h"
#include "xkbcomp/xkbcomp-priv.h"
#include "xkbcomp/rules.h"
#include "bench.h"
#define BENCHMARK_ITERATIONS 20000
@ -33,12 +36,12 @@ int
main(int argc, char *argv[])
{
struct xkb_context *ctx;
struct timespec start, stop, elapsed;
int i;
struct xkb_rule_names rmlvo = {
"evdev", "pc105", "us,il", ",", "ctrl:nocaps,grp:menu_toggle",
};
struct xkb_component_names kccgst;
struct bench bench;
char *elapsed;
ctx = test_get_context(0);
assert(ctx);
@ -46,25 +49,22 @@ main(int argc, char *argv[])
xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_CRITICAL);
xkb_context_set_log_verbosity(ctx, 0);
clock_gettime(CLOCK_MONOTONIC, &start);
bench_start(&bench);
for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
struct xkb_component_names kccgst;
assert(xkb_components_from_rules(ctx, &rmlvo, &kccgst));
free(kccgst.keycodes);
free(kccgst.types);
free(kccgst.compat);
free(kccgst.symbols);
}
clock_gettime(CLOCK_MONOTONIC, &stop);
bench_stop(&bench);
elapsed.tv_sec = stop.tv_sec - start.tv_sec;
elapsed.tv_nsec = stop.tv_nsec - start.tv_nsec;
if (elapsed.tv_nsec < 0) {
elapsed.tv_nsec += 1000000000;
elapsed.tv_sec--;
}
fprintf(stderr, "processed %d rule files in %ld.%09lds\n",
BENCHMARK_ITERATIONS, elapsed.tv_sec, elapsed.tv_nsec);
elapsed = bench_elapsed_str(&bench);
fprintf(stderr, "processed %d rule files in %ss\n",
BENCHMARK_ITERATIONS, elapsed);
free(elapsed);
xkb_context_unref(ctx);
return 0;

View File

@ -21,18 +21,22 @@
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include <time.h>
#include "../test/test.h"
#include "bench.h"
#define BENCHMARK_ITERATIONS 2500
#define BENCHMARK_ITERATIONS 1000
int
main(int argc, char *argv[])
{
struct xkb_context *ctx;
struct xkb_keymap *keymap;
struct timespec start, stop, elapsed;
struct bench bench;
char *elapsed;
int i;
ctx = test_get_context(0);
@ -41,23 +45,18 @@ main(int argc, char *argv[])
xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_CRITICAL);
xkb_context_set_log_verbosity(ctx, 0);
clock_gettime(CLOCK_MONOTONIC, &start);
bench_start(&bench);
for (i = 0; i < BENCHMARK_ITERATIONS; i++) {
keymap = test_compile_rules(ctx, "evdev", "evdev", "us", "", "");
assert(keymap);
xkb_keymap_unref(keymap);
}
clock_gettime(CLOCK_MONOTONIC, &stop);
bench_stop(&bench);
elapsed.tv_sec = stop.tv_sec - start.tv_sec;
elapsed.tv_nsec = stop.tv_nsec - start.tv_nsec;
if (elapsed.tv_nsec < 0) {
elapsed.tv_nsec += 1000000000;
elapsed.tv_sec--;
}
fprintf(stderr, "compiled %d keymaps in %ld.%09lds\n",
BENCHMARK_ITERATIONS, elapsed.tv_sec, elapsed.tv_nsec);
elapsed = bench_elapsed_str(&bench);
fprintf(stderr, "compiled %d keymaps in %ss\n",
BENCHMARK_ITERATIONS, elapsed);
free(elapsed);
xkb_context_unref(ctx);
return 0;

View File

@ -0,0 +1,108 @@
/*
* Copyright © 2020 Ran Benita <ran@unusedvar.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include <assert.h>
#include <stdlib.h>
#include <xcb/xkb.h>
#include "xkbcommon/xkbcommon.h"
#include "xkbcommon/xkbcommon-x11.h"
#include "bench.h"
#define BENCHMARK_ITERATIONS 2500
int
main(void)
{
int ret;
xcb_connection_t *conn;
int32_t device_id;
struct xkb_context *ctx;
struct bench bench;
char *elapsed;
conn = xcb_connect(NULL, NULL);
if (!conn || xcb_connection_has_error(conn)) {
fprintf(stderr, "Couldn't connect to X server: error code %d\n",
conn ? xcb_connection_has_error(conn) : -1);
ret = -1;
goto err_out;
}
ret = xkb_x11_setup_xkb_extension(conn,
XKB_X11_MIN_MAJOR_XKB_VERSION,
XKB_X11_MIN_MINOR_XKB_VERSION,
XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS,
NULL, NULL, NULL, NULL);
if (!ret) {
fprintf(stderr, "Couldn't setup XKB extension\n");
goto err_conn;
}
device_id = xkb_x11_get_core_keyboard_device_id(conn);
if (device_id == -1) {
ret = -1;
fprintf(stderr, "Couldn't find core keyboard device\n");
goto err_conn;
}
ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (!ctx) {
ret = -1;
fprintf(stderr, "Couldn't create xkb context\n");
goto err_conn;
}
bench_start(&bench);
for (int i = 0; i < BENCHMARK_ITERATIONS; i++) {
struct xkb_keymap *keymap;
struct xkb_state *state;
keymap = xkb_x11_keymap_new_from_device(ctx, conn, device_id,
XKB_KEYMAP_COMPILE_NO_FLAGS);
assert(keymap);
state = xkb_x11_state_new_from_device(keymap, conn, device_id);
assert(state);
xkb_state_unref(state);
xkb_keymap_unref(keymap);
}
bench_stop(&bench);
ret = 0;
elapsed = bench_elapsed_str(&bench);
fprintf(stderr, "retrieved %d keymaps from X in %ss\n",
BENCHMARK_ITERATIONS, elapsed);
free(elapsed);
xkb_context_unref(ctx);
err_conn:
xcb_disconnect(conn);
err_out:
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}

View File

@ -1,347 +0,0 @@
#! /bin/sh
# Wrapper for compilers which do not understand '-c -o'.
scriptversion=2012-10-14.11; # UTC
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
nl='
'
# We need space, tab and new line, in precisely that order. Quoting is
# there to prevent tools from complaining about whitespace usage.
IFS=" "" $nl"
file_conv=
# func_file_conv build_file lazy
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts. If the determined conversion
# type is listed in (the comma separated) LAZY, no conversion will
# take place.
func_file_conv ()
{
file=$1
case $file in
/ | /[!/]*) # absolute file, and not a UNC file
if test -z "$file_conv"; then
# lazily determine how to convert abs files
case `uname -s` in
MINGW*)
file_conv=mingw
;;
CYGWIN*)
file_conv=cygwin
;;
*)
file_conv=wine
;;
esac
fi
case $file_conv/,$2, in
*,$file_conv,*)
;;
mingw/*)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin/*)
file=`cygpath -m "$file" || echo "$file"`
;;
wine/*)
file=`winepath -w "$file" || echo "$file"`
;;
esac
;;
esac
}
# func_cl_dashL linkdir
# Make cl look for libraries in LINKDIR
func_cl_dashL ()
{
func_file_conv "$1"
if test -z "$lib_path"; then
lib_path=$file
else
lib_path="$lib_path;$file"
fi
linker_opts="$linker_opts -LIBPATH:$file"
}
# func_cl_dashl library
# Do a library search-path lookup for cl
func_cl_dashl ()
{
lib=$1
found=no
save_IFS=$IFS
IFS=';'
for dir in $lib_path $LIB
do
IFS=$save_IFS
if $shared && test -f "$dir/$lib.dll.lib"; then
found=yes
lib=$dir/$lib.dll.lib
break
fi
if test -f "$dir/$lib.lib"; then
found=yes
lib=$dir/$lib.lib
break
fi
if test -f "$dir/lib$lib.a"; then
found=yes
lib=$dir/lib$lib.a
break
fi
done
IFS=$save_IFS
if test "$found" != yes; then
lib=$lib.lib
fi
}
# func_cl_wrapper cl arg...
# Adjust compile command to suit cl
func_cl_wrapper ()
{
# Assume a capable shell
lib_path=
shared=:
linker_opts=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
eat=1
case $2 in
*.o | *.[oO][bB][jJ])
func_file_conv "$2"
set x "$@" -Fo"$file"
shift
;;
*)
func_file_conv "$2"
set x "$@" -Fe"$file"
shift
;;
esac
;;
-I)
eat=1
func_file_conv "$2" mingw
set x "$@" -I"$file"
shift
;;
-I*)
func_file_conv "${1#-I}" mingw
set x "$@" -I"$file"
shift
;;
-l)
eat=1
func_cl_dashl "$2"
set x "$@" "$lib"
shift
;;
-l*)
func_cl_dashl "${1#-l}"
set x "$@" "$lib"
shift
;;
-L)
eat=1
func_cl_dashL "$2"
;;
-L*)
func_cl_dashL "${1#-L}"
;;
-static)
shared=false
;;
-Wl,*)
arg=${1#-Wl,}
save_ifs="$IFS"; IFS=','
for flag in $arg; do
IFS="$save_ifs"
linker_opts="$linker_opts $flag"
done
IFS="$save_ifs"
;;
-Xlinker)
eat=1
linker_opts="$linker_opts $2"
;;
-*)
set x "$@" "$1"
shift
;;
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
func_file_conv "$1"
set x "$@" -Tp"$file"
shift
;;
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
func_file_conv "$1" mingw
set x "$@" "$file"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -n "$linker_opts"; then
linker_opts="-link$linker_opts"
fi
exec "$@" $linker_opts
exit 1
}
eat=
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: compile [--help] [--version] PROGRAM [ARGS]
Wrapper for compilers which do not understand '-c -o'.
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
arguments, and rename the output as expected.
If you are trying to build a whole package this is not the
right script to run: please start by reading the file 'INSTALL'.
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "compile $scriptversion"
exit $?
;;
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
func_cl_wrapper "$@" # Doesn't return...
;;
esac
ofile=
cfile=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
# So we strip '-o arg' only if arg is an object.
eat=1
case $2 in
*.o | *.obj)
ofile=$2
;;
*)
set x "$@" -o "$2"
shift
;;
esac
;;
*.c)
cfile=$1
set x "$@" "$1"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -z "$ofile" || test -z "$cfile"; then
# If no '-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# '.c' file was seen then we are probably linking. That is also
# ok.
exec "$@"
fi
# Name of file we expect compiler to create.
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
# Create the lock directory.
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
while true; do
if mkdir "$lockdir" >/dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir '$lockdir'; exit 1" 1 2 15
# Run the compile.
"$@"
ret=$?
if test -f "$cofile"; then
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
elif test -f "${cofile}bj"; then
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
fi
rmdir "$lockdir"
exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,791 +0,0 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2013-05-30.07; # UTC
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
Run PROGRAMS ARGS to compile a file, generating dependencies
as side-effects.
Environment variables:
depmode Dependency tracking mode.
source Source file read by 'PROGRAMS ARGS'.
object Object file output by 'PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputting dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "depcomp $scriptversion"
exit $?
;;
esac
# Get the directory component of the given path, and save it in the
# global variables '$dir'. Note that this directory component will
# be either empty or ending with a '/' character. This is deliberate.
set_dir_from ()
{
case $1 in
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
*) dir=;;
esac
}
# Get the suffix-stripped basename of the given path, and save it the
# global variable '$base'.
set_base_from ()
{
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
}
# If no dependency file was actually created by the compiler invocation,
# we still have to create a dummy depfile, to avoid errors with the
# Makefile "include basename.Plo" scheme.
make_dummy_depfile ()
{
echo "#dummy" > "$depfile"
}
# Factor out some common post-processing of the generated depfile.
# Requires the auxiliary global variable '$tmpdepfile' to be set.
aix_post_process_depfile ()
{
# If the compiler actually managed to produce a dependency file,
# post-process it.
if test -f "$tmpdepfile"; then
# Each line is of the form 'foo.o: dependency.h'.
# Do two passes, one to just change these to
# $object: dependency.h
# and one to simply output
# dependency.h:
# which is needed to avoid the deleted-header problem.
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
} > "$depfile"
rm -f "$tmpdepfile"
else
make_dummy_depfile
fi
}
# A tabulation character.
tab=' '
# A newline character.
nl='
'
# Character ranges might be problematic outside the C locale.
# These definitions help.
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
lower=abcdefghijklmnopqrstuvwxyz
digits=0123456789
alpha=${upper}${lower}
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
depfile=${depfile-`echo "$object" |
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Avoid interferences from the environment.
gccflag= dashmflag=
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
cygpath_u="cygpath -u -f -"
if test "$depmode" = msvcmsys; then
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvisualcpp
fi
if test "$depmode" = msvc7msys; then
# This is just like msvc7 but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvc7
fi
if test "$depmode" = xlc; then
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
gccflag=-qmakedep=gcc,-MF
depmode=gcc
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
## the command line argument order; so add the flags where they
## appear in depend2.am. Note that the slowdown incurred here
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
for arg
do
case $arg in
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
*) set fnord "$@" "$arg" ;;
esac
shift # fnord
shift # $arg
done
"$@"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
## (see the conditional assignment to $gccflag above).
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say). Also, it might not be
## supported by the other compilers which use the 'gcc' depmode.
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The second -e expression handles DOS-style file names with drive
# letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the "deleted header file" problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
## Some versions of gcc put a space before the ':'. On the theory
## that the space means something, we add a space to the output as
## well. hp depmode also adds that space, but also prefixes the VPATH
## to the object. Take care to not repeat it in the output.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like '#:fec' to the end of the
# dependency line.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
| tr "$nl" ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile"
;;
xlc)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts '$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
tmpdepfile3=$dir.libs/$base.u
"$@" -Wc,-M
else
tmpdepfile1=$dir$base.u
tmpdepfile2=$dir$base.u
tmpdepfile3=$dir$base.u
"$@" -M
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
aix_post_process_depfile
;;
tcc)
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
# FIXME: That version still under development at the moment of writing.
# Make that this statement remains true also for stable, released
# versions.
# It will wrap lines (doesn't matter whether long or short) with a
# trailing '\', as in:
#
# foo.o : \
# foo.c \
# foo.h \
#
# It will put a trailing '\' even on the last line, and will use leading
# spaces rather than leading tabs (at least since its commit 0394caf7
# "Emit spaces for -MD").
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
# We have to change lines of the first kind to '$object: \'.
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
# And for each line of the second kind, we have to emit a 'dep.h:'
# dummy dependency, to avoid the deleted-header problem.
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
rm -f "$tmpdepfile"
;;
## The order of this option in the case statement is important, since the
## shell code in configure will try each of these formats in the order
## listed in this file. A plain '-MD' option would be understood by many
## compilers, so we must ensure this comes after the gcc and icc options.
pgcc)
# Portland's C compiler understands '-MD'.
# Will always output deps to 'file.d' where file is the root name of the
# source file under compilation, even if file resides in a subdirectory.
# The object file name does not affect the name of the '.d' file.
# pgcc 10.2 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using '\' :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
set_dir_from "$object"
# Use the source, not the object, to determine the base name, since
# that's sadly what pgcc will do too.
set_base_from "$source"
tmpdepfile=$base.d
# For projects that build the same source file twice into different object
# files, the pgcc approach of using the *source* file root name can cause
# problems in parallel builds. Use a locking strategy to avoid stomping on
# the same $tmpdepfile.
lockdir=$base.d-lock
trap "
echo '$0: caught signal, cleaning up...' >&2
rmdir '$lockdir'
exit 1
" 1 2 13 15
numtries=100
i=$numtries
while test $i -gt 0; do
# mkdir is a portable test-and-set.
if mkdir "$lockdir" 2>/dev/null; then
# This process acquired the lock.
"$@" -MD
stat=$?
# Release the lock.
rmdir "$lockdir"
break
else
# If the lock is being held by a different process, wait
# until the winning process is done or we timeout.
while test -d "$lockdir" && test $i -gt 0; do
sleep 1
i=`expr $i - 1`
done
fi
i=`expr $i - 1`
done
trap - 1 2 13 15
if test $i -le 0; then
echo "$0: failed to acquire lock after $numtries attempts" >&2
echo "$0: check lockdir '$lockdir'" >&2
exit 1
fi
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp2)
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
# compilers, which have integrated preprocessors. The correct option
# to use with these is +Maked; it writes dependencies to a file named
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
"$@" -Wc,+Maked
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
"$@" +Maked
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
# Add 'dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
s/$/:/
p
}' "$tmpdepfile" >> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in 'foo.d' instead, so we check for that too.
# Subdirectories are respected.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
# Libtool generates 2 separate objects for the 2 libraries. These
# two compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir$base.o.d # libtool 1.5
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
# Same post-processing that is required for AIX mode.
aix_post_process_depfile
;;
msvc7)
if test "$libtool" = yes; then
showIncludes=-Wc,-showIncludes
else
showIncludes=-showIncludes
fi
"$@" $showIncludes > "$tmpdepfile"
stat=$?
grep -v '^Note: including file: ' "$tmpdepfile"
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The first sed program below extracts the file names and escapes
# backslashes for cygpath. The second sed program outputs the file
# name when reading, but also accumulates all include files in the
# hold buffer in order to output them again at the end. This only
# works with sed implementations that can handle large buffers.
sed < "$tmpdepfile" -n '
/^Note: including file: *\(.*\)/ {
s//\1/
s/\\/\\\\/g
p
}' | $cygpath_u | sort -u | sed -n '
s/ /\\ /g
s/\(.*\)/'"$tab"'\1 \\/p
s/.\(.*\) \\/\1:/
H
$ {
s/.*/'"$tab"'/
G
p
}' >> "$depfile"
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
rm -f "$tmpdepfile"
;;
msvc7msys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for ':'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
"$@" $dashmflag |
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this sed invocation
# correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no eat=no
for arg
do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
if test $eat = yes; then
eat=no
continue
fi
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-arch)
eat=yes ;;
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix=`echo "$object" | sed 's/^.*\././'`
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
# makedepend may prepend the VPATH from the source file name to the object.
# No need to regex-escape $object, excess matching of '.' is harmless.
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process the last invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed '1,2d' "$tmpdepfile" \
| tr ' ' "$nl" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E \
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
| sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
IFS=" "
for arg
do
case "$arg" in
-o)
shift
;;
$object)
shift
;;
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E 2>/dev/null |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
echo "$tab" >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvcmsys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

View File

@ -1,527 +0,0 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2011-11-20.07; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
nl='
'
IFS=" "" $nl"
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit=${DOITPROG-}
if test -z "$doit"; then
doit_exec=exec
else
doit_exec=$doit
fi
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
posix_glob='?'
initialize_posix_glob='
test "$posix_glob" != "?" || {
if (set -f) 2>/dev/null; then
posix_glob=
else
posix_glob=:
fi
}
'
posix_mkdir=
# Desired mode of installed file.
mode=0755
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=
src=
dst=
dir_arg=
dst_arg=
copy_on_change=false
no_target_directory=
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
--help display this help and exit.
--version display version info and exit.
-c (ignored)
-C install only if different (preserve the last data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
"
while test $# -ne 0; do
case $1 in
-c) ;;
-C) copy_on_change=true;;
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
case $mode in
*' '* | *' '* | *'
'* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift;;
-s) stripcmd=$stripprog;;
-t) dst_arg=$2
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) no_target_directory=true;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dst_arg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dst_arg"
shift # fnord
fi
shift # arg
dst_arg=$arg
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
done
fi
if test $# -eq 0; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call 'install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
trap "ret=143; $do_exit" 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
case $mode in
# Optimize common cases.
*644) cp_umask=133;;
*755) cp_umask=22;;
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
fi
for src
do
# Protect names problematic for 'test' and other utilities.
case $src in
-* | [=\(\)!]) src=./$src;;
esac
if test -n "$dir_arg"; then
dst=$src
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dst_arg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dst_arg
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
if test -d "$dst"; then
if test -n "$no_target_directory"; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dst=$dstdir/`basename "$src"`
dstdir_status=0
else
# Prefer dirname, but fall back on a substitute if dirname fails.
dstdir=`
(dirname "$dst") 2>/dev/null ||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$dst" : 'X\(//\)[^/]' \| \
X"$dst" : 'X\(//\)$' \| \
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
echo X"$dst" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'
`
test -d "$dstdir"
dstdir_status=$?
fi
fi
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
if (umask $mkdir_umask &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
ls_ld_tmpdir=`ls -ld "$tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/d" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
fi
trap '' 0;;
esac;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# The umask is ridiculous, or mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix='/';;
[-=\(\)!]*) prefix='./';;
*) prefix='';;
esac
eval "$initialize_posix_glob"
oIFS=$IFS
IFS=/
$posix_glob set -f
set fnord $dstdir
shift
$posix_glob set +f
IFS=$oIFS
prefixes=
for d
do
test X"$d" = X && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
if test -n "$dir_arg"; then
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
else
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
eval "$initialize_posix_glob" &&
$posix_glob set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
$posix_glob set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
rm -f "$dsttmp"
else
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1
trap '' 0
fi
done
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

File diff suppressed because it is too large Load Diff

View File

@ -1,215 +0,0 @@
#! /bin/sh
# Common wrapper for a few potentially missing GNU programs.
scriptversion=2013-10-28.13; # UTC
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
echo 1>&2 "Try '$0 --help' for more information"
exit 1
fi
case $1 in
--is-lightweight)
# Used by our autoconf macros to check whether the available missing
# script is modern enough.
exit 0
;;
--run)
# Back-compat with the calling convention used by older automake.
shift
;;
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
to PROGRAM being missing or too old.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
Supported PROGRAM values:
aclocal autoconf autoheader autom4te automake makeinfo
bison yacc flex lex help2man
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
'g' are ignored when checking the name.
Send bug reports to <bug-automake@gnu.org>."
exit $?
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing $scriptversion (GNU Automake)"
exit $?
;;
-*)
echo 1>&2 "$0: unknown '$1' option"
echo 1>&2 "Try '$0 --help' for more information"
exit 1
;;
esac
# Run the given program, remember its exit status.
"$@"; st=$?
# If it succeeded, we are done.
test $st -eq 0 && exit 0
# Also exit now if we it failed (or wasn't found), and '--version' was
# passed; such an option is passed most likely to detect whether the
# program is present and works.
case $2 in --version|--help) exit $st;; esac
# Exit code 63 means version mismatch. This often happens when the user
# tries to use an ancient version of a tool on a file that requires a
# minimum version.
if test $st -eq 63; then
msg="probably too old"
elif test $st -eq 127; then
# Program was missing.
msg="missing on your system"
else
# Program was found and executed, but failed. Give up.
exit $st
fi
perl_URL=http://www.perl.org/
flex_URL=http://flex.sourceforge.net/
gnu_software_URL=http://www.gnu.org/software
program_details ()
{
case $1 in
aclocal|automake)
echo "The '$1' program is part of the GNU Automake package:"
echo "<$gnu_software_URL/automake>"
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/autoconf>"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
autoconf|autom4te|autoheader)
echo "The '$1' program is part of the GNU Autoconf package:"
echo "<$gnu_software_URL/autoconf/>"
echo "It also requires GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
esac
}
give_advice ()
{
# Normalize program name to check for.
normalized_program=`echo "$1" | sed '
s/^gnu-//; t
s/^gnu//; t
s/^g//; t'`
printf '%s\n' "'$1' is $msg."
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
case $normalized_program in
autoconf*)
echo "You should only need it if you modified 'configure.ac',"
echo "or m4 files included by it."
program_details 'autoconf'
;;
autoheader*)
echo "You should only need it if you modified 'acconfig.h' or"
echo "$configure_deps."
program_details 'autoheader'
;;
automake*)
echo "You should only need it if you modified 'Makefile.am' or"
echo "$configure_deps."
program_details 'automake'
;;
aclocal*)
echo "You should only need it if you modified 'acinclude.m4' or"
echo "$configure_deps."
program_details 'aclocal'
;;
autom4te*)
echo "You might have modified some maintainer files that require"
echo "the 'autom4te' program to be rebuilt."
program_details 'autom4te'
;;
bison*|yacc*)
echo "You should only need it if you modified a '.y' file."
echo "You may want to install the GNU Bison package:"
echo "<$gnu_software_URL/bison/>"
;;
lex*|flex*)
echo "You should only need it if you modified a '.l' file."
echo "You may want to install the Fast Lexical Analyzer package:"
echo "<$flex_URL>"
;;
help2man*)
echo "You should only need it if you modified a dependency" \
"of a man page."
echo "You may want to install the GNU Help2man package:"
echo "<$gnu_software_URL/help2man/>"
;;
makeinfo*)
echo "You should only need it if you modified a '.texi' file, or"
echo "any other file indirectly affecting the aspect of the manual."
echo "You might want to install the Texinfo package:"
echo "<$gnu_software_URL/texinfo/>"
echo "The spurious makeinfo call might also be the consequence of"
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
echo "want to install GNU make:"
echo "<$gnu_software_URL/make/>"
;;
*)
echo "You might have modified some files without having the proper"
echo "tools for further handling them. Check the 'README' file, it"
echo "often tells you about the needed prerequisites for installing"
echo "this package. You may also peek at any GNU archive site, in"
echo "case some other package contains this missing '$1' program."
;;
esac
}
give_advice "$1" | sed -e '1s/^/WARNING: /' \
-e '2,$s/^/ /' >&2
# Propagate the correct exit status (expected to be 127 for a program
# not found, 63 for a program that failed due to version mismatch).
exit $st
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,606 +0,0 @@
# This file was generated by Autom4te Thu Apr 10 10:06:43 UTC 2014.
# It contains the lists of macros which have been traced.
# It can be safely removed.
@request = (
bless( [
'0',
1,
[
'/usr/share/autoconf'
],
[
'/usr/share/autoconf/autoconf/autoconf.m4f',
'-',
'/usr/share/aclocal-1.14/internal/ac-config-macro-dirs.m4',
'/usr/share/aclocal/argz.m4',
'/usr/share/aclocal/libtool.m4',
'/usr/share/aclocal/ltdl.m4',
'/usr/share/aclocal/ltoptions.m4',
'/usr/share/aclocal/ltsugar.m4',
'/usr/share/aclocal/ltversion.m4',
'/usr/share/aclocal/lt~obsolete.m4',
'/usr/share/aclocal/pkg.m4',
'/usr/share/aclocal/xorg-macros.m4',
'/usr/share/aclocal-1.14/amversion.m4',
'/usr/share/aclocal-1.14/auxdir.m4',
'/usr/share/aclocal-1.14/cond.m4',
'/usr/share/aclocal-1.14/depend.m4',
'/usr/share/aclocal-1.14/depout.m4',
'/usr/share/aclocal-1.14/init.m4',
'/usr/share/aclocal-1.14/install-sh.m4',
'/usr/share/aclocal-1.14/lead-dot.m4',
'/usr/share/aclocal-1.14/maintainer.m4',
'/usr/share/aclocal-1.14/make.m4',
'/usr/share/aclocal-1.14/missing.m4',
'/usr/share/aclocal-1.14/options.m4',
'/usr/share/aclocal-1.14/prog-cc-c-o.m4',
'/usr/share/aclocal-1.14/runlog.m4',
'/usr/share/aclocal-1.14/sanity.m4',
'/usr/share/aclocal-1.14/silent.m4',
'/usr/share/aclocal-1.14/strip.m4',
'/usr/share/aclocal-1.14/substnot.m4',
'/usr/share/aclocal-1.14/tar.m4',
'm4/ax_gcc_builtin.m4',
'configure.ac'
],
{
'PKG_CHECK_MODULES' => 1,
'AC_LTDL_DLLIB' => 1,
'_AM_PROG_TAR' => 1,
'AC_LTDL_OBJDIR' => 1,
'XORG_DEFAULT_OPTIONS' => 1,
'_LT_AC_LANG_F77_CONFIG' => 1,
'AM_PROG_LIBTOOL' => 1,
'_LT_PREPARE_SED_QUOTE_VARS' => 1,
'_AC_PROG_LIBTOOL' => 1,
'AM_PROG_NM' => 1,
'XORG_INSTALL' => 1,
'AM_MAINTAINER_MODE' => 1,
'AC_PROG_NM' => 1,
'XORG_TESTSET_CFLAG' => 1,
'AC_WITH_LTDL' => 1,
'AC_LIBTOOL_LANG_C_CONFIG' => 1,
'AM_ENABLE_STATIC' => 1,
'AX_GCC_BUILTIN' => 1,
'XORG_ENABLE_DEVEL_DOCS' => 1,
'_LT_AC_TRY_DLOPEN_SELF' => 1,
'AC_LIBTOOL_GCJ' => 1,
'AC_PROG_EGREP' => 1,
'_LT_AC_LANG_F77' => 1,
'_LT_AC_PROG_CXXCPP' => 1,
'_LT_LINKER_OPTION' => 1,
'gl_FUNC_ARGZ' => 1,
'AM_PROG_CC_C_O' => 1,
'_LT_PATH_TOOL_PREFIX' => 1,
'LT_LANG' => 1,
'LT_AC_PROG_RC' => 1,
'_LT_AC_PROG_ECHO_BACKSLASH' => 1,
'_LT_AC_LANG_GCJ_CONFIG' => 1,
'_LT_COMPILER_BOILERPLATE' => 1,
'gl_PREREQ_ARGZ' => 1,
'XORG_MANPAGE_SECTIONS' => 1,
'XORG_WITH_PS2PDF' => 1,
'AM_DEP_TRACK' => 1,
'PKG_CHECK_EXISTS' => 1,
'AC_LIBTOOL_FC' => 1,
'LTDL_CONVENIENCE' => 1,
'_AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
'AC_CHECK_LIBM' => 1,
'XORG_CWARNFLAGS' => 1,
'XORG_LINT_LIBRARY' => 1,
'_m4_warn' => 1,
'_PKG_SHORT_ERRORS_SUPPORTED' => 1,
'AC_LIBTOOL_PROG_COMPILER_PIC' => 1,
'AM_DISABLE_SHARED' => 1,
'_AM_MANGLE_OPTION' => 1,
'_LT_AC_CHECK_DLFCN' => 1,
'AC_LIBTOOL_PICMODE' => 1,
'AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH' => 1,
'AC_LTDL_SYSSEARCHPATH' => 1,
'AC_PATH_MAGIC' => 1,
'AC_LIBTOOL_WIN32_DLL' => 1,
'_LT_AC_LANG_RC_CONFIG' => 1,
'_LT_AC_SYS_COMPILER' => 1,
'AC_LTDL_SYMBOL_USCORE' => 1,
'_LT_AC_TAGVAR' => 1,
'_LT_PROG_ECHO_BACKSLASH' => 1,
'LT_FUNC_DLSYM_USCORE' => 1,
'XORG_PROG_RAWCPP' => 1,
'_AM_AUTOCONF_VERSION' => 1,
'AM_ENABLE_SHARED' => 1,
'XORG_COMPILER_FLAGS' => 1,
'AC_DISABLE_FAST_INSTALL' => 1,
'XORG_CHECK_LINKER_FLAGS' => 1,
'AC_DEPLIBS_CHECK_METHOD' => 1,
'AM_DISABLE_STATIC' => 1,
'AM_MISSING_HAS_RUN' => 1,
'AC_LTDL_ENABLE_INSTALL' => 1,
'_LT_AC_TAGCONFIG' => 1,
'AC_PROG_LD_GNU' => 1,
'include' => 1,
'LT_SYS_MODULE_EXT' => 1,
'AM_PROG_LD' => 1,
'LT_AC_PROG_SED' => 1,
'AC_LIB_LTDL' => 1,
'AM_RUN_LOG' => 1,
'LT_INIT' => 1,
'_LT_AC_LANG_CXX' => 1,
'AC_LIBTOOL_CXX' => 1,
'AC_DEFUN_ONCE' => 1,
'AC_LIBTOOL_DLOPEN_SELF' => 1,
'LT_PROG_GCJ' => 1,
'LT_SYS_MODULE_PATH' => 1,
'AC_LIBTOOL_RC' => 1,
'_LT_CC_BASENAME' => 1,
'AM_AUTOMAKE_VERSION' => 1,
'_LT_AC_SHELL_INIT' => 1,
'_AM_DEPENDENCIES' => 1,
'AC_LIBTOOL_SYS_LIB_STRIP' => 1,
'_AM_SET_OPTION' => 1,
'_AM_SUBST_NOTMAKE' => 1,
'LT_PATH_NM' => 1,
'XORG_CHECK_MALLOC_ZERO' => 1,
'AC_LIBLTDL_CONVENIENCE' => 1,
'LT_CONFIG_LTDL_DIR' => 1,
'AC_DEFUN' => 1,
'AM_PROG_INSTALL_STRIP' => 1,
'_LT_AC_LOCK' => 1,
'XORG_ENABLE_DOCS' => 1,
'XORG_ENABLE_SPECS' => 1,
'AC_LIBTOOL_COMPILER_OPTION' => 1,
'm4_pattern_forbid' => 1,
'_LTDL_SETUP' => 1,
'AM_SUBST_NOTMAKE' => 1,
'AC_LIBTOOL_DLOPEN' => 1,
'AC_DISABLE_STATIC' => 1,
'LT_PROG_RC' => 1,
'_LT_AC_SYS_LIBPATH_AIX' => 1,
'AC_ENABLE_FAST_INSTALL' => 1,
'AC_PROG_LIBTOOL' => 1,
'XORG_WITH_XMLTO' => 1,
'_LT_LINKER_BOILERPLATE' => 1,
'LTSUGAR_VERSION' => 1,
'_LT_PROG_F77' => 1,
'AC_CONFIG_MACRO_DIR' => 1,
'LTVERSION_VERSION' => 1,
'XORG_LD_WRAP' => 1,
'LT_WITH_LTDL' => 1,
'AC_LIBTOOL_SYS_DYNAMIC_LINKER' => 1,
'XORG_MEMORY_CHECK_FLAGS' => 1,
'LT_SUPPORTED_TAG' => 1,
'LT_AC_PROG_EGREP' => 1,
'AC_LTDL_DLSYM_USCORE' => 1,
'_AM_PROG_CC_C_O' => 1,
'_LT_PROG_LTMAIN' => 1,
'XORG_CHECK_SGML_DOCTOOLS' => 1,
'_AM_IF_OPTION' => 1,
'AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
'_AM_CONFIG_MACRO_DIRS' => 1,
'AC_LIBTOOL_LANG_CXX_CONFIG' => 1,
'_LT_PROG_CXX' => 1,
'AC_LTDL_SHLIBPATH' => 1,
'AC_LIBTOOL_CONFIG' => 1,
'XORG_WITH_DOXYGEN' => 1,
'LT_SYS_DLOPEN_DEPLIBS' => 1,
'AC_CONFIG_MACRO_DIR_TRACE' => 1,
'AC_LIBTOOL_SYS_MAX_CMD_LEN' => 1,
'AC_LIBTOOL_POSTDEP_PREDEP' => 1,
'm4_pattern_allow' => 1,
'LTDL_INSTALLABLE' => 1,
'AC_LTDL_SHLIBEXT' => 1,
'_LT_AC_LANG_CXX_CONFIG' => 1,
'AU_DEFUN' => 1,
'AC_LIBTOOL_OBJDIR' => 1,
'AM_SET_CURRENT_AUTOMAKE_VERSION' => 1,
'AC_LIBTOOL_SETUP' => 1,
'AC_LIBTOOL_F77' => 1,
'AC_ENABLE_SHARED' => 1,
'AC_LIBTOOL_PROG_COMPILER_NO_RTTI' => 1,
'AM_SILENT_RULES' => 1,
'_LT_AC_LANG_C_CONFIG' => 1,
'AC_DISABLE_SHARED' => 1,
'AC_LIBLTDL_INSTALLABLE' => 1,
'AC_PROG_LD' => 1,
'XORG_ENABLE_INTEGRATION_TESTS' => 1,
'PKG_PROG_PKG_CONFIG' => 1,
'XORG_WITH_GROFF' => 1,
'_LT_COMPILER_OPTION' => 1,
'LT_SYS_DLSEARCH_PATH' => 1,
'AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE' => 1,
'XORG_RELEASE_VERSION' => 1,
'AM_INIT_AUTOMAKE' => 1,
'LT_SYS_SYMBOL_USCORE' => 1,
'AC_LIBTOOL_SYS_OLD_ARCHIVE' => 1,
'XORG_CHECK_LINUXDOC' => 1,
'XORG_STRICT_OPTION' => 1,
'XORG_WITH_FOP' => 1,
'XORG_WITH_LINT' => 1,
'XORG_WITH_PERL' => 1,
'AC_PROG_LD_RELOAD_FLAG' => 1,
'AM_SANITY_CHECK' => 1,
'AM_SET_LEADING_DOT' => 1,
'_LT_LIBOBJ' => 1,
'XORG_COMPILER_BRAND' => 1,
'LT_PROG_GO' => 1,
'_LT_AC_FILE_LTDLL_C' => 1,
'LT_SYS_DLOPEN_SELF' => 1,
'LT_LIB_DLLOAD' => 1,
'AC_LIBTOOL_LINKER_OPTION' => 1,
'XORG_WITH_ASCIIDOC' => 1,
'AM_MISSING_PROG' => 1,
'_LT_AC_LANG_GCJ' => 1,
'_AC_AM_CONFIG_HEADER_HOOK' => 1,
'AC_LTDL_PREOPEN' => 1,
'AM_AUX_DIR_EXPAND' => 1,
'XORG_WITH_GLIB' => 1,
'AM_CONDITIONAL' => 1,
'_LT_WITH_SYSROOT' => 1,
'AC_ENABLE_STATIC' => 1,
'XORG_CHECK_DOCBOOK' => 1,
'LTOBSOLETE_VERSION' => 1,
'LT_OUTPUT' => 1,
'XORG_CHANGELOG' => 1,
'LT_LIB_M' => 1,
'AC_LIBTOOL_PROG_CC_C_O' => 1,
'AM_SET_DEPDIR' => 1,
'AC_LIBTOOL_LANG_RC_CONFIG' => 1,
'AC_LIBTOOL_LANG_F77_CONFIG' => 1,
'm4_include' => 1,
'LT_PATH_LD' => 1,
'_LT_PROG_FC' => 1,
'_LT_REQUIRED_DARWIN_CHECKS' => 1,
'AC_LIBTOOL_SYS_HARD_LINK_LOCKS' => 1,
'AC_LTDL_SYS_DLOPEN_DEPLIBS' => 1,
'XORG_WITH_XSLTPROC' => 1,
'LTDL_INIT' => 1,
'AC_PATH_TOOL_PREFIX' => 1,
'AM_PROG_INSTALL_SH' => 1,
'AC_LIBTOOL_LANG_GCJ_CONFIG' => 1,
'_AM_SET_OPTIONS' => 1,
'AC_LIBTOOL_PROG_LD_SHLIBS' => 1,
'LT_AC_PROG_GCJ' => 1,
'LTOPTIONS_VERSION' => 1,
'AM_MAKE_INCLUDE' => 1,
'LT_CMD_MAX_LEN' => 1,
'XORG_ENABLE_UNIT_TESTS' => 1
}
], 'Autom4te::Request' ),
bless( [
'1',
1,
[
'/usr/share/autoconf'
],
[
'/usr/share/autoconf/autoconf/autoconf.m4f',
'aclocal.m4',
'configure.ac'
],
{
'LT_SUPPORTED_TAG' => 1,
'AC_SUBST_TRACE' => 1,
'_LT_AC_TAGCONFIG' => 1,
'AM_NLS' => 1,
'AM_MAINTAINER_MODE' => 1,
'AM_PROG_F77_C_O' => 1,
'AC_LIBSOURCE' => 1,
'AC_FC_PP_SRCEXT' => 1,
'AC_CONFIG_HEADERS' => 1,
'AM_PROG_CXX_C_O' => 1,
'AC_CONFIG_SUBDIRS' => 1,
'AM_PROG_MOC' => 1,
'AH_OUTPUT' => 1,
'AM_PROG_CC_C_O' => 1,
'AM_PROG_MKDIR_P' => 1,
'AC_FC_FREEFORM' => 1,
'AC_INIT' => 1,
'LT_INIT' => 1,
'AC_SUBST' => 1,
'AM_CONDITIONAL' => 1,
'AM_POT_TOOLS' => 1,
'AM_XGETTEXT_OPTION' => 1,
'include' => 1,
'AC_CONFIG_LIBOBJ_DIR' => 1,
'LT_CONFIG_LTDL_DIR' => 1,
'AM_MAKEFILE_INCLUDE' => 1,
'AC_FC_PP_DEFINE' => 1,
'AC_CANONICAL_BUILD' => 1,
'AM_SILENT_RULES' => 1,
'AM_GNU_GETTEXT_INTL_SUBDIR' => 1,
'm4_include' => 1,
'AC_DEFINE_TRACE_LITERAL' => 1,
'AM_GNU_GETTEXT' => 1,
'AC_CANONICAL_SYSTEM' => 1,
'AC_REQUIRE_AUX_FILE' => 1,
'AC_FC_SRCEXT' => 1,
'_AM_SUBST_NOTMAKE' => 1,
'_AM_COND_ENDIF' => 1,
'AM_EXTRA_RECURSIVE_TARGETS' => 1,
'm4_sinclude' => 1,
'AC_CONFIG_AUX_DIR' => 1,
'm4_pattern_allow' => 1,
'AM_AUTOMAKE_VERSION' => 1,
'AC_CONFIG_FILES' => 1,
'sinclude' => 1,
'AM_ENABLE_MULTILIB' => 1,
'AC_CANONICAL_HOST' => 1,
'_AM_MAKEFILE_INCLUDE' => 1,
'AC_PROG_LIBTOOL' => 1,
'AC_CONFIG_LINKS' => 1,
'_m4_warn' => 1,
'AC_CANONICAL_TARGET' => 1,
'AM_PROG_AR' => 1,
'AM_INIT_AUTOMAKE' => 1,
'AM_PATH_GUILE' => 1,
'_AM_COND_ELSE' => 1,
'AM_PROG_FC_C_O' => 1,
'_AM_COND_IF' => 1,
'm4_pattern_forbid' => 1
}
], 'Autom4te::Request' ),
bless( [
'2',
1,
[
'/usr/share/autoconf'
],
[
'/usr/share/autoconf/autoconf/autoconf.m4f',
'-',
'/usr/share/aclocal-1.14/internal/ac-config-macro-dirs.m4',
'/usr/share/aclocal/argz.m4',
'/usr/share/aclocal/ltdl.m4',
'/usr/share/aclocal/pkg.m4',
'/usr/share/aclocal/xorg-macros.m4',
'/usr/share/aclocal-1.14/amversion.m4',
'/usr/share/aclocal-1.14/auxdir.m4',
'/usr/share/aclocal-1.14/cond.m4',
'/usr/share/aclocal-1.14/depend.m4',
'/usr/share/aclocal-1.14/depout.m4',
'/usr/share/aclocal-1.14/init.m4',
'/usr/share/aclocal-1.14/install-sh.m4',
'/usr/share/aclocal-1.14/lead-dot.m4',
'/usr/share/aclocal-1.14/maintainer.m4',
'/usr/share/aclocal-1.14/make.m4',
'/usr/share/aclocal-1.14/missing.m4',
'/usr/share/aclocal-1.14/options.m4',
'/usr/share/aclocal-1.14/prog-cc-c-o.m4',
'/usr/share/aclocal-1.14/runlog.m4',
'/usr/share/aclocal-1.14/sanity.m4',
'/usr/share/aclocal-1.14/silent.m4',
'/usr/share/aclocal-1.14/strip.m4',
'/usr/share/aclocal-1.14/substnot.m4',
'/usr/share/aclocal-1.14/tar.m4',
'm4/ax_gcc_builtin.m4',
'm4/libtool.m4',
'm4/ltoptions.m4',
'm4/ltsugar.m4',
'm4/ltversion.m4',
'm4/lt~obsolete.m4',
'configure.ac'
],
{
'XORG_CHECK_SGML_DOCTOOLS' => 1,
'_AM_IF_OPTION' => 1,
'AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
'_AM_CONFIG_MACRO_DIRS' => 1,
'AC_LIBTOOL_LANG_CXX_CONFIG' => 1,
'AC_LTDL_SHLIBPATH' => 1,
'_LT_PROG_CXX' => 1,
'XORG_WITH_DOXYGEN' => 1,
'AC_LIBTOOL_CONFIG' => 1,
'LTVERSION_VERSION' => 1,
'XORG_LD_WRAP' => 1,
'LT_WITH_LTDL' => 1,
'AC_LIBTOOL_SYS_DYNAMIC_LINKER' => 1,
'AC_LTDL_DLSYM_USCORE' => 1,
'LT_AC_PROG_EGREP' => 1,
'_AM_PROG_CC_C_O' => 1,
'_LT_PROG_LTMAIN' => 1,
'XORG_MEMORY_CHECK_FLAGS' => 1,
'LT_SUPPORTED_TAG' => 1,
'XORG_ENABLE_INTEGRATION_TESTS' => 1,
'AC_PROG_LD' => 1,
'PKG_PROG_PKG_CONFIG' => 1,
'XORG_WITH_GROFF' => 1,
'LT_SYS_SYMBOL_USCORE' => 1,
'AM_INIT_AUTOMAKE' => 1,
'XORG_CHECK_LINUXDOC' => 1,
'AC_LIBTOOL_SYS_OLD_ARCHIVE' => 1,
'LT_SYS_DLSEARCH_PATH' => 1,
'_LT_COMPILER_OPTION' => 1,
'AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE' => 1,
'XORG_RELEASE_VERSION' => 1,
'XORG_WITH_LINT' => 1,
'XORG_STRICT_OPTION' => 1,
'XORG_WITH_FOP' => 1,
'AM_SANITY_CHECK' => 1,
'AC_PROG_LD_RELOAD_FLAG' => 1,
'XORG_WITH_PERL' => 1,
'LTDL_INSTALLABLE' => 1,
'AC_LTDL_SHLIBEXT' => 1,
'm4_pattern_allow' => 1,
'AC_CONFIG_MACRO_DIR_TRACE' => 1,
'LT_SYS_DLOPEN_DEPLIBS' => 1,
'AC_LIBTOOL_SYS_MAX_CMD_LEN' => 1,
'AC_LIBTOOL_POSTDEP_PREDEP' => 1,
'AM_SET_CURRENT_AUTOMAKE_VERSION' => 1,
'AU_DEFUN' => 1,
'AC_LIBTOOL_OBJDIR' => 1,
'_LT_AC_LANG_CXX_CONFIG' => 1,
'AM_SILENT_RULES' => 1,
'AC_LIBTOOL_SETUP' => 1,
'AC_ENABLE_SHARED' => 1,
'AC_LIBTOOL_F77' => 1,
'AC_LIBTOOL_PROG_COMPILER_NO_RTTI' => 1,
'AC_LIBLTDL_INSTALLABLE' => 1,
'AC_DISABLE_SHARED' => 1,
'_LT_AC_LANG_C_CONFIG' => 1,
'XORG_WITH_GLIB' => 1,
'AM_AUX_DIR_EXPAND' => 1,
'_LT_WITH_SYSROOT' => 1,
'AM_CONDITIONAL' => 1,
'AC_ENABLE_STATIC' => 1,
'LT_OUTPUT' => 1,
'XORG_CHANGELOG' => 1,
'XORG_CHECK_DOCBOOK' => 1,
'LTOBSOLETE_VERSION' => 1,
'AM_SET_LEADING_DOT' => 1,
'XORG_COMPILER_BRAND' => 1,
'_LT_LIBOBJ' => 1,
'LT_LIB_DLLOAD' => 1,
'LT_SYS_DLOPEN_SELF' => 1,
'AC_LIBTOOL_LINKER_OPTION' => 1,
'_LT_AC_FILE_LTDLL_C' => 1,
'LT_PROG_GO' => 1,
'AC_LTDL_PREOPEN' => 1,
'XORG_WITH_ASCIIDOC' => 1,
'AM_MISSING_PROG' => 1,
'_LT_AC_LANG_GCJ' => 1,
'_AC_AM_CONFIG_HEADER_HOOK' => 1,
'AM_PROG_INSTALL_SH' => 1,
'AC_LIBTOOL_LANG_GCJ_CONFIG' => 1,
'XORG_WITH_XSLTPROC' => 1,
'LTDL_INIT' => 1,
'AC_PATH_TOOL_PREFIX' => 1,
'AC_LIBTOOL_PROG_LD_SHLIBS' => 1,
'_AM_SET_OPTIONS' => 1,
'LT_AC_PROG_GCJ' => 1,
'LTOPTIONS_VERSION' => 1,
'AM_MAKE_INCLUDE' => 1,
'XORG_ENABLE_UNIT_TESTS' => 1,
'LT_CMD_MAX_LEN' => 1,
'AM_SET_DEPDIR' => 1,
'LT_LIB_M' => 1,
'AC_LIBTOOL_PROG_CC_C_O' => 1,
'AC_LIBTOOL_LANG_RC_CONFIG' => 1,
'm4_include' => 1,
'AC_LIBTOOL_LANG_F77_CONFIG' => 1,
'AC_LIBTOOL_SYS_HARD_LINK_LOCKS' => 1,
'AC_LTDL_SYS_DLOPEN_DEPLIBS' => 1,
'LT_PATH_LD' => 1,
'_LT_REQUIRED_DARWIN_CHECKS' => 1,
'_LT_PROG_FC' => 1,
'AC_LIBTOOL_GCJ' => 1,
'_LT_AC_TRY_DLOPEN_SELF' => 1,
'AM_ENABLE_STATIC' => 1,
'XORG_ENABLE_DEVEL_DOCS' => 1,
'AX_GCC_BUILTIN' => 1,
'_LT_LINKER_OPTION' => 1,
'AC_PROG_EGREP' => 1,
'_LT_AC_LANG_F77' => 1,
'_LT_AC_PROG_CXXCPP' => 1,
'gl_FUNC_ARGZ' => 1,
'LT_LANG' => 1,
'_LT_PATH_TOOL_PREFIX' => 1,
'AM_PROG_CC_C_O' => 1,
'AC_LTDL_DLLIB' => 1,
'_AM_PROG_TAR' => 1,
'AC_LTDL_OBJDIR' => 1,
'PKG_CHECK_MODULES' => 1,
'_LT_AC_LANG_F77_CONFIG' => 1,
'XORG_DEFAULT_OPTIONS' => 1,
'AM_PROG_LIBTOOL' => 1,
'AM_MAINTAINER_MODE' => 1,
'AC_PROG_NM' => 1,
'XORG_TESTSET_CFLAG' => 1,
'_LT_PREPARE_SED_QUOTE_VARS' => 1,
'AM_PROG_NM' => 1,
'_AC_PROG_LIBTOOL' => 1,
'XORG_INSTALL' => 1,
'AC_LIBTOOL_LANG_C_CONFIG' => 1,
'AC_WITH_LTDL' => 1,
'AC_CHECK_LIBM' => 1,
'_AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
'AC_LIBTOOL_PROG_COMPILER_PIC' => 1,
'_PKG_SHORT_ERRORS_SUPPORTED' => 1,
'XORG_CWARNFLAGS' => 1,
'XORG_LINT_LIBRARY' => 1,
'_m4_warn' => 1,
'_AM_MANGLE_OPTION' => 1,
'AM_DISABLE_SHARED' => 1,
'AC_LIBTOOL_WIN32_DLL' => 1,
'AC_PATH_MAGIC' => 1,
'AC_LTDL_SYSSEARCHPATH' => 1,
'AC_LIBTOOL_PICMODE' => 1,
'_LT_AC_CHECK_DLFCN' => 1,
'AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH' => 1,
'_LT_AC_LANG_GCJ_CONFIG' => 1,
'gl_PREREQ_ARGZ' => 1,
'XORG_MANPAGE_SECTIONS' => 1,
'_LT_COMPILER_BOILERPLATE' => 1,
'LT_AC_PROG_RC' => 1,
'_LT_AC_PROG_ECHO_BACKSLASH' => 1,
'AM_DEP_TRACK' => 1,
'XORG_WITH_PS2PDF' => 1,
'LTDL_CONVENIENCE' => 1,
'PKG_CHECK_EXISTS' => 1,
'AC_LIBTOOL_FC' => 1,
'LT_SYS_MODULE_EXT' => 1,
'AM_PROG_LD' => 1,
'AC_PROG_LD_GNU' => 1,
'include' => 1,
'LT_AC_PROG_SED' => 1,
'AC_LIB_LTDL' => 1,
'AM_RUN_LOG' => 1,
'LT_INIT' => 1,
'LT_SYS_MODULE_PATH' => 1,
'LT_PROG_GCJ' => 1,
'AC_LIBTOOL_DLOPEN_SELF' => 1,
'AC_DEFUN_ONCE' => 1,
'AC_LIBTOOL_RC' => 1,
'_LT_AC_LANG_CXX' => 1,
'AC_LIBTOOL_CXX' => 1,
'_LT_AC_TAGVAR' => 1,
'AC_LTDL_SYMBOL_USCORE' => 1,
'_LT_PROG_ECHO_BACKSLASH' => 1,
'LT_FUNC_DLSYM_USCORE' => 1,
'_LT_AC_SYS_COMPILER' => 1,
'_LT_AC_LANG_RC_CONFIG' => 1,
'XORG_PROG_RAWCPP' => 1,
'AM_ENABLE_SHARED' => 1,
'_AM_AUTOCONF_VERSION' => 1,
'AM_DISABLE_STATIC' => 1,
'AC_DEPLIBS_CHECK_METHOD' => 1,
'AM_MISSING_HAS_RUN' => 1,
'_LT_AC_TAGCONFIG' => 1,
'AC_LTDL_ENABLE_INSTALL' => 1,
'AC_DISABLE_FAST_INSTALL' => 1,
'XORG_COMPILER_FLAGS' => 1,
'XORG_CHECK_LINKER_FLAGS' => 1,
'XORG_ENABLE_SPECS' => 1,
'm4_pattern_forbid' => 1,
'AC_LIBTOOL_COMPILER_OPTION' => 1,
'_LT_AC_LOCK' => 1,
'XORG_ENABLE_DOCS' => 1,
'LT_PROG_RC' => 1,
'_LT_AC_SYS_LIBPATH_AIX' => 1,
'AM_SUBST_NOTMAKE' => 1,
'_LTDL_SETUP' => 1,
'AC_DISABLE_STATIC' => 1,
'AC_LIBTOOL_DLOPEN' => 1,
'AC_PROG_LIBTOOL' => 1,
'AC_ENABLE_FAST_INSTALL' => 1,
'AC_CONFIG_MACRO_DIR' => 1,
'_LT_PROG_F77' => 1,
'XORG_WITH_XMLTO' => 1,
'LTSUGAR_VERSION' => 1,
'_LT_LINKER_BOILERPLATE' => 1,
'AM_AUTOMAKE_VERSION' => 1,
'_LT_CC_BASENAME' => 1,
'_AM_SUBST_NOTMAKE' => 1,
'LT_PATH_NM' => 1,
'_LT_AC_SHELL_INIT' => 1,
'_AM_DEPENDENCIES' => 1,
'AC_LIBTOOL_SYS_LIB_STRIP' => 1,
'_AM_SET_OPTION' => 1,
'AM_PROG_INSTALL_STRIP' => 1,
'AC_DEFUN' => 1,
'XORG_CHECK_MALLOC_ZERO' => 1,
'AC_LIBLTDL_CONVENIENCE' => 1,
'LT_CONFIG_LTDL_DIR' => 1
}
], 'Autom4te::Request' )
);

View File

@ -1,139 +0,0 @@
#! /bin/sh
# test-driver - basic testsuite driver script.
scriptversion=2013-07-13.22; # UTC
# Copyright (C) 2011-2013 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
# Make unconditional expansion of undefined variables an error. This
# helps a lot in preventing typo-related bugs.
set -u
usage_error ()
{
echo "$0: $*" >&2
print_usage >&2
exit 2
}
print_usage ()
{
cat <<END
Usage:
test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
[--expect-failure={yes|no}] [--color-tests={yes|no}]
[--enable-hard-errors={yes|no}] [--]
TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
The '--test-name', '--log-file' and '--trs-file' options are mandatory.
END
}
test_name= # Used for reporting.
log_file= # Where to save the output of the test script.
trs_file= # Where to save the metadata of the test run.
expect_failure=no
color_tests=no
enable_hard_errors=yes
while test $# -gt 0; do
case $1 in
--help) print_usage; exit $?;;
--version) echo "test-driver $scriptversion"; exit $?;;
--test-name) test_name=$2; shift;;
--log-file) log_file=$2; shift;;
--trs-file) trs_file=$2; shift;;
--color-tests) color_tests=$2; shift;;
--expect-failure) expect_failure=$2; shift;;
--enable-hard-errors) enable_hard_errors=$2; shift;;
--) shift; break;;
-*) usage_error "invalid option: '$1'";;
*) break;;
esac
shift
done
missing_opts=
test x"$test_name" = x && missing_opts="$missing_opts --test-name"
test x"$log_file" = x && missing_opts="$missing_opts --log-file"
test x"$trs_file" = x && missing_opts="$missing_opts --trs-file"
if test x"$missing_opts" != x; then
usage_error "the following mandatory options are missing:$missing_opts"
fi
if test $# -eq 0; then
usage_error "missing argument"
fi
if test $color_tests = yes; then
# Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
red='' # Red.
grn='' # Green.
lgn='' # Light green.
blu='' # Blue.
mgn='' # Magenta.
std='' # No color.
else
red= grn= lgn= blu= mgn= std=
fi
do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
trap "st=129; $do_exit" 1
trap "st=130; $do_exit" 2
trap "st=141; $do_exit" 13
trap "st=143; $do_exit" 15
# Test script is run here.
"$@" >$log_file 2>&1
estatus=$?
if test $enable_hard_errors = no && test $estatus -eq 99; then
estatus=1
fi
case $estatus:$expect_failure in
0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
0:*) col=$grn res=PASS recheck=no gcopy=no;;
77:*) col=$blu res=SKIP recheck=no gcopy=yes;;
99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;;
*:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;;
*:*) col=$red res=FAIL recheck=yes gcopy=yes;;
esac
# Report outcome to console.
echo "${col}${res}${std}: $test_name"
# Register the test result, and other relevant metadata.
echo ":test-result: $res" > $trs_file
echo ":global-test-result: $res" >> $trs_file
echo ":recheck: $recheck" >> $trs_file
echo ":copy-in-global-log: $gcopy" >> $trs_file
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

File diff suppressed because it is too large Load Diff

View File

@ -1,832 +0,0 @@
m4trace:aclocal.m4:3199: -1- m4_include([m4/ax_gcc_builtin.m4])
m4trace:aclocal.m4:3200: -1- m4_include([m4/libtool.m4])
m4trace:aclocal.m4:3201: -1- m4_include([m4/ltoptions.m4])
m4trace:aclocal.m4:3202: -1- m4_include([m4/ltsugar.m4])
m4trace:aclocal.m4:3203: -1- m4_include([m4/ltversion.m4])
m4trace:aclocal.m4:3204: -1- m4_include([m4/lt~obsolete.m4])
m4trace:configure.ac:25: -1- AC_INIT([libxkbcommon], [0.5.0], [https://bugs.freedesktop.org/enter_bug.cgi?product=libxkbcommon], [libxkbcommon], [http://xkbcommon.org])
m4trace:configure.ac:25: -1- m4_pattern_forbid([^_?A[CHUM]_])
m4trace:configure.ac:25: -1- m4_pattern_forbid([_AC_])
m4trace:configure.ac:25: -1- m4_pattern_forbid([^LIBOBJS$], [do not use LIBOBJS directly, use AC_LIBOBJ (see section `AC_LIBOBJ vs LIBOBJS'])
m4trace:configure.ac:25: -1- m4_pattern_allow([^AS_FLAGS$])
m4trace:configure.ac:25: -1- m4_pattern_forbid([^_?m4_])
m4trace:configure.ac:25: -1- m4_pattern_forbid([^dnl$])
m4trace:configure.ac:25: -1- m4_pattern_forbid([^_?AS_])
m4trace:configure.ac:25: -1- AC_SUBST([SHELL])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([SHELL])
m4trace:configure.ac:25: -1- m4_pattern_allow([^SHELL$])
m4trace:configure.ac:25: -1- AC_SUBST([PATH_SEPARATOR])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([PATH_SEPARATOR])
m4trace:configure.ac:25: -1- m4_pattern_allow([^PATH_SEPARATOR$])
m4trace:configure.ac:25: -1- AC_SUBST([PACKAGE_NAME], [m4_ifdef([AC_PACKAGE_NAME], ['AC_PACKAGE_NAME'])])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([PACKAGE_NAME])
m4trace:configure.ac:25: -1- m4_pattern_allow([^PACKAGE_NAME$])
m4trace:configure.ac:25: -1- AC_SUBST([PACKAGE_TARNAME], [m4_ifdef([AC_PACKAGE_TARNAME], ['AC_PACKAGE_TARNAME'])])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([PACKAGE_TARNAME])
m4trace:configure.ac:25: -1- m4_pattern_allow([^PACKAGE_TARNAME$])
m4trace:configure.ac:25: -1- AC_SUBST([PACKAGE_VERSION], [m4_ifdef([AC_PACKAGE_VERSION], ['AC_PACKAGE_VERSION'])])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([PACKAGE_VERSION])
m4trace:configure.ac:25: -1- m4_pattern_allow([^PACKAGE_VERSION$])
m4trace:configure.ac:25: -1- AC_SUBST([PACKAGE_STRING], [m4_ifdef([AC_PACKAGE_STRING], ['AC_PACKAGE_STRING'])])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([PACKAGE_STRING])
m4trace:configure.ac:25: -1- m4_pattern_allow([^PACKAGE_STRING$])
m4trace:configure.ac:25: -1- AC_SUBST([PACKAGE_BUGREPORT], [m4_ifdef([AC_PACKAGE_BUGREPORT], ['AC_PACKAGE_BUGREPORT'])])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([PACKAGE_BUGREPORT])
m4trace:configure.ac:25: -1- m4_pattern_allow([^PACKAGE_BUGREPORT$])
m4trace:configure.ac:25: -1- AC_SUBST([PACKAGE_URL], [m4_ifdef([AC_PACKAGE_URL], ['AC_PACKAGE_URL'])])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([PACKAGE_URL])
m4trace:configure.ac:25: -1- m4_pattern_allow([^PACKAGE_URL$])
m4trace:configure.ac:25: -1- AC_SUBST([exec_prefix], [NONE])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([exec_prefix])
m4trace:configure.ac:25: -1- m4_pattern_allow([^exec_prefix$])
m4trace:configure.ac:25: -1- AC_SUBST([prefix], [NONE])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([prefix])
m4trace:configure.ac:25: -1- m4_pattern_allow([^prefix$])
m4trace:configure.ac:25: -1- AC_SUBST([program_transform_name], [s,x,x,])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([program_transform_name])
m4trace:configure.ac:25: -1- m4_pattern_allow([^program_transform_name$])
m4trace:configure.ac:25: -1- AC_SUBST([bindir], ['${exec_prefix}/bin'])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([bindir])
m4trace:configure.ac:25: -1- m4_pattern_allow([^bindir$])
m4trace:configure.ac:25: -1- AC_SUBST([sbindir], ['${exec_prefix}/sbin'])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([sbindir])
m4trace:configure.ac:25: -1- m4_pattern_allow([^sbindir$])
m4trace:configure.ac:25: -1- AC_SUBST([libexecdir], ['${exec_prefix}/libexec'])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([libexecdir])
m4trace:configure.ac:25: -1- m4_pattern_allow([^libexecdir$])
m4trace:configure.ac:25: -1- AC_SUBST([datarootdir], ['${prefix}/share'])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([datarootdir])
m4trace:configure.ac:25: -1- m4_pattern_allow([^datarootdir$])
m4trace:configure.ac:25: -1- AC_SUBST([datadir], ['${datarootdir}'])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([datadir])
m4trace:configure.ac:25: -1- m4_pattern_allow([^datadir$])
m4trace:configure.ac:25: -1- AC_SUBST([sysconfdir], ['${prefix}/etc'])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([sysconfdir])
m4trace:configure.ac:25: -1- m4_pattern_allow([^sysconfdir$])
m4trace:configure.ac:25: -1- AC_SUBST([sharedstatedir], ['${prefix}/com'])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([sharedstatedir])
m4trace:configure.ac:25: -1- m4_pattern_allow([^sharedstatedir$])
m4trace:configure.ac:25: -1- AC_SUBST([localstatedir], ['${prefix}/var'])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([localstatedir])
m4trace:configure.ac:25: -1- m4_pattern_allow([^localstatedir$])
m4trace:configure.ac:25: -1- AC_SUBST([includedir], ['${prefix}/include'])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([includedir])
m4trace:configure.ac:25: -1- m4_pattern_allow([^includedir$])
m4trace:configure.ac:25: -1- AC_SUBST([oldincludedir], ['/usr/include'])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([oldincludedir])
m4trace:configure.ac:25: -1- m4_pattern_allow([^oldincludedir$])
m4trace:configure.ac:25: -1- AC_SUBST([docdir], [m4_ifset([AC_PACKAGE_TARNAME],
['${datarootdir}/doc/${PACKAGE_TARNAME}'],
['${datarootdir}/doc/${PACKAGE}'])])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([docdir])
m4trace:configure.ac:25: -1- m4_pattern_allow([^docdir$])
m4trace:configure.ac:25: -1- AC_SUBST([infodir], ['${datarootdir}/info'])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([infodir])
m4trace:configure.ac:25: -1- m4_pattern_allow([^infodir$])
m4trace:configure.ac:25: -1- AC_SUBST([htmldir], ['${docdir}'])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([htmldir])
m4trace:configure.ac:25: -1- m4_pattern_allow([^htmldir$])
m4trace:configure.ac:25: -1- AC_SUBST([dvidir], ['${docdir}'])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([dvidir])
m4trace:configure.ac:25: -1- m4_pattern_allow([^dvidir$])
m4trace:configure.ac:25: -1- AC_SUBST([pdfdir], ['${docdir}'])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([pdfdir])
m4trace:configure.ac:25: -1- m4_pattern_allow([^pdfdir$])
m4trace:configure.ac:25: -1- AC_SUBST([psdir], ['${docdir}'])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([psdir])
m4trace:configure.ac:25: -1- m4_pattern_allow([^psdir$])
m4trace:configure.ac:25: -1- AC_SUBST([libdir], ['${exec_prefix}/lib'])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([libdir])
m4trace:configure.ac:25: -1- m4_pattern_allow([^libdir$])
m4trace:configure.ac:25: -1- AC_SUBST([localedir], ['${datarootdir}/locale'])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([localedir])
m4trace:configure.ac:25: -1- m4_pattern_allow([^localedir$])
m4trace:configure.ac:25: -1- AC_SUBST([mandir], ['${datarootdir}/man'])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([mandir])
m4trace:configure.ac:25: -1- m4_pattern_allow([^mandir$])
m4trace:configure.ac:25: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_NAME])
m4trace:configure.ac:25: -1- m4_pattern_allow([^PACKAGE_NAME$])
m4trace:configure.ac:25: -1- AH_OUTPUT([PACKAGE_NAME], [/* Define to the full name of this package. */
@%:@undef PACKAGE_NAME])
m4trace:configure.ac:25: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_TARNAME])
m4trace:configure.ac:25: -1- m4_pattern_allow([^PACKAGE_TARNAME$])
m4trace:configure.ac:25: -1- AH_OUTPUT([PACKAGE_TARNAME], [/* Define to the one symbol short name of this package. */
@%:@undef PACKAGE_TARNAME])
m4trace:configure.ac:25: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_VERSION])
m4trace:configure.ac:25: -1- m4_pattern_allow([^PACKAGE_VERSION$])
m4trace:configure.ac:25: -1- AH_OUTPUT([PACKAGE_VERSION], [/* Define to the version of this package. */
@%:@undef PACKAGE_VERSION])
m4trace:configure.ac:25: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_STRING])
m4trace:configure.ac:25: -1- m4_pattern_allow([^PACKAGE_STRING$])
m4trace:configure.ac:25: -1- AH_OUTPUT([PACKAGE_STRING], [/* Define to the full name and version of this package. */
@%:@undef PACKAGE_STRING])
m4trace:configure.ac:25: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_BUGREPORT])
m4trace:configure.ac:25: -1- m4_pattern_allow([^PACKAGE_BUGREPORT$])
m4trace:configure.ac:25: -1- AH_OUTPUT([PACKAGE_BUGREPORT], [/* Define to the address where bug reports for this package should be sent. */
@%:@undef PACKAGE_BUGREPORT])
m4trace:configure.ac:25: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_URL])
m4trace:configure.ac:25: -1- m4_pattern_allow([^PACKAGE_URL$])
m4trace:configure.ac:25: -1- AH_OUTPUT([PACKAGE_URL], [/* Define to the home page for this package. */
@%:@undef PACKAGE_URL])
m4trace:configure.ac:25: -1- AC_SUBST([DEFS])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([DEFS])
m4trace:configure.ac:25: -1- m4_pattern_allow([^DEFS$])
m4trace:configure.ac:25: -1- AC_SUBST([ECHO_C])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([ECHO_C])
m4trace:configure.ac:25: -1- m4_pattern_allow([^ECHO_C$])
m4trace:configure.ac:25: -1- AC_SUBST([ECHO_N])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([ECHO_N])
m4trace:configure.ac:25: -1- m4_pattern_allow([^ECHO_N$])
m4trace:configure.ac:25: -1- AC_SUBST([ECHO_T])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([ECHO_T])
m4trace:configure.ac:25: -1- m4_pattern_allow([^ECHO_T$])
m4trace:configure.ac:25: -1- AC_SUBST([LIBS])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([LIBS])
m4trace:configure.ac:25: -1- m4_pattern_allow([^LIBS$])
m4trace:configure.ac:25: -1- AC_SUBST([build_alias])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([build_alias])
m4trace:configure.ac:25: -1- m4_pattern_allow([^build_alias$])
m4trace:configure.ac:25: -1- AC_SUBST([host_alias])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([host_alias])
m4trace:configure.ac:25: -1- m4_pattern_allow([^host_alias$])
m4trace:configure.ac:25: -1- AC_SUBST([target_alias])
m4trace:configure.ac:25: -1- AC_SUBST_TRACE([target_alias])
m4trace:configure.ac:25: -1- m4_pattern_allow([^target_alias$])
m4trace:configure.ac:29: -1- AC_CONFIG_HEADERS([src/config.h])
m4trace:configure.ac:31: -1- AC_CONFIG_AUX_DIR([build-aux])
m4trace:configure.ac:34: -1- AM_INIT_AUTOMAKE([foreign dist-xz no-dist-gzip subdir-objects color-tests parallel-tests check-news])
m4trace:configure.ac:34: -1- m4_pattern_allow([^AM_[A-Z]+FLAGS$])
m4trace:configure.ac:34: -1- AM_AUTOMAKE_VERSION([1.14.1])
m4trace:configure.ac:34: -1- AC_REQUIRE_AUX_FILE([install-sh])
m4trace:configure.ac:34: -1- AC_SUBST([INSTALL_PROGRAM])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([INSTALL_PROGRAM])
m4trace:configure.ac:34: -1- m4_pattern_allow([^INSTALL_PROGRAM$])
m4trace:configure.ac:34: -1- AC_SUBST([INSTALL_SCRIPT])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([INSTALL_SCRIPT])
m4trace:configure.ac:34: -1- m4_pattern_allow([^INSTALL_SCRIPT$])
m4trace:configure.ac:34: -1- AC_SUBST([INSTALL_DATA])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([INSTALL_DATA])
m4trace:configure.ac:34: -1- m4_pattern_allow([^INSTALL_DATA$])
m4trace:configure.ac:34: -1- AC_SUBST([am__isrc], [' -I$(srcdir)'])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([am__isrc])
m4trace:configure.ac:34: -1- m4_pattern_allow([^am__isrc$])
m4trace:configure.ac:34: -1- _AM_SUBST_NOTMAKE([am__isrc])
m4trace:configure.ac:34: -1- AC_SUBST([CYGPATH_W])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([CYGPATH_W])
m4trace:configure.ac:34: -1- m4_pattern_allow([^CYGPATH_W$])
m4trace:configure.ac:34: -1- AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([PACKAGE])
m4trace:configure.ac:34: -1- m4_pattern_allow([^PACKAGE$])
m4trace:configure.ac:34: -1- AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([VERSION])
m4trace:configure.ac:34: -1- m4_pattern_allow([^VERSION$])
m4trace:configure.ac:34: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE])
m4trace:configure.ac:34: -1- m4_pattern_allow([^PACKAGE$])
m4trace:configure.ac:34: -1- AH_OUTPUT([PACKAGE], [/* Name of package */
@%:@undef PACKAGE])
m4trace:configure.ac:34: -1- AC_DEFINE_TRACE_LITERAL([VERSION])
m4trace:configure.ac:34: -1- m4_pattern_allow([^VERSION$])
m4trace:configure.ac:34: -1- AH_OUTPUT([VERSION], [/* Version number of package */
@%:@undef VERSION])
m4trace:configure.ac:34: -1- AC_REQUIRE_AUX_FILE([missing])
m4trace:configure.ac:34: -1- AC_SUBST([ACLOCAL])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([ACLOCAL])
m4trace:configure.ac:34: -1- m4_pattern_allow([^ACLOCAL$])
m4trace:configure.ac:34: -1- AC_SUBST([AUTOCONF])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([AUTOCONF])
m4trace:configure.ac:34: -1- m4_pattern_allow([^AUTOCONF$])
m4trace:configure.ac:34: -1- AC_SUBST([AUTOMAKE])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([AUTOMAKE])
m4trace:configure.ac:34: -1- m4_pattern_allow([^AUTOMAKE$])
m4trace:configure.ac:34: -1- AC_SUBST([AUTOHEADER])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([AUTOHEADER])
m4trace:configure.ac:34: -1- m4_pattern_allow([^AUTOHEADER$])
m4trace:configure.ac:34: -1- AC_SUBST([MAKEINFO])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([MAKEINFO])
m4trace:configure.ac:34: -1- m4_pattern_allow([^MAKEINFO$])
m4trace:configure.ac:34: -1- AC_SUBST([install_sh])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([install_sh])
m4trace:configure.ac:34: -1- m4_pattern_allow([^install_sh$])
m4trace:configure.ac:34: -1- AC_SUBST([STRIP])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([STRIP])
m4trace:configure.ac:34: -1- m4_pattern_allow([^STRIP$])
m4trace:configure.ac:34: -1- AC_SUBST([INSTALL_STRIP_PROGRAM])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([INSTALL_STRIP_PROGRAM])
m4trace:configure.ac:34: -1- m4_pattern_allow([^INSTALL_STRIP_PROGRAM$])
m4trace:configure.ac:34: -1- AC_REQUIRE_AUX_FILE([install-sh])
m4trace:configure.ac:34: -1- AC_SUBST([MKDIR_P])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([MKDIR_P])
m4trace:configure.ac:34: -1- m4_pattern_allow([^MKDIR_P$])
m4trace:configure.ac:34: -1- AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([mkdir_p])
m4trace:configure.ac:34: -1- m4_pattern_allow([^mkdir_p$])
m4trace:configure.ac:34: -1- AC_SUBST([AWK])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([AWK])
m4trace:configure.ac:34: -1- m4_pattern_allow([^AWK$])
m4trace:configure.ac:34: -1- AC_SUBST([SET_MAKE])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([SET_MAKE])
m4trace:configure.ac:34: -1- m4_pattern_allow([^SET_MAKE$])
m4trace:configure.ac:34: -1- AC_SUBST([am__leading_dot])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([am__leading_dot])
m4trace:configure.ac:34: -1- m4_pattern_allow([^am__leading_dot$])
m4trace:configure.ac:34: -1- AC_SUBST([AMTAR], ['$${TAR-tar}'])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([AMTAR])
m4trace:configure.ac:34: -1- m4_pattern_allow([^AMTAR$])
m4trace:configure.ac:34: -1- AC_SUBST([am__tar])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([am__tar])
m4trace:configure.ac:34: -1- m4_pattern_allow([^am__tar$])
m4trace:configure.ac:34: -1- AC_SUBST([am__untar])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([am__untar])
m4trace:configure.ac:34: -1- m4_pattern_allow([^am__untar$])
m4trace:configure.ac:34: -1- AM_SILENT_RULES
m4trace:configure.ac:34: -1- AC_SUBST([AM_V])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([AM_V])
m4trace:configure.ac:34: -1- m4_pattern_allow([^AM_V$])
m4trace:configure.ac:34: -1- _AM_SUBST_NOTMAKE([AM_V])
m4trace:configure.ac:34: -1- AC_SUBST([AM_DEFAULT_V])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([AM_DEFAULT_V])
m4trace:configure.ac:34: -1- m4_pattern_allow([^AM_DEFAULT_V$])
m4trace:configure.ac:34: -1- _AM_SUBST_NOTMAKE([AM_DEFAULT_V])
m4trace:configure.ac:34: -1- AC_SUBST([AM_DEFAULT_VERBOSITY])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([AM_DEFAULT_VERBOSITY])
m4trace:configure.ac:34: -1- m4_pattern_allow([^AM_DEFAULT_VERBOSITY$])
m4trace:configure.ac:34: -1- AC_SUBST([AM_BACKSLASH])
m4trace:configure.ac:34: -1- AC_SUBST_TRACE([AM_BACKSLASH])
m4trace:configure.ac:34: -1- m4_pattern_allow([^AM_BACKSLASH$])
m4trace:configure.ac:34: -1- _AM_SUBST_NOTMAKE([AM_BACKSLASH])
m4trace:configure.ac:35: -1- AM_MAINTAINER_MODE([enable])
m4trace:configure.ac:35: -1- AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
m4trace:configure.ac:35: -1- AC_SUBST([MAINTAINER_MODE_TRUE])
m4trace:configure.ac:35: -1- AC_SUBST_TRACE([MAINTAINER_MODE_TRUE])
m4trace:configure.ac:35: -1- m4_pattern_allow([^MAINTAINER_MODE_TRUE$])
m4trace:configure.ac:35: -1- AC_SUBST([MAINTAINER_MODE_FALSE])
m4trace:configure.ac:35: -1- AC_SUBST_TRACE([MAINTAINER_MODE_FALSE])
m4trace:configure.ac:35: -1- m4_pattern_allow([^MAINTAINER_MODE_FALSE$])
m4trace:configure.ac:35: -1- _AM_SUBST_NOTMAKE([MAINTAINER_MODE_TRUE])
m4trace:configure.ac:35: -1- _AM_SUBST_NOTMAKE([MAINTAINER_MODE_FALSE])
m4trace:configure.ac:35: -1- AC_SUBST([MAINT])
m4trace:configure.ac:35: -1- AC_SUBST_TRACE([MAINT])
m4trace:configure.ac:35: -1- m4_pattern_allow([^MAINT$])
m4trace:configure.ac:38: -1- AC_SUBST([CC])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([CC])
m4trace:configure.ac:38: -1- m4_pattern_allow([^CC$])
m4trace:configure.ac:38: -1- AC_SUBST([CFLAGS])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([CFLAGS])
m4trace:configure.ac:38: -1- m4_pattern_allow([^CFLAGS$])
m4trace:configure.ac:38: -1- AC_SUBST([LDFLAGS])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([LDFLAGS])
m4trace:configure.ac:38: -1- m4_pattern_allow([^LDFLAGS$])
m4trace:configure.ac:38: -1- AC_SUBST([LIBS])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([LIBS])
m4trace:configure.ac:38: -1- m4_pattern_allow([^LIBS$])
m4trace:configure.ac:38: -1- AC_SUBST([CPPFLAGS])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([CPPFLAGS])
m4trace:configure.ac:38: -1- m4_pattern_allow([^CPPFLAGS$])
m4trace:configure.ac:38: -1- AC_SUBST([CC])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([CC])
m4trace:configure.ac:38: -1- m4_pattern_allow([^CC$])
m4trace:configure.ac:38: -1- AC_SUBST([CC])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([CC])
m4trace:configure.ac:38: -1- m4_pattern_allow([^CC$])
m4trace:configure.ac:38: -1- AC_SUBST([CC])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([CC])
m4trace:configure.ac:38: -1- m4_pattern_allow([^CC$])
m4trace:configure.ac:38: -1- AC_SUBST([CC])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([CC])
m4trace:configure.ac:38: -1- m4_pattern_allow([^CC$])
m4trace:configure.ac:38: -1- AC_SUBST([ac_ct_CC])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([ac_ct_CC])
m4trace:configure.ac:38: -1- m4_pattern_allow([^ac_ct_CC$])
m4trace:configure.ac:38: -1- AC_SUBST([EXEEXT], [$ac_cv_exeext])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([EXEEXT])
m4trace:configure.ac:38: -1- m4_pattern_allow([^EXEEXT$])
m4trace:configure.ac:38: -1- AC_SUBST([OBJEXT], [$ac_cv_objext])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([OBJEXT])
m4trace:configure.ac:38: -1- m4_pattern_allow([^OBJEXT$])
m4trace:configure.ac:38: -1- AC_REQUIRE_AUX_FILE([compile])
m4trace:configure.ac:38: -1- AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([DEPDIR])
m4trace:configure.ac:38: -1- m4_pattern_allow([^DEPDIR$])
m4trace:configure.ac:38: -1- AC_SUBST([am__include])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([am__include])
m4trace:configure.ac:38: -1- m4_pattern_allow([^am__include$])
m4trace:configure.ac:38: -1- AC_SUBST([am__quote])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([am__quote])
m4trace:configure.ac:38: -1- m4_pattern_allow([^am__quote$])
m4trace:configure.ac:38: -1- AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
m4trace:configure.ac:38: -1- AC_SUBST([AMDEP_TRUE])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([AMDEP_TRUE])
m4trace:configure.ac:38: -1- m4_pattern_allow([^AMDEP_TRUE$])
m4trace:configure.ac:38: -1- AC_SUBST([AMDEP_FALSE])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([AMDEP_FALSE])
m4trace:configure.ac:38: -1- m4_pattern_allow([^AMDEP_FALSE$])
m4trace:configure.ac:38: -1- _AM_SUBST_NOTMAKE([AMDEP_TRUE])
m4trace:configure.ac:38: -1- _AM_SUBST_NOTMAKE([AMDEP_FALSE])
m4trace:configure.ac:38: -1- AC_SUBST([AMDEPBACKSLASH])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([AMDEPBACKSLASH])
m4trace:configure.ac:38: -1- m4_pattern_allow([^AMDEPBACKSLASH$])
m4trace:configure.ac:38: -1- _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])
m4trace:configure.ac:38: -1- AC_SUBST([am__nodep])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([am__nodep])
m4trace:configure.ac:38: -1- m4_pattern_allow([^am__nodep$])
m4trace:configure.ac:38: -1- _AM_SUBST_NOTMAKE([am__nodep])
m4trace:configure.ac:38: -1- AC_SUBST([CCDEPMODE], [depmode=$am_cv_CC_dependencies_compiler_type])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([CCDEPMODE])
m4trace:configure.ac:38: -1- m4_pattern_allow([^CCDEPMODE$])
m4trace:configure.ac:38: -1- AM_CONDITIONAL([am__fastdepCC], [
test "x$enable_dependency_tracking" != xno \
&& test "$am_cv_CC_dependencies_compiler_type" = gcc3])
m4trace:configure.ac:38: -1- AC_SUBST([am__fastdepCC_TRUE])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([am__fastdepCC_TRUE])
m4trace:configure.ac:38: -1- m4_pattern_allow([^am__fastdepCC_TRUE$])
m4trace:configure.ac:38: -1- AC_SUBST([am__fastdepCC_FALSE])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([am__fastdepCC_FALSE])
m4trace:configure.ac:38: -1- m4_pattern_allow([^am__fastdepCC_FALSE$])
m4trace:configure.ac:38: -1- _AM_SUBST_NOTMAKE([am__fastdepCC_TRUE])
m4trace:configure.ac:38: -1- _AM_SUBST_NOTMAKE([am__fastdepCC_FALSE])
m4trace:configure.ac:38: -1- AC_SUBST([CPP])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([CPP])
m4trace:configure.ac:38: -1- m4_pattern_allow([^CPP$])
m4trace:configure.ac:38: -1- AC_SUBST([CPPFLAGS])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([CPPFLAGS])
m4trace:configure.ac:38: -1- m4_pattern_allow([^CPPFLAGS$])
m4trace:configure.ac:38: -1- AC_SUBST([CPP])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([CPP])
m4trace:configure.ac:38: -1- m4_pattern_allow([^CPP$])
m4trace:configure.ac:38: -1- AC_SUBST([GREP])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([GREP])
m4trace:configure.ac:38: -1- m4_pattern_allow([^GREP$])
m4trace:configure.ac:38: -1- AC_SUBST([EGREP])
m4trace:configure.ac:38: -1- AC_SUBST_TRACE([EGREP])
m4trace:configure.ac:38: -1- m4_pattern_allow([^EGREP$])
m4trace:configure.ac:38: -1- AC_DEFINE_TRACE_LITERAL([STDC_HEADERS])
m4trace:configure.ac:38: -1- m4_pattern_allow([^STDC_HEADERS$])
m4trace:configure.ac:38: -1- AH_OUTPUT([STDC_HEADERS], [/* Define to 1 if you have the ANSI C header files. */
@%:@undef STDC_HEADERS])
m4trace:configure.ac:38: -1- AH_OUTPUT([HAVE_SYS_TYPES_H], [/* Define to 1 if you have the <sys/types.h> header file. */
@%:@undef HAVE_SYS_TYPES_H])
m4trace:configure.ac:38: -1- AH_OUTPUT([HAVE_SYS_STAT_H], [/* Define to 1 if you have the <sys/stat.h> header file. */
@%:@undef HAVE_SYS_STAT_H])
m4trace:configure.ac:38: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the <stdlib.h> header file. */
@%:@undef HAVE_STDLIB_H])
m4trace:configure.ac:38: -1- AH_OUTPUT([HAVE_STRING_H], [/* Define to 1 if you have the <string.h> header file. */
@%:@undef HAVE_STRING_H])
m4trace:configure.ac:38: -1- AH_OUTPUT([HAVE_MEMORY_H], [/* Define to 1 if you have the <memory.h> header file. */
@%:@undef HAVE_MEMORY_H])
m4trace:configure.ac:38: -1- AH_OUTPUT([HAVE_STRINGS_H], [/* Define to 1 if you have the <strings.h> header file. */
@%:@undef HAVE_STRINGS_H])
m4trace:configure.ac:38: -1- AH_OUTPUT([HAVE_INTTYPES_H], [/* Define to 1 if you have the <inttypes.h> header file. */
@%:@undef HAVE_INTTYPES_H])
m4trace:configure.ac:38: -1- AH_OUTPUT([HAVE_STDINT_H], [/* Define to 1 if you have the <stdint.h> header file. */
@%:@undef HAVE_STDINT_H])
m4trace:configure.ac:38: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the <unistd.h> header file. */
@%:@undef HAVE_UNISTD_H])
m4trace:configure.ac:38: -1- AC_DEFINE_TRACE_LITERAL([_POSIX_SOURCE])
m4trace:configure.ac:38: -1- m4_pattern_allow([^_POSIX_SOURCE$])
m4trace:configure.ac:38: -1- AH_OUTPUT([_POSIX_SOURCE], [/* Define to 1 if you need to in order for `stat\' and other things to work. */
@%:@undef _POSIX_SOURCE])
m4trace:configure.ac:38: -1- AC_DEFINE_TRACE_LITERAL([_POSIX_1_SOURCE])
m4trace:configure.ac:38: -1- m4_pattern_allow([^_POSIX_1_SOURCE$])
m4trace:configure.ac:38: -1- AH_OUTPUT([_POSIX_1_SOURCE], [/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
@%:@undef _POSIX_1_SOURCE])
m4trace:configure.ac:38: -1- AC_DEFINE_TRACE_LITERAL([_MINIX])
m4trace:configure.ac:38: -1- m4_pattern_allow([^_MINIX$])
m4trace:configure.ac:38: -1- AH_OUTPUT([_MINIX], [/* Define to 1 if on MINIX. */
@%:@undef _MINIX])
m4trace:configure.ac:38: -1- AH_OUTPUT([USE_SYSTEM_EXTENSIONS], [/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# undef _GNU_SOURCE
#endif
/* Enable threading extensions on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# undef _POSIX_PTHREAD_SEMANTICS
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# undef _TANDEM_SOURCE
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# undef __EXTENSIONS__
#endif
])
m4trace:configure.ac:38: -1- AC_DEFINE_TRACE_LITERAL([__EXTENSIONS__])
m4trace:configure.ac:38: -1- m4_pattern_allow([^__EXTENSIONS__$])
m4trace:configure.ac:38: -1- AC_DEFINE_TRACE_LITERAL([_ALL_SOURCE])
m4trace:configure.ac:38: -1- m4_pattern_allow([^_ALL_SOURCE$])
m4trace:configure.ac:38: -1- AC_DEFINE_TRACE_LITERAL([_GNU_SOURCE])
m4trace:configure.ac:38: -1- m4_pattern_allow([^_GNU_SOURCE$])
m4trace:configure.ac:38: -1- AC_DEFINE_TRACE_LITERAL([_POSIX_PTHREAD_SEMANTICS])
m4trace:configure.ac:38: -1- m4_pattern_allow([^_POSIX_PTHREAD_SEMANTICS$])
m4trace:configure.ac:38: -1- AC_DEFINE_TRACE_LITERAL([_TANDEM_SOURCE])
m4trace:configure.ac:38: -1- m4_pattern_allow([^_TANDEM_SOURCE$])
m4trace:configure.ac:41: -1- LT_INIT
m4trace:configure.ac:41: -1- m4_pattern_forbid([^_?LT_[A-Z_]+$])
m4trace:configure.ac:41: -1- m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])
m4trace:configure.ac:41: -1- AC_REQUIRE_AUX_FILE([ltmain.sh])
m4trace:configure.ac:41: -1- AC_SUBST([LIBTOOL])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([LIBTOOL])
m4trace:configure.ac:41: -1- m4_pattern_allow([^LIBTOOL$])
m4trace:configure.ac:41: -1- AC_CANONICAL_HOST
m4trace:configure.ac:41: -1- AC_CANONICAL_BUILD
m4trace:configure.ac:41: -1- AC_REQUIRE_AUX_FILE([config.sub])
m4trace:configure.ac:41: -1- AC_REQUIRE_AUX_FILE([config.guess])
m4trace:configure.ac:41: -1- AC_SUBST([build], [$ac_cv_build])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([build])
m4trace:configure.ac:41: -1- m4_pattern_allow([^build$])
m4trace:configure.ac:41: -1- AC_SUBST([build_cpu], [$[1]])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([build_cpu])
m4trace:configure.ac:41: -1- m4_pattern_allow([^build_cpu$])
m4trace:configure.ac:41: -1- AC_SUBST([build_vendor], [$[2]])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([build_vendor])
m4trace:configure.ac:41: -1- m4_pattern_allow([^build_vendor$])
m4trace:configure.ac:41: -1- AC_SUBST([build_os])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([build_os])
m4trace:configure.ac:41: -1- m4_pattern_allow([^build_os$])
m4trace:configure.ac:41: -1- AC_SUBST([host], [$ac_cv_host])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([host])
m4trace:configure.ac:41: -1- m4_pattern_allow([^host$])
m4trace:configure.ac:41: -1- AC_SUBST([host_cpu], [$[1]])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([host_cpu])
m4trace:configure.ac:41: -1- m4_pattern_allow([^host_cpu$])
m4trace:configure.ac:41: -1- AC_SUBST([host_vendor], [$[2]])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([host_vendor])
m4trace:configure.ac:41: -1- m4_pattern_allow([^host_vendor$])
m4trace:configure.ac:41: -1- AC_SUBST([host_os])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([host_os])
m4trace:configure.ac:41: -1- m4_pattern_allow([^host_os$])
m4trace:configure.ac:41: -1- AC_SUBST([SED])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([SED])
m4trace:configure.ac:41: -1- m4_pattern_allow([^SED$])
m4trace:configure.ac:41: -1- AC_SUBST([FGREP])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([FGREP])
m4trace:configure.ac:41: -1- m4_pattern_allow([^FGREP$])
m4trace:configure.ac:41: -1- AC_SUBST([GREP])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([GREP])
m4trace:configure.ac:41: -1- m4_pattern_allow([^GREP$])
m4trace:configure.ac:41: -1- AC_SUBST([LD])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([LD])
m4trace:configure.ac:41: -1- m4_pattern_allow([^LD$])
m4trace:configure.ac:41: -1- AC_SUBST([DUMPBIN])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([DUMPBIN])
m4trace:configure.ac:41: -1- m4_pattern_allow([^DUMPBIN$])
m4trace:configure.ac:41: -1- AC_SUBST([ac_ct_DUMPBIN])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([ac_ct_DUMPBIN])
m4trace:configure.ac:41: -1- m4_pattern_allow([^ac_ct_DUMPBIN$])
m4trace:configure.ac:41: -1- AC_SUBST([DUMPBIN])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([DUMPBIN])
m4trace:configure.ac:41: -1- m4_pattern_allow([^DUMPBIN$])
m4trace:configure.ac:41: -1- AC_SUBST([NM])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([NM])
m4trace:configure.ac:41: -1- m4_pattern_allow([^NM$])
m4trace:configure.ac:41: -1- AC_SUBST([LN_S], [$as_ln_s])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([LN_S])
m4trace:configure.ac:41: -1- m4_pattern_allow([^LN_S$])
m4trace:configure.ac:41: -1- AC_SUBST([OBJDUMP])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([OBJDUMP])
m4trace:configure.ac:41: -1- m4_pattern_allow([^OBJDUMP$])
m4trace:configure.ac:41: -1- AC_SUBST([OBJDUMP])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([OBJDUMP])
m4trace:configure.ac:41: -1- m4_pattern_allow([^OBJDUMP$])
m4trace:configure.ac:41: -1- AC_SUBST([DLLTOOL])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([DLLTOOL])
m4trace:configure.ac:41: -1- m4_pattern_allow([^DLLTOOL$])
m4trace:configure.ac:41: -1- AC_SUBST([DLLTOOL])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([DLLTOOL])
m4trace:configure.ac:41: -1- m4_pattern_allow([^DLLTOOL$])
m4trace:configure.ac:41: -1- AC_SUBST([AR])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([AR])
m4trace:configure.ac:41: -1- m4_pattern_allow([^AR$])
m4trace:configure.ac:41: -1- AC_SUBST([ac_ct_AR])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([ac_ct_AR])
m4trace:configure.ac:41: -1- m4_pattern_allow([^ac_ct_AR$])
m4trace:configure.ac:41: -1- AC_SUBST([STRIP])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([STRIP])
m4trace:configure.ac:41: -1- m4_pattern_allow([^STRIP$])
m4trace:configure.ac:41: -1- AC_SUBST([RANLIB])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([RANLIB])
m4trace:configure.ac:41: -1- m4_pattern_allow([^RANLIB$])
m4trace:configure.ac:41: -1- m4_pattern_allow([LT_OBJDIR])
m4trace:configure.ac:41: -1- AC_DEFINE_TRACE_LITERAL([LT_OBJDIR])
m4trace:configure.ac:41: -1- m4_pattern_allow([^LT_OBJDIR$])
m4trace:configure.ac:41: -1- AH_OUTPUT([LT_OBJDIR], [/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
@%:@undef LT_OBJDIR])
m4trace:configure.ac:41: -1- LT_SUPPORTED_TAG([CC])
m4trace:configure.ac:41: -1- AC_SUBST([MANIFEST_TOOL])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([MANIFEST_TOOL])
m4trace:configure.ac:41: -1- m4_pattern_allow([^MANIFEST_TOOL$])
m4trace:configure.ac:41: -1- AC_SUBST([DSYMUTIL])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([DSYMUTIL])
m4trace:configure.ac:41: -1- m4_pattern_allow([^DSYMUTIL$])
m4trace:configure.ac:41: -1- AC_SUBST([NMEDIT])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([NMEDIT])
m4trace:configure.ac:41: -1- m4_pattern_allow([^NMEDIT$])
m4trace:configure.ac:41: -1- AC_SUBST([LIPO])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([LIPO])
m4trace:configure.ac:41: -1- m4_pattern_allow([^LIPO$])
m4trace:configure.ac:41: -1- AC_SUBST([OTOOL])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([OTOOL])
m4trace:configure.ac:41: -1- m4_pattern_allow([^OTOOL$])
m4trace:configure.ac:41: -1- AC_SUBST([OTOOL64])
m4trace:configure.ac:41: -1- AC_SUBST_TRACE([OTOOL64])
m4trace:configure.ac:41: -1- m4_pattern_allow([^OTOOL64$])
m4trace:configure.ac:41: -1- AH_OUTPUT([HAVE_DLFCN_H], [/* Define to 1 if you have the <dlfcn.h> header file. */
@%:@undef HAVE_DLFCN_H])
m4trace:configure.ac:41: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DLFCN_H])
m4trace:configure.ac:41: -1- m4_pattern_allow([^HAVE_DLFCN_H$])
m4trace:configure.ac:47: -1- AC_SUBST([BASE_CFLAGS])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([BASE_CFLAGS])
m4trace:configure.ac:47: -1- m4_pattern_allow([^BASE_CFLAGS$])
m4trace:configure.ac:47: -1- AC_SUBST([CWARNFLAGS])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([CWARNFLAGS])
m4trace:configure.ac:47: -1- m4_pattern_allow([^CWARNFLAGS$])
m4trace:configure.ac:47: -1- AC_SUBST([STRICT_CFLAGS])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([STRICT_CFLAGS])
m4trace:configure.ac:47: -1- m4_pattern_allow([^STRICT_CFLAGS$])
m4trace:configure.ac:47: -1- AC_SUBST([BASE_CFLAGS])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([BASE_CFLAGS])
m4trace:configure.ac:47: -1- m4_pattern_allow([^BASE_CFLAGS$])
m4trace:configure.ac:47: -2- AC_SUBST([CWARNFLAGS])
m4trace:configure.ac:47: -2- AC_SUBST_TRACE([CWARNFLAGS])
m4trace:configure.ac:47: -2- m4_pattern_allow([^CWARNFLAGS$])
m4trace:configure.ac:47: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_VERSION_MAJOR])
m4trace:configure.ac:47: -1- m4_pattern_allow([^PACKAGE_VERSION_MAJOR$])
m4trace:configure.ac:47: -1- AH_OUTPUT([PACKAGE_VERSION_MAJOR], [/* Major version of this package */
@%:@undef PACKAGE_VERSION_MAJOR])
m4trace:configure.ac:47: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_VERSION_MINOR])
m4trace:configure.ac:47: -1- m4_pattern_allow([^PACKAGE_VERSION_MINOR$])
m4trace:configure.ac:47: -1- AH_OUTPUT([PACKAGE_VERSION_MINOR], [/* Minor version of this package */
@%:@undef PACKAGE_VERSION_MINOR])
m4trace:configure.ac:47: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_VERSION_PATCHLEVEL])
m4trace:configure.ac:47: -1- m4_pattern_allow([^PACKAGE_VERSION_PATCHLEVEL$])
m4trace:configure.ac:47: -1- AH_OUTPUT([PACKAGE_VERSION_PATCHLEVEL], [/* Patch version of this package */
@%:@undef PACKAGE_VERSION_PATCHLEVEL])
m4trace:configure.ac:47: -1- AC_SUBST([CHANGELOG_CMD])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([CHANGELOG_CMD])
m4trace:configure.ac:47: -1- m4_pattern_allow([^CHANGELOG_CMD$])
m4trace:configure.ac:47: -1- m4_pattern_forbid([^_?PKG_[A-Z_]+$])
m4trace:configure.ac:47: -1- m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
m4trace:configure.ac:47: -1- m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
m4trace:configure.ac:47: -1- AC_SUBST([PKG_CONFIG])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([PKG_CONFIG])
m4trace:configure.ac:47: -1- m4_pattern_allow([^PKG_CONFIG$])
m4trace:configure.ac:47: -1- AC_SUBST([PKG_CONFIG_PATH])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([PKG_CONFIG_PATH])
m4trace:configure.ac:47: -1- m4_pattern_allow([^PKG_CONFIG_PATH$])
m4trace:configure.ac:47: -1- AC_SUBST([PKG_CONFIG_LIBDIR])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([PKG_CONFIG_LIBDIR])
m4trace:configure.ac:47: -1- m4_pattern_allow([^PKG_CONFIG_LIBDIR$])
m4trace:configure.ac:47: -1- AC_SUBST([PKG_CONFIG])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([PKG_CONFIG])
m4trace:configure.ac:47: -1- m4_pattern_allow([^PKG_CONFIG$])
m4trace:configure.ac:47: -1- AC_SUBST([INSTALL_CMD])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([INSTALL_CMD])
m4trace:configure.ac:47: -1- m4_pattern_allow([^INSTALL_CMD$])
m4trace:configure.ac:47: -1- AC_SUBST([APP_MAN_SUFFIX])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([APP_MAN_SUFFIX])
m4trace:configure.ac:47: -1- m4_pattern_allow([^APP_MAN_SUFFIX$])
m4trace:configure.ac:47: -1- AC_SUBST([LIB_MAN_SUFFIX])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([LIB_MAN_SUFFIX])
m4trace:configure.ac:47: -1- m4_pattern_allow([^LIB_MAN_SUFFIX$])
m4trace:configure.ac:47: -1- AC_SUBST([FILE_MAN_SUFFIX])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([FILE_MAN_SUFFIX])
m4trace:configure.ac:47: -1- m4_pattern_allow([^FILE_MAN_SUFFIX$])
m4trace:configure.ac:47: -1- AC_SUBST([MISC_MAN_SUFFIX])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([MISC_MAN_SUFFIX])
m4trace:configure.ac:47: -1- m4_pattern_allow([^MISC_MAN_SUFFIX$])
m4trace:configure.ac:47: -1- AC_SUBST([DRIVER_MAN_SUFFIX])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([DRIVER_MAN_SUFFIX])
m4trace:configure.ac:47: -1- m4_pattern_allow([^DRIVER_MAN_SUFFIX$])
m4trace:configure.ac:47: -1- AC_SUBST([ADMIN_MAN_SUFFIX])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([ADMIN_MAN_SUFFIX])
m4trace:configure.ac:47: -1- m4_pattern_allow([^ADMIN_MAN_SUFFIX$])
m4trace:configure.ac:47: -1- AC_SUBST([APP_MAN_DIR])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([APP_MAN_DIR])
m4trace:configure.ac:47: -1- m4_pattern_allow([^APP_MAN_DIR$])
m4trace:configure.ac:47: -1- AC_SUBST([LIB_MAN_DIR])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([LIB_MAN_DIR])
m4trace:configure.ac:47: -1- m4_pattern_allow([^LIB_MAN_DIR$])
m4trace:configure.ac:47: -1- AC_SUBST([FILE_MAN_DIR])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([FILE_MAN_DIR])
m4trace:configure.ac:47: -1- m4_pattern_allow([^FILE_MAN_DIR$])
m4trace:configure.ac:47: -1- AC_SUBST([MISC_MAN_DIR])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([MISC_MAN_DIR])
m4trace:configure.ac:47: -1- m4_pattern_allow([^MISC_MAN_DIR$])
m4trace:configure.ac:47: -1- AC_SUBST([DRIVER_MAN_DIR])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([DRIVER_MAN_DIR])
m4trace:configure.ac:47: -1- m4_pattern_allow([^DRIVER_MAN_DIR$])
m4trace:configure.ac:47: -1- AC_SUBST([ADMIN_MAN_DIR])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([ADMIN_MAN_DIR])
m4trace:configure.ac:47: -1- m4_pattern_allow([^ADMIN_MAN_DIR$])
m4trace:configure.ac:47: -1- AC_SUBST([XORG_MAN_PAGE])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([XORG_MAN_PAGE])
m4trace:configure.ac:47: -1- m4_pattern_allow([^XORG_MAN_PAGE$])
m4trace:configure.ac:47: -1- AC_SUBST([MAN_SUBSTS])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([MAN_SUBSTS])
m4trace:configure.ac:47: -1- m4_pattern_allow([^MAN_SUBSTS$])
m4trace:configure.ac:47: -1- AM_SILENT_RULES([yes])
m4trace:configure.ac:47: -1- AC_SUBST([AM_V])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([AM_V])
m4trace:configure.ac:47: -1- m4_pattern_allow([^AM_V$])
m4trace:configure.ac:47: -1- _AM_SUBST_NOTMAKE([AM_V])
m4trace:configure.ac:47: -1- AC_SUBST([AM_DEFAULT_V])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([AM_DEFAULT_V])
m4trace:configure.ac:47: -1- m4_pattern_allow([^AM_DEFAULT_V$])
m4trace:configure.ac:47: -1- _AM_SUBST_NOTMAKE([AM_DEFAULT_V])
m4trace:configure.ac:47: -1- AC_SUBST([AM_DEFAULT_VERBOSITY])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([AM_DEFAULT_VERBOSITY])
m4trace:configure.ac:47: -1- m4_pattern_allow([^AM_DEFAULT_VERBOSITY$])
m4trace:configure.ac:47: -1- AC_SUBST([AM_BACKSLASH])
m4trace:configure.ac:47: -1- AC_SUBST_TRACE([AM_BACKSLASH])
m4trace:configure.ac:47: -1- m4_pattern_allow([^AM_BACKSLASH$])
m4trace:configure.ac:47: -1- _AM_SUBST_NOTMAKE([AM_BACKSLASH])
m4trace:configure.ac:48: -1- AC_SUBST([XORG_MALLOC_DEBUG_ENV])
m4trace:configure.ac:48: -1- AC_SUBST_TRACE([XORG_MALLOC_DEBUG_ENV])
m4trace:configure.ac:48: -1- m4_pattern_allow([^XORG_MALLOC_DEBUG_ENV$])
m4trace:configure.ac:48: -1- AC_SUBST([XORG_MALLOC_DEBUG_ENV], [$malloc_debug_env])
m4trace:configure.ac:48: -1- AC_SUBST_TRACE([XORG_MALLOC_DEBUG_ENV])
m4trace:configure.ac:48: -1- m4_pattern_allow([^XORG_MALLOC_DEBUG_ENV$])
m4trace:configure.ac:49: -1- AM_CONDITIONAL([ENABLE_DOCS], [test x$build_docs = xyes])
m4trace:configure.ac:49: -1- AC_SUBST([ENABLE_DOCS_TRUE])
m4trace:configure.ac:49: -1- AC_SUBST_TRACE([ENABLE_DOCS_TRUE])
m4trace:configure.ac:49: -1- m4_pattern_allow([^ENABLE_DOCS_TRUE$])
m4trace:configure.ac:49: -1- AC_SUBST([ENABLE_DOCS_FALSE])
m4trace:configure.ac:49: -1- AC_SUBST_TRACE([ENABLE_DOCS_FALSE])
m4trace:configure.ac:49: -1- m4_pattern_allow([^ENABLE_DOCS_FALSE$])
m4trace:configure.ac:49: -1- _AM_SUBST_NOTMAKE([ENABLE_DOCS_TRUE])
m4trace:configure.ac:49: -1- _AM_SUBST_NOTMAKE([ENABLE_DOCS_FALSE])
m4trace:configure.ac:50: -1- AC_SUBST([DOXYGEN])
m4trace:configure.ac:50: -1- AC_SUBST_TRACE([DOXYGEN])
m4trace:configure.ac:50: -1- m4_pattern_allow([^DOXYGEN$])
m4trace:configure.ac:50: -1- AC_SUBST([DOXYGEN])
m4trace:configure.ac:50: -1- AC_SUBST_TRACE([DOXYGEN])
m4trace:configure.ac:50: -1- m4_pattern_allow([^DOXYGEN$])
m4trace:configure.ac:50: -1- AC_SUBST([DOXYGEN])
m4trace:configure.ac:50: -1- AC_SUBST_TRACE([DOXYGEN])
m4trace:configure.ac:50: -1- m4_pattern_allow([^DOXYGEN$])
m4trace:configure.ac:50: -1- AM_CONDITIONAL([HAVE_DOXYGEN], [test "$have_doxygen" = yes])
m4trace:configure.ac:50: -1- AC_SUBST([HAVE_DOXYGEN_TRUE])
m4trace:configure.ac:50: -1- AC_SUBST_TRACE([HAVE_DOXYGEN_TRUE])
m4trace:configure.ac:50: -1- m4_pattern_allow([^HAVE_DOXYGEN_TRUE$])
m4trace:configure.ac:50: -1- AC_SUBST([HAVE_DOXYGEN_FALSE])
m4trace:configure.ac:50: -1- AC_SUBST_TRACE([HAVE_DOXYGEN_FALSE])
m4trace:configure.ac:50: -1- m4_pattern_allow([^HAVE_DOXYGEN_FALSE$])
m4trace:configure.ac:50: -1- _AM_SUBST_NOTMAKE([HAVE_DOXYGEN_TRUE])
m4trace:configure.ac:50: -1- _AM_SUBST_NOTMAKE([HAVE_DOXYGEN_FALSE])
m4trace:configure.ac:53: -1- AM_PROG_CC_C_O
m4trace:configure.ac:56: -1- AH_OUTPUT([inline], [/* Define to `__inline__\' or `__inline\' if that\'s what the C compiler
calls it, or to nothing if \'inline\' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif])
m4trace:configure.ac:60: -1- m4_pattern_forbid([^_?PKG_[A-Z_]+$])
m4trace:configure.ac:60: -1- m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
m4trace:configure.ac:60: -1- m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
m4trace:configure.ac:60: -1- AC_SUBST([PKG_CONFIG])
m4trace:configure.ac:60: -1- AC_SUBST_TRACE([PKG_CONFIG])
m4trace:configure.ac:60: -1- m4_pattern_allow([^PKG_CONFIG$])
m4trace:configure.ac:60: -1- AC_SUBST([PKG_CONFIG_PATH])
m4trace:configure.ac:60: -1- AC_SUBST_TRACE([PKG_CONFIG_PATH])
m4trace:configure.ac:60: -1- m4_pattern_allow([^PKG_CONFIG_PATH$])
m4trace:configure.ac:60: -1- AC_SUBST([PKG_CONFIG_LIBDIR])
m4trace:configure.ac:60: -1- AC_SUBST_TRACE([PKG_CONFIG_LIBDIR])
m4trace:configure.ac:60: -1- m4_pattern_allow([^PKG_CONFIG_LIBDIR$])
m4trace:configure.ac:60: -1- AC_SUBST([PKG_CONFIG])
m4trace:configure.ac:60: -1- AC_SUBST_TRACE([PKG_CONFIG])
m4trace:configure.ac:60: -1- m4_pattern_allow([^PKG_CONFIG$])
m4trace:configure.ac:64: -1- AC_SUBST([YACC])
m4trace:configure.ac:64: -1- AC_SUBST_TRACE([YACC])
m4trace:configure.ac:64: -1- m4_pattern_allow([^YACC$])
m4trace:configure.ac:64: -1- AC_SUBST([YACC])
m4trace:configure.ac:64: -1- AC_SUBST_TRACE([YACC])
m4trace:configure.ac:64: -1- m4_pattern_allow([^YACC$])
m4trace:configure.ac:64: -1- AC_SUBST([YFLAGS])
m4trace:configure.ac:64: -1- AC_SUBST_TRACE([YFLAGS])
m4trace:configure.ac:64: -1- m4_pattern_allow([^YFLAGS$])
m4trace:configure.ac:65: -1- AC_SUBST([YACC_INST])
m4trace:configure.ac:65: -1- AC_SUBST_TRACE([YACC_INST])
m4trace:configure.ac:65: -1- m4_pattern_allow([^YACC_INST$])
m4trace:configure.ac:71: -1- AH_OUTPUT([HAVE_STRCASECMP], [/* Define to 1 if you have the `strcasecmp\' function. */
@%:@undef HAVE_STRCASECMP])
m4trace:configure.ac:71: -1- AH_OUTPUT([HAVE_STRNCASECMP], [/* Define to 1 if you have the `strncasecmp\' function. */
@%:@undef HAVE_STRNCASECMP])
m4trace:configure.ac:77: -1- AH_OUTPUT([HAVE_EACCESS], [/* Define to 1 if you have the `eaccess\' function. */
@%:@undef HAVE_EACCESS])
m4trace:configure.ac:77: -1- AH_OUTPUT([HAVE_EUIDACCESS], [/* Define to 1 if you have the `euidaccess\' function. */
@%:@undef HAVE_EUIDACCESS])
m4trace:configure.ac:77: -1- AH_OUTPUT([HAVE_MMAP], [/* Define to 1 if you have the `mmap\' function. */
@%:@undef HAVE_MMAP])
m4trace:configure.ac:79: -1- AH_OUTPUT([HAVE_SECURE_GETENV], [/* Define to 1 if you have the `secure_getenv\' function. */
@%:@undef HAVE_SECURE_GETENV])
m4trace:configure.ac:79: -1- AH_OUTPUT([HAVE___SECURE_GETENV], [/* Define to 1 if you have the `__secure_getenv\' function. */
@%:@undef HAVE___SECURE_GETENV])
m4trace:configure.ac:85: -1- AC_DEFINE_TRACE_LITERAL([HAVE___BUILTIN_EXPECT])
m4trace:configure.ac:85: -1- m4_pattern_allow([^HAVE___BUILTIN_EXPECT$])
m4trace:configure.ac:85: -1- AH_OUTPUT([HAVE___BUILTIN_EXPECT], [/* Define to 1 if the system has the `__builtin_expect\' built-in function */
@%:@undef HAVE___BUILTIN_EXPECT])
m4trace:configure.ac:89: -1- AM_CONDITIONAL([BUILD_LINUX_TESTS], [test "x$ac_cv_header_linux_input_h" = xyes])
m4trace:configure.ac:89: -1- AC_SUBST([BUILD_LINUX_TESTS_TRUE])
m4trace:configure.ac:89: -1- AC_SUBST_TRACE([BUILD_LINUX_TESTS_TRUE])
m4trace:configure.ac:89: -1- m4_pattern_allow([^BUILD_LINUX_TESTS_TRUE$])
m4trace:configure.ac:89: -1- AC_SUBST([BUILD_LINUX_TESTS_FALSE])
m4trace:configure.ac:89: -1- AC_SUBST_TRACE([BUILD_LINUX_TESTS_FALSE])
m4trace:configure.ac:89: -1- m4_pattern_allow([^BUILD_LINUX_TESTS_FALSE$])
m4trace:configure.ac:89: -1- _AM_SUBST_NOTMAKE([BUILD_LINUX_TESTS_TRUE])
m4trace:configure.ac:89: -1- _AM_SUBST_NOTMAKE([BUILD_LINUX_TESTS_FALSE])
m4trace:configure.ac:104: -1- AM_CONDITIONAL([HAVE_NO_UNDEFINED], [test "x$have_no_undefined" = xyes])
m4trace:configure.ac:104: -1- AC_SUBST([HAVE_NO_UNDEFINED_TRUE])
m4trace:configure.ac:104: -1- AC_SUBST_TRACE([HAVE_NO_UNDEFINED_TRUE])
m4trace:configure.ac:104: -1- m4_pattern_allow([^HAVE_NO_UNDEFINED_TRUE$])
m4trace:configure.ac:104: -1- AC_SUBST([HAVE_NO_UNDEFINED_FALSE])
m4trace:configure.ac:104: -1- AC_SUBST_TRACE([HAVE_NO_UNDEFINED_FALSE])
m4trace:configure.ac:104: -1- m4_pattern_allow([^HAVE_NO_UNDEFINED_FALSE$])
m4trace:configure.ac:104: -1- _AM_SUBST_NOTMAKE([HAVE_NO_UNDEFINED_TRUE])
m4trace:configure.ac:104: -1- _AM_SUBST_NOTMAKE([HAVE_NO_UNDEFINED_FALSE])
m4trace:configure.ac:106: -1- AC_SUBST([RT_LIBS], ["-lrt"])
m4trace:configure.ac:106: -1- AC_SUBST_TRACE([RT_LIBS])
m4trace:configure.ac:106: -1- m4_pattern_allow([^RT_LIBS$])
m4trace:configure.ac:106: -1- AC_SUBST([RT_LIBS], [""])
m4trace:configure.ac:106: -1- AC_SUBST_TRACE([RT_LIBS])
m4trace:configure.ac:106: -1- m4_pattern_allow([^RT_LIBS$])
m4trace:configure.ac:121: -1- AC_SUBST([XKBCONFIGROOT])
m4trace:configure.ac:121: -1- AC_SUBST_TRACE([XKBCONFIGROOT])
m4trace:configure.ac:121: -1- m4_pattern_allow([^XKBCONFIGROOT$])
m4trace:configure.ac:129: -1- AC_SUBST([XLOCALEDIR])
m4trace:configure.ac:129: -1- AC_SUBST_TRACE([XLOCALEDIR])
m4trace:configure.ac:129: -1- m4_pattern_allow([^XLOCALEDIR$])
m4trace:configure.ac:136: -1- AC_DEFINE_TRACE_LITERAL([DEFAULT_XKB_RULES])
m4trace:configure.ac:136: -1- m4_pattern_allow([^DEFAULT_XKB_RULES$])
m4trace:configure.ac:136: -1- AH_OUTPUT([DEFAULT_XKB_RULES], [/* Default XKB ruleset */
@%:@undef DEFAULT_XKB_RULES])
m4trace:configure.ac:144: -1- AC_DEFINE_TRACE_LITERAL([DEFAULT_XKB_MODEL])
m4trace:configure.ac:144: -1- m4_pattern_allow([^DEFAULT_XKB_MODEL$])
m4trace:configure.ac:144: -1- AH_OUTPUT([DEFAULT_XKB_MODEL], [/* Default XKB model */
@%:@undef DEFAULT_XKB_MODEL])
m4trace:configure.ac:152: -1- AC_DEFINE_TRACE_LITERAL([DEFAULT_XKB_LAYOUT])
m4trace:configure.ac:152: -1- m4_pattern_allow([^DEFAULT_XKB_LAYOUT$])
m4trace:configure.ac:152: -1- AH_OUTPUT([DEFAULT_XKB_LAYOUT], [/* Default XKB layout */
@%:@undef DEFAULT_XKB_LAYOUT])
m4trace:configure.ac:160: -1- AC_DEFINE_TRACE_LITERAL([DEFAULT_XKB_VARIANT])
m4trace:configure.ac:160: -1- m4_pattern_allow([^DEFAULT_XKB_VARIANT$])
m4trace:configure.ac:160: -1- AH_OUTPUT([DEFAULT_XKB_VARIANT], [/* Default XKB variant */
@%:@undef DEFAULT_XKB_VARIANT])
m4trace:configure.ac:170: -1- AC_DEFINE_TRACE_LITERAL([DEFAULT_XKB_OPTIONS])
m4trace:configure.ac:170: -1- m4_pattern_allow([^DEFAULT_XKB_OPTIONS$])
m4trace:configure.ac:170: -1- AH_OUTPUT([DEFAULT_XKB_OPTIONS], [/* Default XKB options */
@%:@undef DEFAULT_XKB_OPTIONS])
m4trace:configure.ac:179: -1- AC_SUBST([XCB_XKB_CFLAGS])
m4trace:configure.ac:179: -1- AC_SUBST_TRACE([XCB_XKB_CFLAGS])
m4trace:configure.ac:179: -1- m4_pattern_allow([^XCB_XKB_CFLAGS$])
m4trace:configure.ac:179: -1- AC_SUBST([XCB_XKB_LIBS])
m4trace:configure.ac:179: -1- AC_SUBST_TRACE([XCB_XKB_LIBS])
m4trace:configure.ac:179: -1- m4_pattern_allow([^XCB_XKB_LIBS$])
m4trace:configure.ac:184: -1- AM_CONDITIONAL([ENABLE_X11], [test "x$enable_x11" = xyes])
m4trace:configure.ac:184: -1- AC_SUBST([ENABLE_X11_TRUE])
m4trace:configure.ac:184: -1- AC_SUBST_TRACE([ENABLE_X11_TRUE])
m4trace:configure.ac:184: -1- m4_pattern_allow([^ENABLE_X11_TRUE$])
m4trace:configure.ac:184: -1- AC_SUBST([ENABLE_X11_FALSE])
m4trace:configure.ac:184: -1- AC_SUBST_TRACE([ENABLE_X11_FALSE])
m4trace:configure.ac:184: -1- m4_pattern_allow([^ENABLE_X11_FALSE$])
m4trace:configure.ac:184: -1- _AM_SUBST_NOTMAKE([ENABLE_X11_TRUE])
m4trace:configure.ac:184: -1- _AM_SUBST_NOTMAKE([ENABLE_X11_FALSE])
m4trace:configure.ac:186: -1- AC_CONFIG_FILES([
Makefile
xkbcommon-uninstalled.pc
xkbcommon.pc
xkbcommon-x11.pc
xkbcommon-x11-uninstalled.pc
doc/Doxyfile
])
m4trace:configure.ac:194: -1- AC_SUBST([LIB@&t@OBJS], [$ac_libobjs])
m4trace:configure.ac:194: -1- AC_SUBST_TRACE([LIB@&t@OBJS])
m4trace:configure.ac:194: -1- m4_pattern_allow([^LIB@&t@OBJS$])
m4trace:configure.ac:194: -1- AC_SUBST([LTLIBOBJS], [$ac_ltlibobjs])
m4trace:configure.ac:194: -1- AC_SUBST_TRACE([LTLIBOBJS])
m4trace:configure.ac:194: -1- m4_pattern_allow([^LTLIBOBJS$])
m4trace:configure.ac:194: -1- AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])
m4trace:configure.ac:194: -1- AC_SUBST([am__EXEEXT_TRUE])
m4trace:configure.ac:194: -1- AC_SUBST_TRACE([am__EXEEXT_TRUE])
m4trace:configure.ac:194: -1- m4_pattern_allow([^am__EXEEXT_TRUE$])
m4trace:configure.ac:194: -1- AC_SUBST([am__EXEEXT_FALSE])
m4trace:configure.ac:194: -1- AC_SUBST_TRACE([am__EXEEXT_FALSE])
m4trace:configure.ac:194: -1- m4_pattern_allow([^am__EXEEXT_FALSE$])
m4trace:configure.ac:194: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_TRUE])
m4trace:configure.ac:194: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_FALSE])
m4trace:configure.ac:194: -1- AC_SUBST_TRACE([top_builddir])
m4trace:configure.ac:194: -1- AC_SUBST_TRACE([top_build_prefix])
m4trace:configure.ac:194: -1- AC_SUBST_TRACE([srcdir])
m4trace:configure.ac:194: -1- AC_SUBST_TRACE([abs_srcdir])
m4trace:configure.ac:194: -1- AC_SUBST_TRACE([top_srcdir])
m4trace:configure.ac:194: -1- AC_SUBST_TRACE([abs_top_srcdir])
m4trace:configure.ac:194: -1- AC_SUBST_TRACE([builddir])
m4trace:configure.ac:194: -1- AC_SUBST_TRACE([abs_builddir])
m4trace:configure.ac:194: -1- AC_SUBST_TRACE([abs_top_builddir])
m4trace:configure.ac:194: -1- AC_SUBST_TRACE([INSTALL])
m4trace:configure.ac:194: -1- AC_SUBST_TRACE([MKDIR_P])
m4trace:configure.ac:194: -1- AC_REQUIRE_AUX_FILE([ltmain.sh])

File diff suppressed because it is too large Load Diff

View File

@ -1,247 +0,0 @@
#! /bin/sh
# ylwrap - wrapper for lex/yacc invocations.
scriptversion=2013-01-12.17; # UTC
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
#
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
get_dirname ()
{
case $1 in
*/*|*\\*) printf '%s\n' "$1" | sed -e 's|\([\\/]\)[^\\/]*$|\1|';;
# Otherwise, we want the empty string (not ".").
esac
}
# guard FILE
# ----------
# The CPP macro used to guard inclusion of FILE.
guard ()
{
printf '%s\n' "$1" \
| sed \
-e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \
-e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g' \
-e 's/__*/_/g'
}
# quote_for_sed [STRING]
# ----------------------
# Return STRING (or stdin) quoted to be used as a sed pattern.
quote_for_sed ()
{
case $# in
0) cat;;
1) printf '%s\n' "$1";;
esac \
| sed -e 's|[][\\.*]|\\&|g'
}
case "$1" in
'')
echo "$0: No files given. Try '$0 --help' for more information." 1>&2
exit 1
;;
--basedir)
basedir=$2
shift 2
;;
-h|--h*)
cat <<\EOF
Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]...
Wrapper for lex/yacc invocations, renaming files as desired.
INPUT is the input file
OUTPUT is one file PROG generates
DESIRED is the file we actually want instead of OUTPUT
PROGRAM is program to run
ARGS are passed to PROG
Any number of OUTPUT,DESIRED pairs may be used.
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v|--v*)
echo "ylwrap $scriptversion"
exit $?
;;
esac
# The input.
input=$1
shift
# We'll later need for a correct munging of "#line" directives.
input_sub_rx=`get_dirname "$input" | quote_for_sed`
case $input in
[\\/]* | ?:[\\/]*)
# Absolute path; do nothing.
;;
*)
# Relative path. Make it absolute.
input=`pwd`/$input
;;
esac
input_rx=`get_dirname "$input" | quote_for_sed`
# Since DOS filename conventions don't allow two dots,
# the DOS version of Bison writes out y_tab.c instead of y.tab.c
# and y_tab.h instead of y.tab.h. Test to see if this is the case.
y_tab_nodot=false
if test -f y_tab.c || test -f y_tab.h; then
y_tab_nodot=true
fi
# The parser itself, the first file, is the destination of the .y.c
# rule in the Makefile.
parser=$1
# A sed program to s/FROM/TO/g for all the FROM/TO so that, for
# instance, we rename #include "y.tab.h" into #include "parse.h"
# during the conversion from y.tab.c to parse.c.
sed_fix_filenames=
# Also rename header guards, as Bison 2.7 for instance uses its header
# guard in its implementation file.
sed_fix_header_guards=
while test $# -ne 0; do
if test x"$1" = x"--"; then
shift
break
fi
from=$1
# Handle y_tab.c and y_tab.h output by DOS
if $y_tab_nodot; then
case $from in
"y.tab.c") from=y_tab.c;;
"y.tab.h") from=y_tab.h;;
esac
fi
shift
to=$1
shift
sed_fix_filenames="${sed_fix_filenames}s|"`quote_for_sed "$from"`"|$to|g;"
sed_fix_header_guards="${sed_fix_header_guards}s|"`guard "$from"`"|"`guard "$to"`"|g;"
done
# The program to run.
prog=$1
shift
# Make any relative path in $prog absolute.
case $prog in
[\\/]* | ?:[\\/]*) ;;
*[\\/]*) prog=`pwd`/$prog ;;
esac
dirname=ylwrap$$
do_exit="cd '`pwd`' && rm -rf $dirname > /dev/null 2>&1;"' (exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
trap "ret=143; $do_exit" 15
mkdir $dirname || exit 1
cd $dirname
case $# in
0) "$prog" "$input" ;;
*) "$prog" "$@" "$input" ;;
esac
ret=$?
if test $ret -eq 0; then
for from in *
do
to=`printf '%s\n' "$from" | sed "$sed_fix_filenames"`
if test -f "$from"; then
# If $2 is an absolute path name, then just use that,
# otherwise prepend '../'.
case $to in
[\\/]* | ?:[\\/]*) target=$to;;
*) target=../$to;;
esac
# Do not overwrite unchanged header files to avoid useless
# recompilations. Always update the parser itself: it is the
# destination of the .y.c rule in the Makefile. Divert the
# output of all other files to a temporary file so we can
# compare them to existing versions.
if test $from != $parser; then
realtarget=$target
target=tmp-`printf '%s\n' "$target" | sed 's|.*[\\/]||g'`
fi
# Munge "#line" or "#" directives. Don't let the resulting
# debug information point at an absolute srcdir. Use the real
# output file name, not yy.lex.c for instance. Adjust the
# include guards too.
sed -e "/^#/!b" \
-e "s|$input_rx|$input_sub_rx|" \
-e "$sed_fix_filenames" \
-e "$sed_fix_header_guards" \
"$from" >"$target" || ret=$?
# Check whether files must be updated.
if test "$from" != "$parser"; then
if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then
echo "$to is unchanged"
rm -f "$target"
else
echo "updating $to"
mv -f "$target" "$realtarget"
fi
fi
else
# A missing file is only an error for the parser. This is a
# blatant hack to let us support using "yacc -d". If -d is not
# specified, don't fail when the header file is "missing".
if test "$from" = "$parser"; then
ret=1
fi
fi
done
fi
# Remove the directory.
cd ..
rm -rf $dirname
exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

View File

@ -1,214 +0,0 @@
dnl Copyright © 2008 Dan Nicholson
dnl
dnl Permission to use, copy, modify, distribute, and sell this software and its
dnl documentation for any purpose is hereby granted without fee, provided that
dnl the above copyright notice appear in all copies and that both that
dnl copyright notice and this permission notice appear in supporting
dnl documentation, and that the name of Keith Packard not be used in
dnl advertising or publicity pertaining to distribution of the software without
dnl specific, written prior permission. Keith Packard makes no
dnl representations about the suitability of this software for any purpose. It
dnl is provided "as is" without express or implied warranty.
dnl
dnl DAN NICHOLSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
dnl INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
dnl EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
dnl CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
dnl DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
dnl TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
dnl PERFORMANCE OF THIS SOFTWARE.
dnl
dnl Process this file with autoconf to create configure.
# Initialize Autoconf
AC_PREREQ([2.62])
AC_INIT([libxkbcommon], [0.5.0],
[https://bugs.freedesktop.org/enter_bug.cgi?product=libxkbcommon],
[libxkbcommon], [http://xkbcommon.org])
AC_CONFIG_SRCDIR([Makefile.am])
AC_CONFIG_HEADERS([src/config.h])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([build-aux])
# Initialize Automake
AM_INIT_AUTOMAKE([foreign dist-xz no-dist-gzip subdir-objects color-tests parallel-tests check-news])
AM_MAINTAINER_MODE([enable])
# Get _GNU_SOURCE and friends
AC_USE_SYSTEM_EXTENSIONS
# Initialize libtool
LT_INIT
# Add xorg-macros stuff
m4_ifndef([XORG_MACROS_VERSION],
[m4_fatal([must install xorg-macros 1.16 or later before running autoconf/autogen])])
XORG_MACROS_VERSION(1.16)
XORG_DEFAULT_OPTIONS
XORG_MEMORY_CHECK_FLAGS
XORG_ENABLE_DOCS
XORG_WITH_DOXYGEN
# Needed in older Automakes for subdir-objects
AM_PROG_CC_C_O
# Check for compiler features
AC_C_INLINE
# Check for programs
AC_PROG_MKDIR_P
PKG_PROG_PKG_CONFIG
# Note: we use some yacc extensions, which work with either GNU bison
# (preferred) or byacc. Other yacc's may or may not work.
AC_PROG_YACC
AC_PATH_PROG([YACC_INST], [$YACC])
AS_IF([test ! -f "src/xkbcomp/parser.c" -a "x$YACC_INST" = x], [
AC_MSG_ERROR([yacc not found - unable to compile src/xkbcomp/parser.y])
])
# Checks for library functions.
AC_CHECK_FUNCS([strcasecmp strncasecmp])
AS_IF([test "x$ac_cv_func_strcasecmp" = xno -o \
"x$ac_cv_func_strncasecmp" = xno], [
AC_MSG_ERROR([C library does not support strcasecmp/strncasecmp])
])
AC_CHECK_FUNCS([eaccess euidaccess mmap])
AC_CHECK_FUNCS([secure_getenv __secure_getenv])
AS_IF([test "x$ac_cv_func_secure_getenv" = xno -a \
"x$ac_cv_func___secure_getenv" = xno], [
AC_MSG_WARN([C library does not support secure_getenv, using getenv instead])
])
AX_GCC_BUILTIN(__builtin_expect)
# Some tests use Linux-specific headers
AC_CHECK_HEADER([linux/input.h])
AM_CONDITIONAL(BUILD_LINUX_TESTS, [test "x$ac_cv_header_linux_input_h" = xyes])
XORG_TESTSET_CFLAG([BASE_CFLAGS], [-fvisibility=hidden])
XORG_TESTSET_CFLAG([BASE_CFLAGS], [-Wextra -Wno-unused-parameter -Wno-missing-field-initializers])
XORG_TESTSET_CFLAG([BASE_CFLAGS], [-Wdocumentation])
# OpenBSD does not have DT_NEEDED entries for libc by design
# so when these flags are passed to ld via libtool the checks will fail
case "$host_os" in
openbsd*)
;;
*)
XORG_CHECK_LINKER_FLAGS([-Wl,--no-undefined], [have_no_undefined=yes]) ;;
esac
AM_CONDITIONAL([HAVE_NO_UNDEFINED], [test "x$have_no_undefined" = xyes])
AC_CHECK_LIB(rt, clock_gettime,
[AC_SUBST(RT_LIBS, "-lrt")],
[AC_SUBST(RT_LIBS, "")],
[-lrt])
# Define a configuration option for the XKB config root
xkb_base=`$PKG_CONFIG --variable=xkb_base xkeyboard-config`
AS_IF([test "x$xkb_base" = x], [
xkb_base="$datadir/X11/xkb"
])
AC_ARG_WITH([xkb_config_root],
[AS_HELP_STRING([--with-xkb-config-root=<path>],
[Set default XKB config root (default: xkeyboard-config install path)])],
[XKBCONFIGROOT="$withval"],
[XKBCONFIGROOT="$xkb_base"])
AC_SUBST([XKBCONFIGROOT])
# Define a configuration option for the X locale directory for compose
AC_ARG_WITH([x_locale_root],
[AS_HELP_STRING([--with-x-locale-root=<path>],
[Set X locale root (default: $datadir/X11/locale)])],
[XLOCALEDIR="$withval"],
[XLOCALEDIR="$datadir/X11/locale"])
AC_SUBST([XLOCALEDIR])
AC_ARG_WITH([default_rules],
[AS_HELP_STRING([--with-default-rules=<path>],
[Default XKB ruleset (default: evdev)])],
[DEFAULT_XKB_RULES="$withval"],
[DEFAULT_XKB_RULES="evdev"])
AC_DEFINE_UNQUOTED([DEFAULT_XKB_RULES], ["$DEFAULT_XKB_RULES"],
[Default XKB ruleset])
AC_ARG_WITH([default_model],
[AS_HELP_STRING([--with-default-model=<path>],
[Default XKB model (default: pc105)])],
[DEFAULT_XKB_MODEL="$withval"],
[DEFAULT_XKB_MODEL="pc105"])
AC_DEFINE_UNQUOTED([DEFAULT_XKB_MODEL], ["$DEFAULT_XKB_MODEL"],
[Default XKB model])
AC_ARG_WITH([default_layout],
[AS_HELP_STRING([--with-default-layout=<path>],
[Default XKB layout (default: us)])],
[DEFAULT_XKB_LAYOUT="$withval"],
[DEFAULT_XKB_LAYOUT="us"])
AC_DEFINE_UNQUOTED([DEFAULT_XKB_LAYOUT], ["$DEFAULT_XKB_LAYOUT"],
[Default XKB layout])
AC_ARG_WITH([default_variant],
[AS_HELP_STRING([--with-default-variant=<path>],
[Default XKB variant (default: (none))])],
[DEFAULT_XKB_VARIANT="$withval"],
[DEFAULT_XKB_VARIANT=])
AS_IF([test "x$DEFAULT_XKB_VARIANT" != x], [
AC_DEFINE_UNQUOTED([DEFAULT_XKB_VARIANT], ["$DEFAULT_XKB_VARIANT"],
[Default XKB variant])
])
AC_ARG_WITH([default_options],
[AS_HELP_STRING([--with-default-options=<path>],
[Default XKB options (default: (none))])],
[DEFAULT_XKB_OPTIONS="$withval"],
[DEFAULT_XKB_OPTIONS=])
AS_IF([test "x$DEFAULT_XKB_OPTIONS" != x], [
AC_DEFINE_UNQUOTED([DEFAULT_XKB_OPTIONS], ["$DEFAULT_XKB_OPTIONS"],
[Default XKB options])
])
AC_ARG_ENABLE([x11],
[AS_HELP_STRING([--disable-x11],
[Disable support for creating keymaps with the X11 protocol (default: enabled)])],
[], [enable_x11=yes])
AS_IF([test "x$enable_x11" = xyes], [
PKG_CHECK_MODULES([XCB_XKB], [xcb xcb-xkb >= 1.10], [],
[AC_MSG_ERROR([xkbcommon-x11 requires xcb-xkb >= 1.10 which was not found. \
You can disable X11 support with --disable-x11.])])
], [enable_x11=no])
AM_CONDITIONAL([ENABLE_X11], [test "x$enable_x11" = xyes])
AC_CONFIG_FILES([
Makefile
xkbcommon-uninstalled.pc
xkbcommon.pc
xkbcommon-x11.pc
xkbcommon-x11-uninstalled.pc
doc/Doxyfile
])
AC_OUTPUT
AC_MSG_RESULT([
$PACKAGE_NAME $VERSION
libxkbcommon: yes
libxkbcommon-x11: ${enable_x11}
documentation: ${build_docs}
default XKB rules: ${DEFAULT_XKB_RULES}
default XKB model: ${DEFAULT_XKB_MODEL}
default XKB layout: ${DEFAULT_XKB_LAYOUT}
default XKB variant: ${DEFAULT_XKB_VARIANT}
default XKB options: ${DEFAULT_XKB_OPTIONS}
prefix: ${prefix}
includedir: ${includedir}
lib dir: ${libdir}
XKB config root: ${XKBCONFIGROOT}
X11 locale root: ${XLOCALEDIR}
])

View File

@ -1,3 +0,0 @@
Doxyfile
html/
stamp-doxygen

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
# Compatibility
Relative to the XKB 1.1 specification implemented in current X servers,
Relative to the XKB 1.0 specification implemented in current X servers,
xkbcommon has removed support for some parts of the specification which
introduced unnecessary complications. Many of these removals were in fact
not implemented, or half-implemented at best, as well as being totally
@ -42,8 +42,8 @@ Notable additions:
- extended number of modifiers (planned)
- extended number of groups (planned)
- multiple keysyms per level
+ this requires incompatible dataset changes, such that X11 would
not be able to parse these
+ such levels are ignored by x11/xkbcomp.
- key names (e.g. `<AE11>`) can be longer than 4 characters.
## Compose support
@ -51,5 +51,6 @@ Relative to the standard implementation in libX11 (described in the
Compose(5) man-page), some features are not supported:
- the (! MODIFIER) syntax
+ parsed correctly but ignored.
- using modifier keysyms in Compose sequences
- several interactions with Braille keysyms

View File

@ -0,0 +1,472 @@
# The XKB keymap text format, V1
This document describes the `XKB_KEYMAP_FORMAT_TEXT_V1` keymap format,
as implemented by libxkbcommon.
NOTE: This document is ever incomplete. Some additional resources are:
- [Ivan Pascal's XKB documentation](https://web.archive.org/web/20190724015820/http://pascal.tsu.ru/en/xkb/)
- [An Unreliable Guide to XKB Configuration](https://www.charvolant.org/doug/xkb/html/index.html)
- [ArchWiki XKB page](https://wiki.archlinux.org/index.php/X_keyboard_extension)
A keymap consists of a single top-level `xkb_keymap` block, underwhich
are nested the following sections.
## The `xkb_keycodes` section
This is the simplest section type, and is the first one to be
compiled. The purpose of this is mostly to map between the
hardware/evdev scancodes and xkb keycodes. Each key is given a name
by which it can be referred to later, e.g. in the symbols section.
### Keycode statements
Statements of the form:
<TLDE> = 49;
<AE01> = 10;
The above would let 49 and 10 be valid keycodes in the keymap, and
assign them the names `TLDE` and `AE01` respectively. The format
`<WXYZ>` is always used to refer to a key by name.
[The naming convention `<AE01>` just denotes the position of the key
in the main alphanumeric section of a standard QWERTY keyboard, with
the two letters specifying the row and the two digits specifying the
column, from the bottom left.]
In the common case this just maps to the evdev scancodes from
`/usr/include/linux/input.h`, e.g. the following definitions:
#define KEY_GRAVE 41
#define KEY_1 2
correspond to the ones above. Similar definitions appear in the
xf86-input-keyboard driver. Note that in all current keymaps there's a
constant offset of 8 (for historical reasons).
If there's a conflict, like the same name given to different keycodes,
or same keycode given different names, it is resolved according to the
merge mode which applies to the definitions.
### Alias statements
Statements of the form:
alias <MENU> = <COMP>;
Allows to refer to a previously defined key (here `<COMP>`) by another
name (here `<MENU>`). Conflicts are handled similarly to keycode
statements.
### LED name statements
Statements of the form:
indicator 1 = "Caps Lock";
indicator 2 = "Num Lock";
indicator 3 = "Scroll Lock";
Assigns a name to the keyboard LED (AKA indicator) with the given
index. The LED may be referred by this name later in the compat
section and by the user.
## The `xkb_types` section
This section is the second to be processed, after `xkb_keycodes`.
However, it is completely independent and could have been the first to
be processed (it does not refer to specific keys as specified in the
`xkb_keycodes` section).
This section defines key types, which, given a key and a keyboard
state (i.e. modifier state and group), determine the shift level to be
used in translating the key to keysyms. These types are assigned to
each group in each key, in the `xkb_symbols` section.
Key types are called this way because, in a way, they really describe
the "type" of the key (or more correctly, a specific group of the
key). For example, an ordinary keymap will provide a type called
`KEYPAD`, which consists of two levels, with the second level being
chosen according to the state of the Num Lock (or Shift) modifiers.
Another example is a type called `ONE_LEVEL`, which is usually
assigned to keys such as Escape; these have just one level and are not
affected by the modifier state. Yet more common examples are
`TWO_LEVEL` (with Shift choosing the second level), `ALPHABETIC`
(where Caps Lock may also choose the second level), etc.
### Type definitions
Statements of the form:
type "FOUR_LEVEL" { ... }
The above would create a new type named `FOUR_LEVEL`.
The body of the definition may include statements of the following
forms:
#### `level_name` statements
level_name[Level1] = "Base";
Mandatory for each level in the type.
Gives each level in this type a descriptive name. It isn't used
for anything.
Note: A level may be specified as Level[1-8] or just a number (can
be more than 8).
#### `modifiers` statement
modifiers = Shift+Lock+LevelThree;
Mandatory, should be specified only once.
A mask of real and virtual modifiers. These are the only modifiers
being considered when matching the modifier state against the type.
The other modifiers, whether active or not, are masked out in the
calculation.
#### `map` entry statements
map[Shift+LevelThree] = Level4;
Should have at least as many mappings as there are levels in the type.
If the active modifiers, masked with the type's modifiers (as stated
above), match (i.e. equal) the modifiers inside the `map[]` statement,
then the level in the right hand side is chosen. For example, in the
above, if in the current keyboard state the `Shift` and `LevelThree`
modifiers are active, while the `Lock` modifier is not, then the
keysym(s) in the 4th level of the group will be returned to the user.
#### `preserve` statements
map[Shift+Lock+LevelThree] = Level5;
preserve[Shift+Lock+LevelThree] = Lock;
When a key type is used for keysym translation, its modifiers are said
to be "consumed". For example, in a simple US keymap, the "g" "g" key
is assigned an ordinary `ALPHABETIC` key type, whose modifiers are
Shift and Lock; then for the "g" key, these two modifiers are consumed
by the translation. This information is relevant for applications
which further process the modifiers, since by then the consumed
modifiers have already "done their part" and should be masked out.
However, sometimes even if a modifier had already affected the key
translation through the type, it should *not* be reported as consumed,
for various reasons. In this case, a `preserve[]` statement can be
used to augment the map entry. The modifiers inside the square
brackets should match one of the map[] statements in the type (if
there is no matching map entry, one mapping to Level1 is implicitly
added). The right hand side should consists of modifiers from the
type's modifiers; these modifiers are then "preserved" and not
reported as consumed.
## The `xkb_compat` section
This section is the third to be processed, after `xkb_keycodes` and
`xkb_types`.
### Interpret statements
Statements of the form:
interpret Num_Lock+Any { ... }
interpret Shift_Lock+AnyOf(Shift+Lock) { ... }
The `xkb_symbols` section (see below) allows the keymap author to
perform, among other things, the following things for each key:
- Bind an action, like SetMods or LockGroup, to the key. Actions, like
symbols, are specified for each level of each group in the key
separately.
- Add a virtual modifier to the key's virtual modifier mapping
(vmodmap).
- Specify whether the key should repeat or not.
However, doing this for each key (or level) is tedious and inflexible.
Interpret's are a mechanism to apply these settings to a bunch of
keys/levels at once.
Each interpret specifies a condition by which it attaches to certain
levels. The condition consists of two parts:
- A keysym. If the level has a different (or more than one) keysym,
the match fails. Leaving out the keysym is equivalent to using the
`NoSymbol` keysym, which always matches successfully.
- A modifier predicate. The predicate consists of a matching operation
and a mask of (real) modifiers. The modifiers are matched against
the key's modifier map (modmap). The matching operation can be one
of the following:
* `AnyOfOrNone` - The modmap must either be empty or include at
least one of the specified modifiers.
* `AnyOf` - The modmap must include at least one of the specified
modifiers.
* `NoneOf` - The modmap must not include any of the specified
modifiers.
* `AllOf` - The modmap must include all of the specified modifiers
(but may include others as well).
* `Exactly` - The modmap must be exactly the same as the specified
modifiers.
Leaving out the predicate is equivalent to using `AnyOfOrNone` while
specifying all modifiers. Leaving out just the matching condition is
equivalent to using `Exactly`.
An interpret may also include `useModMapMods = level1;` - see below.
If a level fulfils the conditions of several interprets, only the
most specific one is used:
- A specific keysym will always match before a generic `NoSymbol`
condition.
- If the keysyms are the same, the interpret with the more specific
matching operation is used. The above list is sorted from least to
most specific.
- If both the keysyms and the matching operations are the same (but the
modifiers are different), the first interpret is used.
As described above, once an interpret "attaches" to a level, it can bind
an action to that level, add one virtual modifier to the key's vmodmap,
or set the key's repeat setting. You should note the following:
- The key repeat is a property of the entire key; it is not
level-specific. In order to avoid confusion, it is only inspected
for the first level of the first group; the interpret's repeat
setting is ignored when applied to other levels.
- If one of the above fields was set directly for a key in
`xkb_symbols`, the explicit setting takes precedence over the
interpret.
The body of the statement may include statements of the following
forms (all of which are optional):
#### `useModMapMods` statement
useModMapMods = level1;
When set to `level1`, the interpret will only match levels which are
the first level of the first group of the keys. This can be useful in
conjunction with e.g. a `virtualModifier` statement.
#### `action` statement
action = LockMods(modifiers=NumLock);
Bind this action to the matching levels.
#### `virtualModifier` statement
virtualModifier = NumLock;
Add this virtual modifier to the key's vmodmap. The given virtual
modifier must be declared at the top level of the file with a
`virtual_modifiers` statement, e.g.:
virtual_modifiers NumLock;
#### `repeat` statement
repeat = True;
Set whether the key should repeat or not. Must be a boolean value.
### LED map statements
Statements of the form:
indicator "Shift Lock" { ... }
This statement specifies the behavior and binding of the LED (AKA
indicator) with the given name ("Shift Lock" above). The name should
have been declared previously in the `xkb_keycodes` section (see LED
name statement), and given an index there. If it wasn't, it is created
with the next free index.
The body of the statement describes the conditions of the keyboard
state which will cause the LED to be lit. It may include the following
statements:
#### `modifiers` statement
modifiers = ScrollLock;
If the given modifiers are in the required state (see below), the
LED is lit.
#### `whichModState` statement
whichModState = Latched+Locked;
Can be any combination of:
* `base`, `latched`, `locked`, `effective`
* `any` (i.e. all of the above)
* `none` (i.e. none of the above)
* `compat` (legacy value, treated as effective)
This will cause the respective portion of the modifier state (see
`struct xkb_state`) to be matched against the modifiers given in the
`modifiers` statement.
Here's a simple example:
indicator "Num Lock" {
modifiers = NumLock;
whichModState = Locked;
};
Whenever the NumLock modifier is locked, the Num Lock LED will light
up.
#### `groups` statement
groups = All - group1;
If the given groups are in the required state (see below), the LED is
lit.
#### `whichGroupState` statement
whichGroupState = Effective;
Can be any combination of:
* `base`, `latched`, `locked`, `effective`
* `any` (i.e. all of the above)
* `none` (i.e. none of the above)
This will cause the respective portion of the group state (see
`struct xkb_state`) to be matched against the groups given in the
`groups` statement.
Note: the above conditions are disjunctive, i.e. if any of them are
satisfied the LED is lit.
## The `xkb_symbols` section
NOTE: The documentation of this section is incomplete.
This section is the fourth to be processed, after `xkb_keycodes`, `xkb_types`
and `xkb_compat`.
Statements of the form:
xkb_symbols "basic" {
...
}
Declare a symbols map named `basic`. Statements inside the curly braces only
affect the symbols map.
A map can have various flags applied to it above the statement, separated by
whitespace:
partial alphanumeric_keys
xkb_symbols "basic" {
...
}
The possible flags are:
* `partial` - Indicates that the map doesn't cover a complete keyboard.
* `default` - Marks the symbol map as the default map in the file when no
explicit map is specified. If no map is marked as a default, the first map
in the file is the default.
* `hidden` - Variant that can only be used internally
* `alphanumeric_keys` - Indicates that the map contains alphanumeric keys
* `modifier_keys` - Indicates that the map contains modifier keys
* `keypad_keys` - Indicates that the map contains keypad keys
* `function_keys` - Indicates that the map contains function keys
* `alternate_group` - Indicates that the map contains keys for an alternate
group
If no `*_keys` flags are supplied, then the map is assumed to cover a complete
keyboard.
At present, except for `default`, none of the flags affect key processing in
libxkbcommon, and only serve as metadata.
### Name statements
Statements of the form:
name[Group1] = "US/ASCII";
groupName[1] = "US/ASCII";
Gives the name "US/ASCII" to the first group of symbols. Other groups can be
named using a different group index (ex: `Group2`), and with a different name.
A group must be named.
`group` and `groupName` mean the same thing, and the `Group` in `Group1` is
optional.
### Include statements
Statements of the form:
include "nokia_vndr/rx-51(nordic_base)
Will include data from another `xkb_symbols` section, possibly located in
another file. Here it would include the `xkb_symbols` section called
`nordic_base`, from the file `rx-51` located in the `nokia_vndr` folder, itself
located in an XKB include path.
### Key statement
Statements of the form:
key <AD01> { [ q, Q ] };
Describes the mapping of a keycode `<AD01>` to a given group of symbols. The
possible keycodes are the keycodes defined in the `xkb_keycodes` section.
Symbols are named using the symbolic names from the
`xkbcommon/xkbcommon-keysyms.h` file. A group of symbols is enclosed in brackets
and separated by commas. Each element of the symbol arrays corresponds to a
different modifier level. In this example, the symbol (keysym) `XKB_KEY_q` for
level 1 and `XKB_KEY_Q` for level 2.
#### Groups
Each group represents a list of symbols mapped to a keycode:
name[Group1]= "US/ASCII";
name[Group2]= "Russian";
...
key <AD01> { [ q, Q ],
[ Cyrillic_shorti, Cyrillic_SHORTI ] };
A long-form syntax can also be used:
key <AD01> {
symbols[Group1]= [ q, Q ],
symbols[Group2]= [ Cyrillic_shorti, Cyrillic_SHORTI ]
};
Groups can also be omitted, but the brackets must be present. The following
statement only defines the Group3 of a mapping:
key <AD01> { [], [], [ q, Q ] };
## Virtual modifier statements
Statements of the form:
virtual_modifiers LControl;
Can appear in the `xkb_types`, `xkb_compat`, `xkb_symbols` sections.
TODO

View File

@ -1,359 +0,0 @@
The xkb_keycodes section
========================
This is the simplest section type, and is the first one to be
compiled. The purpose of this is mostly to map between the
hardware/evdev scancodes and xkb keycodes. Each key is given a name
by which it can be referred to later, e.g. in the symbols section.
Keycode statements
------------------
Statements of the form:
<TLDE> = 49;
<AE01> = 10;
The above would let 49 and 10 be valid keycodes in the keymap, and
assign them the names TLDE and AE01 respectively. The format <WXYZ> is
always used to refer to a key by name.
[The naming convention <AE01> just denoted the position of the key
in the main alphanumric section of the keyboard, with the two letters
specifying the row and the two digits specifying the column, from
the bottom left.]
In the common case this just maps to the evdev scancodes from
/usr/include/linux/input.h, e.g. the following definitions:
#define KEY_GRAVE 41
#define KEY_1 2
correspond to the ones above. Similar definitions appear in the
xf86-input-keyboard driver. Note that in all current keymaps there's a
constant offset of 8 (for historical reasons).
If there's a conflict, like the same name given to different keycodes,
or same keycode given different names, it is resolved according to the
merge mode which applies to the definitions.
Alias statements
----------------
Statements of the form:
alias <MENU> = <COMP>;
Allows to refer to a previously defined key (here <COMP>) by another
name (here <MENU>). Conflicts are handled similarly to keycode
statements.
LED name statements
-------------------
Statements of the form:
indicator 1 = "Caps Lock";
indicator 2 = "Num Lock";
indicator 3 = "Scroll Lock";
Assigns a name to the keyboard LED (a.k.a indicator) with the given
index. The LED may be referred by this name later in the compat section
and by the user.
The xkb_types section
=====================
This section is the second to be processesed, after xkb_keycodes.
However, it is completely independent and could have been the first
to be processed (it does not refer to specific keys as specified in
the xkb_keycodes section).
This section defines key types, which, given a key and a keyboard
state (i.e. modifier state and group), determine the shift level to
be used in translating the key to keysyms. These types are assigned
to each group in each key, in the xkb_symbols section.
Key types are called this way because, in a way, they really describe
the "type" of the key (or more correctly, a specific group of the
key). For example, an ordinary keymap will provide a type called
"KEYPAD", which consists of two levels, with the second level being
chosen according to the state of the Num Lock (or Shift) modifiers.
Another example is a type called "ONE_LEVEL", which is usually
assigned to keys such as Escape; these have just one level and are
not affected by the modifier state. Yet more common examples are
"TWO_LEVEL" (with Shift choosing the second level), "ALPHABETIC"
(where Caps Lock may also choose the second level), etc.
Type definitions
----------------
Statements of the form:
type "FOUR_LEVEL" { ... }
The above would create a new type named "FOUR_LEVEL".
The body of the definition may include statements of the following
forms:
- level_name statements (mandatory for each level in the type):
level_name[Level1] = "Base";
Gives each level in this type a descriptive name. It isn't used
for anything.
Note: A level may be specified as Level[1-8] or just a number (can
be more than 8).
- modifiers statement (mandatory, should be specified only once):
modifiers = Shift+Lock+LevelThree;
A mask of real and virtual modifiers. These are the only modifiers
being considered when matching the modifier state against the type.
The other modifiers, whether active or not, are masked out in the
calculation.
- map entry statements (should have at least as many mappings as there
are levels in the type):
map[Shift+LevelThree] = Level4;
If the active modifiers, masked with the type's modifiers (as stated
above), match (i.e. equal) the modifiers inside the map[] statement,
then the level in the right hand side is chosen. For example, in the
above, if in the current keyboard state the Shift and LevelThree
modifiers are active, while the Lock modifier is not, then the
keysym(s) in the 4th level of the group will be returned to the
user.
- preserve statements:
map[Shift+Lock+LevelThree] = Level5;
preserve[Shift+Lock+LevelThree] = Lock;
When a map entry matches the active modifiers and the level it
specified is chosen, then these modifiers are said to be "consumed";
for example, in a simple US keymap where the "g" key is assigned an
ordinary ALPHABETIC key type, if the Lock (Caps Lock) modifier is
active and the key is pressed, then a "G" keysym is produced (as
opposed to lower-case "g"). This is because the type definition has
a map entry like the following:
map[Lock] = Level2;
And as such the Lock modifier is consumed. This information is
relevant for applications which further process the modifiers,
since by then the consumed modifiers have already "done their part"
and should be masked out.
However, sometimes even if a modifier is actually used to choose
the shift level (as Lock above), it should *not* be reported as
consumed, for various reasons. In this case, a preserve[] statement
can be used to augment the map entry. The modifiers inside the square
brackets should match one of the map[] statements in the type. The
right hand side should consists of modifiers from the left hand
side; these modifiers are then "preserved" and not reported as
consumed.
The xkb_compat section
======================
This section is the third to be processed, after xkb_keycodes and
xkb_types.
Interpret statements
--------------------
Statements of the form:
interpret Num_Lock+Any { ... }
interpret Shift_Lock+AnyOf(Shift+Lock) { ... }
The xkb_symbols section (see below) allows the keymap author to perform,
among other things, the following things for each key:
- Bind an action, like SetMods or LockGroup, to the key. Actions, like
symbols, are specified for each level of each group in the key
separately.
- Add a virtual modifier to the key's virtual modifier mapping (vmodmap).
- Specify whether the key should repeat or not.
However, doing this for each key (or level) is tedious and inflexible.
Interpret's are a mechanism to apply these settings to a bunch of
keys/levels at once.
Each interpret specifies a condition by which it attaches to certain
levels. The condition consists of two parts:
- A keysym. If the level has a different (or more than one) keysym, the
match fails. Leaving out the keysym is equivalent to using the NoSymbol
keysym, which always matches successfully.
- A modifier predicate. The predicate consists of a matching operation
and a mask of (real) modifiers. The modifiers are matched against the
key's modifier map (modmap). The matching operation can be one of the
following:
* AnyOfOrNone - The modmap must either be empty or include at least
one of the specified modifiers.
* AnyOf - The modmap must include at least one of the specified
modifiers.
* NoneOf - The modmap must not include any of the specified modifiers.
* AllOf - The modmap must include all of the specified modifiers (but
may include others as well).
* Exactly - The modmap must be exactly the same as the specified
modifiers.
Leaving out the predicate is equivalent to using AnyOfOrNone while
specifying all modifiers. Leaving out just the matching condition
is equivalent to using Exactly.
An interpret may also include "useModMapMods = level1;" - see below.
If a level fulfils the conditions of several interpret's, only the
most specific one is used:
- A specific keysym will always match before a generic NoSymbol
condition.
- If the keysyms are the same, the interpret with the more specific
matching operation is used. The above list is sorted from least to
most specific.
- If both the keysyms and the matching operations are the same (but the
modifiers are different), the first interpret is used.
As described above, once an interpret "attaches" to a level, it can bind
an action to that level, add one virtual modifier to the key's vmodmap,
or set the key's repeat setting. You should note the following:
- The key repeat is a property of the entire key; it is not level-specific.
In order to avoid confusion, it is only inspected for the first level of
the first group; the interpret's repeat setting is ignored when applied
to other levels.
- If one of the above fields was set directly for a key in xkb_symbols,
the explicit setting takes precedence over the interpret.
The body of the statement may include statements of the following
forms (all of which are optional):
- useModMapMods statement:
useModMapMods = level1;
When set to 'level1', the interpret will only match levels which are
the first level of the first group of the keys. This can be useful in
conjunction with e.g. a virtualModifier statement.
- action statement:
action = LockMods(modifiers=NumLock);
Bind this action to the matching levels.
- virtual modifier statement:
virtualModifier = NumLock;
Add this virtual modifier to the key's vmodmap. The given virtual
modifier must be declared at the top level of the file with a
virtual_modifiers statement, e.g.:
virtual_modifiers NumLock;
- repeat statement:
repeat = True;
Set whether the key should repeat or not. Must be a boolean value.
LED map statements
------------------
Statements of the form:
indicator "Shift Lock" { ... }
This statement specifies the behavior and binding of the LED (a.k.a
indicator) with the given name ("Shift Lock" above). The name should
have been declared previously in the xkb_keycodes section (see LED
name statement), and given an index there. If it wasn't, it is created
with the next free index.
The body of the statement describes the conditions of the keyboard
state which will cause the LED to be lit. It may include the following
statements:
- modifiers statement:
modifiers = ScrollLock;
If the given modifiers are in the required state (see below), the
LED is lit.
- whichModifierState statment:
whichModState = Latched+Locked;
Can be any combination of:
* base, latched, locked, effective
* any (i.e. all of the above)
* none (i.e. none of the above)
* compat (legacy value, treated as effective)
This will cause the respective portion of the modifer state (see
struct xkb_state) to be matched against the modifiers given in the
"modifiers" statement.
Here's a simple example:
indicator "Num Lock" {
modifiers = NumLock;
whichModState = Locked;
};
Whenever the NumLock modifier is locked, the Num Lock LED will light
up.
- groups statment:
groups = All - group1;
If the given groups are in the required state (see below), the LED
is lit.
- whichGroupState statment:
whichGroupState = Effective;
Can be any combination of:
* base, latched, locked, effective
* any (i.e. all of the above)
* none (i.e. none of the above)
This will cause the respective portion of the group state (see
struct xkb_state) to be matched against the groups given in the
"groups" statement.
Note: the above conditions are disjunctive, i.e. if any of them are
satisfied the LED is lit.
The xkb_symbols section
=======================
This section is the fourth to be processed, after xkb_keycodes,
xkb_types and xkb_compat.
TODO
Virtual modifier statements
===========================
Statements of the form:
virtual_modifiers LControl;
Can appear in the xkb_types, xkb_compat, xkb_symbols sections.
TODO

View File

@ -16,9 +16,11 @@ the library. We will employ a few use-cases to lead the examples:
The snippets are not complete, and some support code is omitted. You
can find complete and more complex examples in the source directory:
1. test/interactive-evdev.c contains an interactive evdev client.
1. tools/interactive-evdev.c contains an interactive evdev client.
2. test/interactive-x11.c contains an interactive X11 client.
2. tools/interactive-x11.c contains an interactive X11 client.
3. tools/interactive-wayland.c contains an interactive Wayland client.
Also, the library contains many more functions for examining and using
the library context, the keymap and the keyboard state. See the
@ -27,22 +29,21 @@ xkbcommon/ for more details.
## Code
Before we can do anything interesting, we need a library context. So
let's create one:
Before we can do anything interesting, we need a library context:
~~~{.c}
#include <xkbcommon/xkbcommon.h>
struct xkb_context ctx;
struct xkb_context *ctx;
ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (!ctx) <error>
~~~
The xkb_context contains the keymap include paths, the log level and
The `xkb_context` contains the keymap include paths, the log level and
functions, and other general customizable administrativia.
Next we need to create a keymap, xkb_keymap. This is an immutable object
Next we need to create a keymap, `xkb_keymap`. This is an immutable object
which contains all of the information about the keys, layouts, etc. There
are different ways to do this.
@ -50,8 +51,8 @@ If we are an evdev client, we have nothing to go by, so we need to ask
the user for his/her keymap preferences (for example, an Icelandic
keyboard with a Dvorak layout). The configuration format is commonly
called RMLVO (Rules+Model+Layout+Variant+Options), the same format used
by the X server. With it, we can fill a struct called xkb_rule_names;
passing NULL chooses the system's default.
by the X server. With it, we can fill a struct called `xkb_rule_names`;
passing `NULL` chooses the system's default.
~~~{.c}
struct xkb_keymap *keymap;
@ -75,6 +76,7 @@ with a keymap. In this case, we can create the keymap object like this:
~~~{.c}
/* From the wl_keyboard::keymap event. */
const char *keymap_string = <...>;
struct xkb_keymap *keymap;
keymap = xkb_keymap_new_from_string(ctx, keymap_string,
XKB_KEYMAP_FORMAT_TEXT_V1,
@ -101,7 +103,7 @@ we will use the core keyboard device:
~~~
Now that we have the keymap, we are ready to handle the keyboard devices.
For each device, we create an xkb_state, which remembers things like which
For each device, we create an `xkb_state`, which remembers things like which
keyboard modifiers and LEDs are active:
~~~{.c}
@ -118,7 +120,7 @@ For X11/XCB clients, this is better:
if (!state) <error>
~~~
When we have an xkb_state for a device, we can start handling key events
When we have an `xkb_state` for a device, we can start handling key events
from it. Given a keycode for a key, we can get its keysym:
~~~{.c}
@ -165,7 +167,7 @@ We can also get a UTF-8 string representation for this key:
xkb_state_key_get_utf8(state, keycode, buffer, size);
~~~
Of course, we also need to keep the xkb_state up-to-date with the
Of course, we also need to keep the `xkb_state` up-to-date with the
keyboard device, if we want to get the correct keysyms in the future.
If we are an evdev client, we must let the library know whether a key
@ -183,7 +185,7 @@ is pressed or released at any given time:
The `changed` return value tells us exactly which parts of the state
have changed.
If is is a key-repeat event, we can ask the keymap what to do with it:
If it is a key-repeat event, we can ask the keymap what to do with it:
~~~{.c}
if (<key repeat> && !xkb_keymap_key_repeats(keymap, keycode))
@ -205,7 +207,7 @@ information usually comes in a form of some "state changed" event):
event->locked_layout);
~~~
Now that we have an always-up-to-date xkb_state, we can examine it.
Now that we have an always-up-to-date `xkb_state`, we can examine it.
For example, we can check whether the Control modifier is active, or
whether the Num Lock LED is active:
@ -218,8 +220,7 @@ whether the Num Lock LED is active:
<The Num Lock LED is active>
~~~
And that's it! When we're finished, we should free the objects we've
created:
And that's it! Eventually, we should free the objects we've created:
~~~{.c}
xkb_state_unref(state);

View File

@ -38,9 +38,12 @@ near the end.
Grammar
-------
(It might be helpful to look at a file like rules/evdev along with
this grammer. Comments, whitespace, etc. are not shown.)
this grammar. Comments, whitespace, etc. are not shown.)
File ::= { "!" (Group | RuleSet) }
```
File ::= { "!" (Include | Group | RuleSet) }
Include ::= "include" <ident>
Group ::= GroupName "=" { GroupElement } "\n"
GroupName ::= "$"<ident>
@ -56,9 +59,27 @@ Kccgst ::= "keycodes" | "symbols" | "types" | "compat" | "geometry"
Rule ::= { MlvoValue } "=" { KccgstValue } "\n"
MlvoValue ::= "*" | GroupName | <ident>
KccgstValue ::= <ident>
```
Notes:
- Include processes the rules in the file path specified in the ident,
in order. %-expansion is performed, as follows:
```
%%:
A literal %.
%H:
The value of the HOME environment variable.
%E:
The extra lookup path for system-wide XKB data (usually /etc/xkb/rules).
%S:
The system-installed rules directory (usually /usr/share/X11/xkb/rules).
```
- The order of values in a Rule must be the same as the Mapping it
follows. The mapping line determines the meaning of the values in
the rules which follow in the RuleSet.
@ -66,6 +87,7 @@ Notes:
- If a Rule is matched, %-expansion is performed on the KccgstValue,
as follows:
```
%m, %l, %v:
The model, layout or variant, if only one was given (e.g.
%l for "us,il" is invalid).
@ -80,6 +102,7 @@ Notes:
%(m), %(l), %(l[1]), %(v), %(v[1]):
As above, but prefixed by '(' and suffixed by ')'.
```
In case the expansion is invalid, as described above, it is
skipped (the rest of the string is still processed); this includes

View File

@ -0,0 +1,232 @@
# User-configuration
This page describes how to add a custom layout or option so that it will be
parsed by libxkbcommon.
**The below requires libxkbcommon as keymap compiler and does not work in X**.
## Data locations
libxkbcommon searches the following paths for XKB configuration files:
- `$XDG_CONFIG_HOME/xkb/`, or `$HOME/.config/xkb/` if the `$XDG_CONFIG_HOME`
environment variable is not defined
- `$HOME/.xkb/`
- `$XKB_CONFIG_EXTRA_PATH` if set, otherswise `<sysconfdir>/xkb` (on most
distributions this is `/etc/xkb`)
- `$XKB_CONFIG_ROOT` if set, otherwise `<datadir>/X11/xkb/` (path defined by the
`xkeyboard-config` package, on most distributions this is
`/usr/share/X11/xkb`)
A keymap created with `xkb_keymap_new_from_names()` will look up those paths in
order until the required data is found.
**Note: Where libxkbcommon runs in a privileged context, only the system
(datadir) path is available.**
Each directory should have one or more of the following subdirectories:
- `compat`
- `geometry` (libxkbcommon ignores this directory)
- `keycodes`
- `rules`
- `symbols`
- `types`
The majority of user-specific configuration involve modifying key symbols and
this is what this document focuses on. For use-cases where a user may need to
add new key types or compat entries the general approach remains the same. A
detailed description for how to add those types or compat entries is out of
scope for this document.
You should never need to add user-specific keycodes. Where a keycode is missing,
the addition should be filed in the upstream xkeyboard-config project.
## RMLVO vs KcCGST
Due to how XKB is configured, there is no such thing as a "layout" in XKB
itself, or, indeed, any of the rules, models, variant, options (RMLVO) decribed
in `struct xkb_rule_names`. RMLVO names are merely lookup keys in the
rules file provided by xkeyboard-config to map to the correct keycode, compat,
geometry (ignored by libxkbcommon), symbols and types (KcCGST). The KcCGST data
is the one used by XKB and libxbkcommon to map keys to actual symbols.
For example, a common RMLVO configuration is layout "us", variant "dvorak" and
option "terminate:ctrl_alt_bksp". Using the default rules file and model
this maps into the following KcCGST components:
```
xkb_keymap {
xkb_keycodes { include "evdev+aliases(qwerty)" };
xkb_types { include "complete" };
xkb_compat { include "complete" };
xkb_symbols { include "pc+us(dvorak)+inet(evdev)+terminate(ctrl_alt_bksp)" };
xkb_geometry { include "pc(pc105)" };
};
```
A detailed explanation of how rules files convert RMLVO to KcCGST is out of
scope for this document. See [the rules file](md_doc_rules-format.html) page
instead.
## Adding a layout
Adding a layout requires that the user adds **symbols** in the correct location.
The default rules files (usually `evdev`) have a catch-all to map a layout, say
"foo", and a variant, say "bar", into the "bar" section in the file
`$xkb_base_dir/symbols/foo`.
This is sufficient to define a new keyboard layout. The example below defines
the keyboard layout "banana" with an optional variant "orange"
```
$ cat $XDG_CONFIG_HOME/xkb/symbols/banana
// Like a US layout but swap the top row so numbers are on Shift
default partial alphanumeric_keys
xkb_symbols "basic" {
include "us(basic)"
name[Group1]= "Banana (US)";
key <AE01> { [ exclam, 1] };
key <AE02> { [ at, 2] };
key <AE03> { [ numbersign, 3] };
key <AE04> { [ dollar, 4] };
key <AE05> { [ percent, 5] };
key <AE06> { [ asciicircum, 6] };
key <AE07> { [ ampersand, 7] };
key <AE08> { [ asterisk, 8] };
key <AE09> { [ parenleft, 9] };
key <AE10> { [ parenright, 0] };
key <AE11> { [ underscore, minus] };
key <AE12> { [ plus, equal] };
};
// Same as banana but map the euro sign to the 5 key
partial alphanumeric_keys
xkb_symbols "orange" {
include "banana(basic)"
name[Group1] = "Banana (Eurosign on 5)";
include "eurosign(5)"
};
```
The `default` section is loaded when no variant is given. The first example
sections uses ``include`` to populate with a symbols list defined elsewhere
(here: section `basic` from the file `symbols/us`, aka. the default US keyboard
layout) and overrides parts of these
symbols. The effect of this section is to swap the numbers and symbols in the
top-most row (compared to the US layout) but otherwise use the US layout.
The "orange" variant uses the "banana" symbols and includes a different section
to define the eurosign. It does not specificially override any symbols.
The exact details of how `xkb_symbols` work is out of scope for this document.
## Adding an option
For technical reasons, options do **not** have a catch-all to map option names
to files and sections and must be specifically mapped by the user. This requires
a custom rules file. As the `evdev` ruleset is hardcoded in many clients, the
custom rules file must usually be named `evdev`.
```
$ cat $XDG_CONFIG_HOME/xkb/rules/evdev
! option = symbols
custom:foo = +custom(bar)
custom:baz = +other(baz)
! include %S/evdev
```
This rules file maps the RMLVO option "custom:foo" to the "bar" section in the
`symbols/custom` file and the "custom:baz" option to the "baz" section in the
`symbols/other` file. Note how the RMLVO option name may be different to the
file or section name.
The `include` statement includes the system-provided `evdev` ruleset. This
allows users to only override those options they need.
The files themselves are similar to the layout examples in the previous section:
```
$ cat $XDG_CONFIG_HOME/xkb/symbols/custom
// map the Tilde key to nothing on the first shift level
partial alphanumeric_keys
xkb_symbols "bar" {
key <TLDE> { [ VoidSymbol ] };
};
$ cat $XDG_CONFIG_HOME/xkb/symbols/other
// map first key in bottom row (Z in the US layout) to k/K
partial alphanumeric_keys
xkb_symbols "baz" {
key <AB01> { [ k, K ] };
};
```
With these in place, a user may select any layout/variant together with
the "custom:foo" and/or "custom:baz" options.
## Discoverable layouts
**The below requires libxkbregistry as XKB lookup tool and does not work where
clients parse the XML file directly**.
The above sections apply only to the data files and require that the user knows
about the existence of the new entries. To make custom entries discoverable by
the configuration tools (e.g. the GNOME Control Center), the new entries must
also be added to the XML file that is parsed by libxkbregistry. In most cases,
this is the `evdev.xml` file in the rules directory. The example below shows the
XML file that would add the custom layout and custom options as outlined above
to the XKB registry:
```
$ cat $XDG_CONFIG_HOME/xkb/rules/evdev.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xkbConfigRegistry SYSTEM "xkb.dtd">
<xkbConfigRegistry version="1.1">
<layoutList>
<layout>
<configItem>
<name>banana</name>
<shortDescription>ban</shortDescription>
<description>Banana</description>
</configItem>
<variantList>
<variant>
<configItem>
<name>orange</name>
<shortDescription>or</shortDescription>
<description>Orange (Banana)</description>
</configItem>
</variant>
</variantList>
</layout>
</layoutList>
<optionList>
<group allowMultipleSelection="true">
<configItem>
<name>custom</name>
<description>Custom options</description>
</configItem>
<option>
<configItem>
<name>custom:foo</name>
<description>Map Tilde to nothing</description>
</configItem>
</option>
<option>
<configItem>
<name>custom:baz</name>
<description>Map Z to K</description>
</configItem>
</option>
</group>
</optionList>
</xkbConfigRegistry>
```
The default behavior of libxkbregistry ensures that the new layout and options
are added to the system-provided layouts and options.
For details on the XML format, see DTD in `<datadir>/X11/xkb/rules/xkb.dtd`
and the system-provided XML files in `<datadir>/X11/xkb/rulies/xkb.dtd`.

View File

@ -0,0 +1,8 @@
"Ctrl"
"Lock"
"Caps"
"Shift"
"Alt"
"Meta"
"None"
"acute"

View File

@ -0,0 +1,46 @@
/*
* A target program for fuzzing the Compose text format.
*
* Currently, just parses an input file, and hopefully doesn't crash or hang.
*/
#include "config.h"
#include <assert.h>
#include "xkbcommon/xkbcommon.h"
#include "xkbcommon/xkbcommon-compose.h"
int
main(int argc, char *argv[])
{
struct xkb_context *ctx;
FILE *file;
struct xkb_compose_table *table;
if (argc != 2) {
fprintf(stderr, "usage: %s <file>\n", argv[0]);
return 1;
}
ctx = xkb_context_new(XKB_CONTEXT_NO_DEFAULT_INCLUDES | XKB_CONTEXT_NO_ENVIRONMENT_NAMES);
assert(ctx);
#ifdef __AFL_HAVE_MANUAL_CONTROL
__AFL_INIT();
while (__AFL_LOOP(1000))
#endif
{
file = fopen(argv[1], "rb");
assert(file);
table = xkb_compose_table_new_from_file(ctx, file,
"en_US.UTF-8",
XKB_COMPOSE_FORMAT_TEXT_V1,
XKB_COMPOSE_COMPILE_NO_FLAGS);
xkb_compose_table_unref(table);
fclose(file);
}
puts(table ? "OK" : "FAIL");
xkb_context_unref(ctx);
}

View File

@ -0,0 +1,2 @@
<dead_tilde> <space> : "~" asciitilde # X
Meta <Multi_key> !Alt ~Shift <apostrophe> <apostrophe> : "\"\'\x43\123abc" acute # Y

View File

@ -0,0 +1,17 @@
#!/bin/sh
set -e
case "$1" in
keymap|compose)
;;
*)
echo "usage: $0 keymap|compose" 1>&2
exit 1
;;
esac
export CC=afl-clang-fast
export AFL_HARDEN=1
test -d fuzz/build || meson setup -Db_lto=true fuzz/build
ninja -C fuzz/build
afl-fuzz -i fuzz/$1/testcases -x fuzz/$1/dict -o fuzz/$1/findings -t 200 -m 10 -- ./fuzz/build/fuzz-$1 @@

View File

@ -0,0 +1,120 @@
"Control"
"Group1"
"Group5"
"Lock"
"Mod1"
"Mod9"
"Shift"
"U1"
"0x1"
"Up"
"accel"
"action"
"actions"
"affect"
"alias"
"all"
"allowexplicit"
"allownone"
"alphanumeric_keys"
"alternate"
"alternate_group"
"any"
"augment"
"both"
"button"
"clearLocks"
"clearmods"
"controls"
"count"
"ctrls"
"data"
"default"
"dev"
"device"
"dfltbtn"
"driveskbd"
"false"
"foo"
"function_keys"
"genKeyEvent"
"group"
"groupname"
"groups"
"groupsclamp"
"groupsredirect"
"groupswrap"
"hidden"
"include"
"increment"
"index"
"indicator"
"indicatordriveskbd"
"interpret"
"kc"
"key"
"keycode"
"keypad_keys"
"keys"
"latchToLock"
"leddriveskbd"
"levelname"
"lock"
"locking"
"logo"
"map"
"mod_map"
"modifier_keys"
"modifier_map"
"modifiers"
"modmap"
"modmapmods"
"mods"
"name"
"neither"
"no"
"none"
"nosymbol"
"off"
"on"
"outline"
"overlay"
"override"
"partial"
"preserve"
"radiogroup"
"repeat"
"replace"
"report"
"row"
"same"
"sameServer"
"screen"
"section"
"shape"
"solid"
"symbols"
"text"
"true"
"type"
"unlock"
"usemodmap"
"value"
"virtual"
"virtual_modifiers"
"virtualmod"
"vmods"
"voidsymbol"
"whichgroupstate"
"whichmodstate"
"x"
"xkb_compat"
"xkb_geometry"
"xkb_keycodes"
"xkb_keymap"
"xkb_layout"
"xkb_semantics"
"xkb_symbols"
"xkb_types"
"y"
"yes"

View File

@ -0,0 +1,44 @@
/*
* A target program for fuzzing the XKB keymap text format.
*
* Currently, just parses an input file, and hopefully doesn't crash or hang.
*/
#include "config.h"
#include <assert.h>
#include "xkbcommon/xkbcommon.h"
int
main(int argc, char *argv[])
{
struct xkb_context *ctx;
FILE *file;
struct xkb_keymap *keymap;
if (argc != 2) {
fprintf(stderr, "usage: %s <file>\n", argv[0]);
return 1;
}
ctx = xkb_context_new(XKB_CONTEXT_NO_DEFAULT_INCLUDES | XKB_CONTEXT_NO_ENVIRONMENT_NAMES);
assert(ctx);
#ifdef __AFL_HAVE_MANUAL_CONTROL
__AFL_INIT();
while (__AFL_LOOP(1000))
#endif
{
file = fopen(argv[1], "rb");
assert(file);
keymap = xkb_keymap_new_from_file(ctx, file,
XKB_KEYMAP_FORMAT_TEXT_V1,
XKB_KEYMAP_COMPILE_NO_FLAGS);
xkb_keymap_unref(keymap);
fclose(file);
}
puts(keymap ? "OK" : "FAIL");
xkb_context_unref(ctx);
}

View File

@ -0,0 +1,59 @@
xkb_keymap{
xkb_keycodes"0"{
minimum=0;
maximum=500;
<a>=0;
indicator 1="X";
alias<X>=<Y>;
};
xkb_types"X"{
virtual_modifiers NumLock;
type"X"{
modifiers=Shift;
map[Shift]=Level2;
level_name[Level1]="X";
preserve[Shift]=Shift;
};
};
partial xkb_compat{
virtual_modifiers Alt;
interpret.useModMapMods=AnyLevel;
interpret.repeat=False;
interpret.locking=False;
interpret ISO_Level2_Latch+Exactly(Shift){
repeat=True;
virtualModifier=NumLock;
useModMapMods=level1;
action=LatchMods(modifiers=Shift,clearLocks,latchToLock);
action=MovePtr(x=+0,y=-0);
action=SwitchScreen(screen=00,!same);
action=Private(type=0x80,data[0]=0x00);
};
indicator"X"{whichModState=locked;modifiers=Lock;};
};
xkb_symbols{
name[group1]="X";
key<Y>{type[group2]="X",symbols[Group1]=[0,exclam],symbols[Group2]=[0xff,U00],symbols[Group3]=[z]};
modifier_map Control{<a>};
};
default xkb_geometry"X"{
description="X";
width=470;
shape.cornerRadius=1;
shape"NORM"{cornerRadius=0,{[0.0,0]},{[0,0],[0,0.0]}};
solid"X"{shape="X";top=00;left=00;color="X";};
indicator.onColor="X";
indicator.top=00.0;
indicator.shape="X";
indicator"X"{left=0;};
text.top=00;
text.color="X";
text"X"{left=0;text="X";};
section.left=00;
row.left=0;
key.shape="X";
key.gap=1;
section"X"{top=22;row{top=1;keys{{<X>,color="X"},{<X>,00.0},<X>,<X>,<X>};};};
alias<AC00>=<CAPS>;
};
};

View File

@ -55,13 +55,13 @@ extern "C" {
* Here are some example sequences, in the libX11 Compose file format:
*
* <dead_acute> <a> : "á" aacute # LATIN SMALL LETTER A WITH ACUTE
* <Multi_key> <A> <T> : "@" at # COMMERCIAL AT
* <Multi_key> <A> <T> : "@" at # COMMERCIAL AT
*
* When the user presses a key which produces the \<dead_acute> keysym,
* When the user presses a key which produces the `<dead_acute>` keysym,
* nothing initially happens (thus the key is dubbed a "dead-key"). But
* when the user enters <a>, "á" is "composed", in place of "a". If
* when the user enters `<a>`, "á" is "composed", in place of "a". If
* instead the user had entered a keysym which does not follow
* \<dead_acute\> in any compose sequence, the sequence is said to be
* `<dead_acute>` in any compose sequence, the sequence is said to be
* "cancelled".
*
* Compose files define many such sequences. For a description of the
@ -73,7 +73,7 @@ extern "C" {
* result string (using xkb_keysym_to_utf8()).
*
* This library provides low-level support for Compose file parsing and
* processing. Higher-level APIs (such as libX11's Xutf8LookupString(3))
* processing. Higher-level APIs (such as libX11's `Xutf8LookupString`(3))
* may be built upon it, or it can be used directly.
*
* @endparblock
@ -90,7 +90,7 @@ extern "C" {
* 2. An equal sequence overrides an existing one.
* 3. A shorter sequence does not override a longer one.
*
* Sequences of length 1 are allowed, although they are not common.
* Sequences of length 1 are allowed.
*
* @endparblock
*/
@ -100,15 +100,15 @@ extern "C" {
* @parblock
*
* What should happen when a sequence is cancelled? For example, consider
* there are only the above sequences, and the input kesysms are
* \<dead_acute\> \<b\>. There are a few approaches:
* there are only the above sequences, and the input keysyms are
* `<dead_acute> <b>`. There are a few approaches:
*
* 1. Swallow the cancelling keysym; that is, no keysym is produced.
* This is the approach taken by libX11.
* 2. Let the cancelling keysym through; that is, \<b\> is produced.
* 3. Replay the entire sequence; that is, \<dead_acute\> \<b\> is produced.
* 2. Let the cancelling keysym through; that is, `<b>` is produced.
* 3. Replay the entire sequence; that is, `<dead_acute> <b>` is produced.
* This is the approach taken by Microsoft Windows (approximately;
* instead of \<dead_acute\>, the underlying key is used. This is
* instead of `<dead_acute>`, the underlying key is used. This is
* difficult to simulate with XKB keymaps).
*
* You can program whichever approach best fits users' expectations.
@ -158,9 +158,10 @@ enum xkb_compose_format {
* - Compose files are written for a locale, and the locale is used when
* searching for the appropriate file to use.
* - Compose files may reference the locale internally, with directives
* such as %L.
* such as \%L.
*
* As such, functions like xkb_compose_table_new_from_locale() require
* a @p locale parameter. This will usually be the current locale (see
* a `locale` parameter. This will usually be the current locale (see
* locale(7) for more details). You may also want to allow the user to
* explicitly configure it, so he can use the Compose file of a given
* locale, but not use that locale for other things.
@ -172,19 +173,20 @@ enum xkb_compose_format {
* @endcode
*
* This will only give useful results if the program had previously set
* the current locale using setlocale(3), with LC_CTYPE or LC_ALL and a
* non-NULL argument.
* the current locale using setlocale(3), with `LC_CTYPE` or `LC_ALL`
* and a non-NULL argument.
*
* If you prefer not to use the locale system of the C runtime library,
* you may nevertheless obtain the user's locale directly using
* environment variables, as described in locale(7). For example,
* @code
* const char *locale;
* locale = getenv("LC_ALL");
* if (!locale)
* if (!locale || !*locale)
* locale = getenv("LC_CTYPE");
* if (!locale)
* if (!locale || !*locale)
* locale = getenv("LANG");
* if (!locale)
* if (!locale || !*locale)
* locale = "C";
* @endcode
*
@ -200,12 +202,28 @@ enum xkb_compose_format {
* The locale is used for searching the file-system for an appropriate
* Compose file. The search order is described in Compose(5). It is
* affected by the following environment variables:
* XCOMPOSEFILE, HOME, XLOCALEDIR.
*
* 1. `XCOMPOSEFILE` - see Compose(5).
* 2. `XDG_CONFIG_HOME` - before `$HOME/.XCompose` is checked,
* `$XDG_CONFIG_HOME/XCompose` is checked (with a fall back to
* `$HOME/.config/XCompose` if `XDG_CONFIG_HOME` is not defined).
* This is a libxkbcommon extension to the search procedure in
* Compose(5) (since libxkbcommon 1.0.0). Note that other
* implementations, such as libX11, might not find a Compose file in
* this path.
* 3. `HOME` - see Compose(5).
* 4. `XLOCALEDIR` - if set, used as the base directory for the system's
* X locale files, e.g. `/usr/share/X11/locale`, instead of the
* preconfigured directory.
*
* @param context
* The library context in which to create the compose table.
* @param locale
* The current locale. See @ref compose-locale.
* \n
* The value is copied, so it is safe to pass the result of getenv(3)
* (or similar) without fear of it being invalidated by a subsequent
* setenv(3) (or similar).
* @param flags
* Optional flags for the compose table, or 0.
*
@ -362,15 +380,15 @@ enum xkb_compose_feed_result {
* Feed one keysym to the Compose sequence state machine.
*
* This function can advance into a compose sequence, cancel a sequence,
* start a new sequence, or do nothing in particular . The resulting
* start a new sequence, or do nothing in particular. The resulting
* status may be observed with xkb_compose_state_get_status().
*
* Some keysyms, such as keysysm for modifier keys, are ignored - they
* Some keysyms, such as keysyms for modifier keys, are ignored - they
* have no effect on the status or otherwise.
*
* The following is a description of the possible status transitions, in
* the format CURRENT STATUS => NEXT STATUS, given a non-ignored input
* keysym @p keysym:
* keysym `keysym`:
*
@verbatim
NOTHING or CANCELLED or COMPOSED =>
@ -389,8 +407,8 @@ enum xkb_compose_feed_result {
*
* The current Compose formats do not support multiple-keysyms.
* Therefore, if you are using a function such as xkb_state_key_get_syms()
* and it returns more than one keysym, consider feeding
* @p XKB_KEY_NoSymbol instead.
* and it returns more than one keysym, consider feeding XKB_KEY_NoSymbol
* instead.
*
* @param state
* The compose state object.
@ -446,12 +464,11 @@ xkb_compose_state_get_status(struct xkb_compose_state *state);
* @returns
* The number of bytes required for the string, excluding the NUL byte.
* If the sequence is not complete, or does not have a viable result
* string, returns 0, and sets @p buffer to the empty string (if
* possible).
* string, returns 0, and sets `buffer` to the empty string (if possible).
* @returns
* You may check if truncation has occurred by comparing the return value
* with the size of @p buffer, similarly to the snprintf(3) function.
* You may safely pass NULL and 0 to @p buffer and @p size to find the
* with the size of `buffer`, similarly to the `snprintf`(3) function.
* You may safely pass NULL and 0 to `buffer` and `size` to find the
* required size (without the NUL-byte).
*
* @memberof xkb_compose_state

File diff suppressed because it is too large Load Diff

View File

@ -54,7 +54,7 @@ extern "C" {
* can be used as a replacement for Xlib's keyboard handling.
*
* Following is an example workflow using xkbcommon-x11. A complete
* example may be found in the test/interactive-x11.c file in the
* example may be found in the tools/interactive-x11.c file in the
* xkbcommon source repository. On startup:
*
* 1. Connect to the X server using xcb_connect().
@ -64,10 +64,9 @@ extern "C" {
*
* The XKB extension supports using separate keymaps and states for
* different keyboard devices. The devices are identified by an integer
* device ID and are managed by another X11 extension, XInput (or its
* successor, XInput2). The original X11 protocol only had one keyboard
* device, called the "core keyboard", which is still supported as a
* "virtual device".
* device ID and are managed by another X11 extension, XInput. The
* original X11 protocol only had one keyboard device, called the "core
* keyboard", which is still supported as a "virtual device".
*
* 3. We will use the core keyboard as an example. To get its device ID,
* use either the xcb_xkb_get_device_info() request directly, or the
@ -79,7 +78,7 @@ extern "C" {
*
* @note At this point, you may consider setting various XKB controls and
* XKB per-client flags. For example, enabling detectable autorepeat: \n
* http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Detectable_Autorepeat
* https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Detectable_Autorepeat
*
* Next, you need to react to state changes (e.g. a modifier was pressed,
* the layout was changed) and to keymap changes (e.g. a tool like xkbcomp,
@ -96,7 +95,7 @@ extern "C" {
* @note It is also possible to use the KeyPress/KeyRelease @p state
* field to find the effective modifier and layout state, instead of
* using XkbStateNotify: \n
* http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Computing_A_State_Field_from_an_XKB_State
* https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Computing_A_State_Field_from_an_XKB_State
* \n However, XkbStateNotify is more accurate.
*
* @note There is no need to call xkb_state_update_key(); the state is
@ -197,8 +196,9 @@ xkb_x11_get_core_keyboard_device_id(xcb_connection_t *connection);
* @param connection
* An XCB connection to the X server.
* @param device_id
* An XInput 1 device ID (in the range 0-255) with input class KEY.
* Passing values outside of this range is an error.
* An XInput device ID (in the range 0-127) with input class KEY.
* Passing values outside of this range is an error (the XKB protocol
* predates the XInput2 protocol, which first allowed IDs > 127).
* @param flags
* Optional flags for the keymap, or 0.
*

View File

@ -152,6 +152,10 @@ struct xkb_state;
* underlying input system. For example, with an X11-compatible keymap
* and Linux evdev scan codes (see linux/input.h), a fixed offset is used:
*
* The keymap defines a canonical name for each key, plus possible aliases.
* Historically, the XKB protocol restricts these names to at most 4 (ASCII)
* characters, but this library does not share this limit.
*
* @code
* xkb_keycode_t keycode_A = KEY_A + 8;
* @endcode
@ -173,7 +177,7 @@ typedef uint32_t xkb_keycode_t;
* somewhat more general, in that they can also represent some "function",
* such as "Left" or "Right" for the arrow keys. For more information,
* see:
* http://www.x.org/releases/X11R7.7/doc/xproto/x11protocol.html#keysym_encoding
* https://www.x.org/releases/current/doc/xproto/x11protocol.html#keysym_encoding
*
* Specifically named keysyms can be found in the
* xkbcommon/xkbcommon-keysyms.h header file. Their name does not include
@ -204,6 +208,15 @@ typedef uint32_t xkb_keysym_t;
* Therefore, it is not safe to use the name as a unique identifier for a
* layout. Layout names are case-sensitive.
*
* Layout names are specified in the layout's definition, for example
* "English (US)". These are different from the (conventionally) short names
* which are used to locate the layout, for example "us" or "us(intl)". These
* names are not present in a compiled keymap.
*
* If the user selects layouts from a list generated from the XKB registry
* (using libxkbregistry or directly), and this metadata is needed later on, it
* is recommended to store it along with the keymap.
*
* Layouts are also called "groups" by XKB.
*
* @sa xkb_keymap_num_layouts() xkb_keymap_num_layouts_for_key()
@ -342,6 +355,9 @@ struct xkb_rule_names {
* A comma separated list of variants, one per layout, which may
* modify or augment the respective layout in various ways.
*
* Generally, should either be empty or have the same number of values
* as the number of layouts. You may use empty values as in "intl,,neo".
*
* If NULL or the empty string "", and a default value is also used
* for the layout, a default value is used. Otherwise no variant is
* used.
@ -381,7 +397,7 @@ struct xkb_rule_names {
* Similarly, the UTF-8/UTF-32 string produced is capitalized.
*
* This is described in:
* http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier
* https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier
*
* - Control transformation. If the Control modifier is active and
* was not consumed by the translation process, the string produced
@ -389,7 +405,7 @@ struct xkb_rule_names {
* applicable). Keysyms are not affected.
*
* This is described in:
* http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier
* https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier
*
* Each relevant function discusses which transformations it performs.
*
@ -445,6 +461,9 @@ enum xkb_keysym_flags {
* fails, only then to try with this flag, while possibly warning the user
* he had misspelled the name, and might get wrong results.
*
* Case folding is done according to the C locale; the current locale is not
* consulted.
*
* @returns The keysym. If the name is invalid, returns XKB_KEY_NoSymbol.
*
* @sa xkb_keysym_t
@ -486,6 +505,49 @@ xkb_keysym_to_utf8(xkb_keysym_t keysym, char *buffer, size_t size);
uint32_t
xkb_keysym_to_utf32(xkb_keysym_t keysym);
/**
* Get the keysym corresponding to a Unicode/UTF-32 codepoint.
*
* @returns The keysym corresponding to the specified Unicode
* codepoint, or XKB_KEY_NoSymbol if there is none.
*
* This function is the inverse of @ref xkb_keysym_to_utf32. In cases
* where a single codepoint corresponds to multiple keysyms, returns
* the keysym with the lowest value.
*
* Unicode codepoints which do not have a special (legacy) keysym
* encoding use a direct encoding scheme. These keysyms don't usually
* have an associated keysym constant (XKB_KEY_*).
*
* For noncharacter Unicode codepoints and codepoints outside of the
* defined Unicode planes this function returns XKB_KEY_NoSymbol.
*
* @sa xkb_keysym_to_utf32()
* @since 1.0.0
*/
xkb_keysym_t
xkb_utf32_to_keysym(uint32_t ucs);
/**
* Convert a keysym to its uppercase form.
*
* If there is no such form, the keysym is returned unchanged.
*
* The conversion rules may be incomplete; prefer to work with the Unicode
* representation instead, when possible.
*/
xkb_keysym_t
xkb_keysym_to_upper(xkb_keysym_t ks);
/**
* Convert a keysym to its lowercase form.
*
* The conversion rules may be incomplete; prefer to work with the Unicode
* representation instead, when possible.
*/
xkb_keysym_t
xkb_keysym_to_lower(xkb_keysym_t ks);
/** @} */
/**
@ -498,6 +560,18 @@ xkb_keysym_to_utf32(xkb_keysym_t keysym);
* @{
*/
/**
* @page envvars Environment Variables
*
* The user may set some environment variables which affect the library:
*
* - `XKB_CONFIG_ROOT`, `XKB_CONFIG_EXTRA_PATH`, `XDG_CONFIG_DIR`, `HOME` - see @ref include-path.
* - `XKB_LOG_LEVEL` - see xkb_context_set_log_level().
* - `XKB_LOG_VERBOSITY` - see xkb_context_set_log_verbosity().
* - `XKB_DEFAULT_RULES`, `XKB_DEFAULT_MODEL`, `XKB_DEFAULT_LAYOUT`,
* `XKB_DEFAULT_VARIANT`, `XKB_DEFAULT_OPTIONS` - see xkb_rule_names.
*/
/** Flags for context creation. */
enum xkb_context_flags {
/** Do not apply any context flags. */
@ -518,10 +592,6 @@ enum xkb_context_flags {
*
* @returns A new context, or NULL on failure.
*
* The user may set some environment variables to affect default values in
* the context. See e.g. xkb_context_set_log_level() and
* xkb_context_set_log_verbosity().
*
* @memberof xkb_context
*/
struct xkb_context *
@ -580,7 +650,17 @@ xkb_context_get_user_data(struct xkb_context *context);
*
* The include paths are the file-system paths that are searched when an
* include statement is encountered during keymap compilation.
* In most cases, the default include paths are sufficient.
*
* The default include paths are, in that lookup order:
* - The path `$XDG_CONFIG_HOME/xkb`, with the usual `XDG_CONFIG_HOME`
* fallback to `$HOME/.config/` if unset.
* - The path `$HOME/.xkb`, where $HOME is the value of the environment
* variable `HOME`.
* - The `XKB_CONFIG_EXTRA_PATH` environment variable, if defined, otherwise the
* system configuration directory, defined at library configuration time
* (usually `/etc/xkb`).
* - The `XKB_CONFIG_ROOT` environment variable, if defined, otherwise
* the system XKB root, defined at library configuration time.
*
* @{
*/
@ -875,7 +955,7 @@ xkb_keymap_unref(struct xkb_keymap *keymap);
*
* @returns The keymap as a NUL-terminated string, or NULL if unsuccessful.
*
* The returned string may be fed back into xkb_map_new_from_string() to get
* The returned string may be fed back into xkb_keymap_new_from_string() to get
* the exact same keymap (possibly in another process, etc.).
*
* The returned string is dynamically allocated and should be freed by the
@ -940,6 +1020,37 @@ void
xkb_keymap_key_for_each(struct xkb_keymap *keymap, xkb_keymap_key_iter_t iter,
void *data);
/**
* Find the name of the key with the given keycode.
*
* This function always returns the canonical name of the key (see
* description in xkb_keycode_t).
*
* @returns The key name. If no key with this keycode exists,
* returns NULL.
*
* @sa xkb_keycode_t
* @memberof xkb_keymap
* @since 0.6.0
*/
const char *
xkb_keymap_key_get_name(struct xkb_keymap *keymap, xkb_keycode_t key);
/**
* Find the keycode of the key with the given name.
*
* The name can be either a canonical name or an alias.
*
* @returns The keycode. If no key with this name exists,
* returns XKB_KEYCODE_INVALID.
*
* @sa xkb_keycode_t
* @memberof xkb_keymap
* @since 0.6.0
*/
xkb_keycode_t
xkb_keymap_key_by_name(struct xkb_keymap *keymap, const char *name);
/**
* Get the number of modifiers in the keymap.
*
@ -988,6 +1099,7 @@ xkb_keymap_num_layouts(struct xkb_keymap *keymap);
* a name, returns NULL.
*
* @sa xkb_layout_index_t
* For notes on layout names.
* @memberof xkb_keymap
*/
const char *
@ -1000,6 +1112,8 @@ xkb_keymap_layout_get_name(struct xkb_keymap *keymap, xkb_layout_index_t idx);
* XKB_LAYOUT_INVALID. If more than one layout in the keymap has this name,
* returns the lowest index among them.
*
* @sa xkb_layout_index_t
* For notes on layout names.
* @memberof xkb_keymap
*/
xkb_layout_index_t
@ -1067,6 +1181,49 @@ xkb_level_index_t
xkb_keymap_num_levels_for_key(struct xkb_keymap *keymap, xkb_keycode_t key,
xkb_layout_index_t layout);
/**
* Retrieves every possible modifier mask that produces the specified
* shift level for a specific key and layout.
*
* This API is useful for inverse key transformation; i.e. finding out
* which modifiers need to be active in order to be able to type the
* keysym(s) corresponding to the specific key code, layout and level.
*
* @warning It returns only up to masks_size modifier masks. If the
* buffer passed is too small, some of the possible modifier combinations
* will not be returned.
*
* @param[in] keymap The keymap.
* @param[in] key The keycode of the key.
* @param[in] layout The layout for which to get modifiers.
* @param[in] level The shift level in the layout for which to get the
* modifiers. This should be smaller than:
* @code xkb_keymap_num_levels_for_key(keymap, key) @endcode
* @param[out] masks_out A buffer in which the requested masks should be
* stored.
* @param[out] masks_size The size of the buffer pointed to by masks_out.
*
* If @c layout is out of range for this key (that is, larger or equal to
* the value returned by xkb_keymap_num_layouts_for_key()), it is brought
* back into range in a manner consistent with xkb_state_key_get_layout().
*
* @returns The number of modifier masks stored in the masks_out array.
* If the key is not in the keymap or if the specified shift level cannot
* be reached it returns 0 and does not modify the masks_out buffer.
*
* @sa xkb_level_index_t
* @sa xkb_mod_mask_t
* @memberof xkb_keymap
* @since 1.0.0
*/
size_t
xkb_keymap_key_get_mods_for_level(struct xkb_keymap *keymap,
xkb_keycode_t key,
xkb_layout_index_t layout,
xkb_level_index_t level,
xkb_mod_mask_t *masks_out,
size_t masks_size);
/**
* Get the keysyms obtained from pressing a key in a given layout and
* shift level.
@ -1079,7 +1236,7 @@ xkb_keymap_num_levels_for_key(struct xkb_keymap *keymap, xkb_keycode_t key,
* @param[in] key The keycode of the key.
* @param[in] layout The layout for which to get the keysyms.
* @param[in] level The shift level in the layout for which to get the
* keysyms. This must be smaller than:
* keysyms. This should be smaller than:
* @code xkb_keymap_num_levels_for_key(keymap, key) @endcode
* @param[out] syms_out An immutable array of keysyms corresponding to the
* key in the given layout and shift level.
@ -1200,7 +1357,7 @@ enum xkb_state_component {
XKB_STATE_MODS_LOCKED = (1 << 2),
/** Effective modifiers, i.e. currently active and affect key
* processing (derived from the other state components).
* Use this unless you explictly care how the state came about. */
* Use this unless you explicitly care how the state came about. */
XKB_STATE_MODS_EFFECTIVE = (1 << 3),
/** Depressed layout, i.e. a key is physically holding it. */
XKB_STATE_LAYOUT_DEPRESSED = (1 << 4),
@ -1212,7 +1369,7 @@ enum xkb_state_component {
XKB_STATE_LAYOUT_LOCKED = (1 << 6),
/** Effective layout, i.e. currently active and affects key processing
* (derived from the other state components).
* Use this unless you explictly care how the state came about. */
* Use this unless you explicitly care how the state came about. */
XKB_STATE_LAYOUT_EFFECTIVE = (1 << 7),
/** LEDs (derived from the other state components). */
XKB_STATE_LEDS = (1 << 8)
@ -1223,10 +1380,10 @@ enum xkb_state_component {
* released.
*
* This entry point is intended for programs which track the keyboard state
* explictly (like an evdev client). If the state is serialized to you by
* explicitly (like an evdev client). If the state is serialized to you by
* a master process (like a Wayland compositor) using functions like
* xkb_state_serialize_mods(), you should use xkb_state_update_mask() instead.
* The two functins should not generally be used together.
* The two functions should not generally be used together.
*
* A series of calls to this function should be consistent; that is, a call
* with XKB_KEY_DOWN for a key should be matched by an XKB_KEY_UP; if a key
@ -1601,7 +1758,7 @@ xkb_state_mod_indices_are_active(struct xkb_state *state,
* Effectively, this means that consumed modifiers (Shift in this example)
* are masked out as well, before doing the comparison.
*
* In summary, this is how the matching would be performed:
* In summary, this is approximately how the matching would be performed:
* @code
* (keysym == shortcut_keysym) &&
* ((state_mods & ~consumed_mods & significant_mods) == shortcut_mods)
@ -1617,16 +1774,100 @@ xkb_state_mod_indices_are_active(struct xkb_state *state,
* @endparblock
*/
/**
* Consumed modifiers mode.
*
* There are several possible methods for deciding which modifiers are
* consumed and which are not, each applicable for different systems or
* situations. The mode selects the method to use.
*
* Keep in mind that in all methods, the keymap may decide to "preserve"
* a modifier, meaning it is not reported as consumed even if it would
* have otherwise.
*/
enum xkb_consumed_mode {
/**
* This is the mode defined in the XKB specification and used by libX11.
*
* A modifier is consumed if and only if it *may affect* key translation.
*
* For example, if `Control+Alt+<Backspace>` produces some assigned keysym,
* then when pressing just `<Backspace>`, `Control` and `Alt` are consumed,
* even though they are not active, since if they *were* active they would
* have affected key translation.
*/
XKB_CONSUMED_MODE_XKB,
/**
* This is the mode used by the GTK+ toolkit.
*
* The mode consists of the following two independent heuristics:
*
* - The currently active set of modifiers, excluding modifiers which do
* not affect the key (as described for @ref XKB_CONSUMED_MODE_XKB), are
* considered consumed, if the keysyms produced when all of them are
* active are different from the keysyms produced when no modifiers are
* active.
*
* - A single modifier is considered consumed if the keysyms produced for
* the key when it is the only active modifier are different from the
* keysyms produced when no modifiers are active.
*/
XKB_CONSUMED_MODE_GTK
};
/**
* Get the mask of modifiers consumed by translating a given key.
*
* @param state The keyboard state.
* @param key The keycode of the key.
* @param mode The consumed modifiers mode to use; see enum description.
*
* @returns a mask of the consumed modifiers.
*
* @memberof xkb_state
* @since 0.7.0
*/
xkb_mod_mask_t
xkb_state_key_get_consumed_mods2(struct xkb_state *state, xkb_keycode_t key,
enum xkb_consumed_mode mode);
/**
* Same as xkb_state_key_get_consumed_mods2() with mode XKB_CONSUMED_MODE_XKB.
*
* @memberof xkb_state
* @since 0.4.1
*/
xkb_mod_mask_t
xkb_state_key_get_consumed_mods(struct xkb_state *state, xkb_keycode_t key);
/**
* Test whether a modifier is consumed by keyboard state translation for
* a key.
*
* @param state The keyboard state.
* @param key The keycode of the key.
* @param idx The index of the modifier to check.
* @param mode The consumed modifiers mode to use; see enum description.
*
* @returns 1 if the modifier is consumed, 0 if it is not. If the modifier
* index is not valid in the keymap, returns -1.
*
* @sa xkb_state_mod_mask_remove_consumed()
* @sa xkb_state_key_get_consumed_mods()
* @memberof xkb_state
* @since 0.7.0
*/
int
xkb_state_mod_index_is_consumed2(struct xkb_state *state,
xkb_keycode_t key,
xkb_mod_index_t idx,
enum xkb_consumed_mode mode);
/**
* Same as xkb_state_mod_index_is_consumed2() with mode XKB_CONSUMED_MOD_XKB.
*
* @memberof xkb_state
* @since 0.4.1
*/
int
xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t key,
@ -1635,6 +1876,8 @@ xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t key,
/**
* Remove consumed modifiers from a modifier mask for a key.
*
* @deprecated Use xkb_state_key_get_consumed_mods2() instead.
*
* Takes the given modifier mask, and removes all modifiers which are
* consumed for that particular key (as in xkb_state_mod_index_is_consumed()).
*
@ -1645,18 +1888,6 @@ xkb_mod_mask_t
xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t key,
xkb_mod_mask_t mask);
/**
* Get the mask of modifiers consumed by translating a given key.
*
* @returns a mask of the consumed modifiers.
*
* @sa xkb_state_mod_index_is_consumed()
* @memberof xkb_state
* @since 0.4.1
*/
xkb_mod_mask_t
xkb_state_key_get_consumed_mods(struct xkb_state *state, xkb_keycode_t key);
/**
* Test whether a layout is active in a given keyboard state by name.
*

View File

@ -0,0 +1,782 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef _XKBREGISTRY_H_
#define _XKBREGISTRY_H_
#include <stdarg.h>
#include <stdbool.h>
/**
* @file
* @brief Query for available RMLVO
*
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup registry Query for available RMLVO
*
* The libxkbregistry API to query for available rules, models, layouts,
* variants and options (RMLVO). libxkbregistry is a separate library to
* libxkbcommon.
*
* This library is the replacement for clients currently parsing evdev.xml
* directly. The library is intended to provide easy access to the set of
* **possible** MLVO configurations for a given ruleset. It is not a library to
* apply these configurations, merely to enumerate them. The intended users of
* this library are the configuration UIs that allow a user to select their
* keyboard layout of choice.
*
* @{
*/
/**
* @struct rxkb_context
*
* Opaque top level library context object.
*
* The context contains general library state, like include paths and parsed
* data. Objects are created in a specific context, and multiple contexts
* may coexist simultaneously. Objects from different contexts are
* completely separated and do not share any memory or state.
*/
struct rxkb_context;
/**
* @struct rxkb_model
*
* Opaque struct representing an XKB model.
*/
struct rxkb_model;
/**
* @struct rxkb_layout
*
* Opaque struct representing an XKB layout, including an optional variant.
* Where the variant is NULL, the layout is the base layout.
*
* For example, "us" is the base layout, "us(intl)" is the "intl" variant of the
* layout "us".
*/
struct rxkb_layout;
/**
* @struct rxkb_option_group
*
* Opaque struct representing an option group. Option groups divide the
* individual options into logical groups. Their main purpose is to indicate
* whether some options are mutually exclusive or not.
*/
struct rxkb_option_group;
/**
* @struct rxkb_option
*
* Opaque struct representing an XKB option. Options are grouped inside an @ref
* rxkb_option_group.
*/
struct rxkb_option;
/**
*
* @struct rxkb_iso639_code
*
* Opaque struct representing an ISO 639-3 code (e.g. "eng", "fra"). There
* is no guarantee that two identical ISO codes share the same struct. You
* must not rely on the pointer value of this struct.
*
* See https://iso639-3.sil.org/code_tables/639/data for a list of codes.
*/
struct rxkb_iso639_code;
/**
*
* @struct rxkb_iso3166_code
*
* Opaque struct representing an ISO 3166 Alpha 2 code (e.g. "US", "FR").
* There is no guarantee that two identical ISO codes share the same struct.
* You must not rely on the pointer value of this struct.
*
* See https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes for a list
* of codes.
*/
struct rxkb_iso3166_code;
/**
* Describes the popularity of an item. Historically, some highly specialized or
* experimental definitions are excluded from the default list and shipped in
* separate files. If these extra definitions are loaded (see @ref
* RXKB_CONTEXT_LOAD_EXOTIC_RULES), the popularity of the item is set
* accordingly.
*
* If the exotic items are not loaded, all items will have the standard
* popularity.
*/
enum rxkb_popularity {
RXKB_POPULARITY_STANDARD = 1,
RXKB_POPULARITY_EXOTIC,
};
/**
* Flags for context creation.
*/
enum rxkb_context_flags {
RXKB_CONTEXT_NO_FLAGS = 0,
/**
* Skip the default include paths. This requires the caller to call
* rxkb_context_include_path_append() or
* rxkb_context_include_path_append_default().
*/
RXKB_CONTEXT_NO_DEFAULT_INCLUDES = (1 << 0),
/**
* Load the extra items that are considered too exotic for the default list.
*
* For historical reasons, xkeyboard-config ships those exotic rules in a
* separate file (e.g. `evdev.extras.xml`). Where the exotic rules are
* requested, libxkbregistry will look for and load `$ruleset.extras.xml`
* in the include paths, see rxkb_context_include_path_append() for details
* on the lookup behavior.
*/
RXKB_CONTEXT_LOAD_EXOTIC_RULES = (1 << 1),
};
/**
* Create a new xkb registry context.
*
* The context has an initial refcount of 1. Use rxkb_context_unref() to release
* memory associated with this context.
*
* Creating a context does not parse the files yet, use
* rxkb_context_parse().
*
* @param flags Flags affecting context behavior
* @return A new xkb registry context or NULL on failure
*/
struct rxkb_context *
rxkb_context_new(enum rxkb_context_flags flags);
/** Specifies a logging level. */
enum rxkb_log_level {
RXKB_LOG_LEVEL_CRITICAL = 10, /**< Log critical internal errors only. */
RXKB_LOG_LEVEL_ERROR = 20, /**< Log all errors. */
RXKB_LOG_LEVEL_WARNING = 30, /**< Log warnings and errors. */
RXKB_LOG_LEVEL_INFO = 40, /**< Log information, warnings, and errors. */
RXKB_LOG_LEVEL_DEBUG = 50 /**< Log everything. */
};
/**
* Set the current logging level.
*
* @param ctx The context in which to set the logging level.
* @param level The logging level to use. Only messages from this level
* and below will be logged.
*
* The default level is RXKB_LOG_LEVEL_ERROR. The environment variable
* RXKB_LOG_LEVEL, if set at the time the context was created, overrides the
* default value. It may be specified as a level number or name.
*/
void
rxkb_context_set_log_level(struct rxkb_context *ctx,
enum rxkb_log_level level);
/**
* Get the current logging level.
*/
enum rxkb_log_level
rxkb_context_get_log_level(struct rxkb_context *ctx);
/**
* Set a custom function to handle logging messages.
*
* @param ctx The context in which to use the set logging function.
* @param log_fn The function that will be called for logging messages.
* Passing NULL restores the default function, which logs to stderr.
*
* By default, log messages from this library are printed to stderr. This
* function allows you to replace the default behavior with a custom
* handler. The handler is only called with messages which match the
* current logging level and verbosity settings for the context.
* level is the logging level of the message. @a format and @a args are
* the same as in the vprintf(3) function.
*
* You may use rxkb_context_set_user_data() on the context, and then call
* rxkb_context_get_user_data() from within the logging function to provide
* it with additional private context.
*/
void
rxkb_context_set_log_fn(struct rxkb_context *ctx,
void (*log_fn)(struct rxkb_context *ctx,
enum rxkb_log_level level,
const char *format, va_list args));
/**
* Parse the given ruleset. This can only be called once per context and once
* parsed the data in the context is considered constant and will never
* change.
*
* This function parses all files with the given ruleset name. See
* rxkb_context_include_path_append() for details.
*
* If this function returns false, libxkbregistry failed to parse the xml files.
* This is usually caused by invalid files on the host and should be debugged by
* the host's administrator using external tools. Callers should reduce the
* include paths to known good paths and/or fall back to a default RMLVO set.
*
* If this function returns false, the context should be be considered dead and
* must be released with rxkb_context_unref().
*
* @param ctx The xkb registry context
* @param ruleset The ruleset to parse, e.g. "evdev"
* @return true on success or false on failure
*/
bool
rxkb_context_parse(struct rxkb_context *ctx, const char *ruleset);
/**
* Parse the default ruleset as configured at build time. See
* rxkb_context_parse() for details.
*/
bool
rxkb_context_parse_default_ruleset(struct rxkb_context *ctx);
/**
* Increases the refcount of this object by one and returns the object.
*
* @param ctx The xkb registry context
* @return The passed in object
*/
struct rxkb_context*
rxkb_context_ref(struct rxkb_context *ctx);
/**
* Decreases the refcount of this object by one. Where the refcount of an
* object hits zero, associated resources will be freed.
*
* @param ctx The xkb registry context
* @return always NULL
*/
struct rxkb_context*
rxkb_context_unref(struct rxkb_context *ctx);
/**
* Assign user-specific data. libxkbregistry will not look at or modify the
* data, it will merely return the same pointer in
* rxkb_context_get_user_data().
*
* @param ctx The xkb registry context
* @param user_data User-specific data pointer
*/
void
rxkb_context_set_user_data(struct rxkb_context *ctx, void *user_data);
/**
* Return the pointer passed into rxkb_context_get_user_data().
*
* @param ctx The xkb registry context
* @return User-specific data pointer
*/
void *
rxkb_context_get_user_data(struct rxkb_context *ctx);
/**
* Append a new entry to the context's include path.
*
* The include path handling is optimized for the most common use-case: a set of
* system files that provide a complete set of MLVO and some
* custom MLVO provided by a user **in addition** to the system set.
*
* The include paths should be given so that the least complete path is
* specified first and the most complete path is appended last. For example:
*
* @code
* ctx = rxkb_context_new(RXKB_CONTEXT_NO_DEFAULT_INCLUDES);
* rxkb_context_include_path_append(ctx, "/home/user/.config/xkb");
* rxkb_context_include_path_append(ctx, "/usr/share/X11/xkb");
* rxkb_context_parse(ctx, "evdev");
* @endcode
*
* The above example reflects the default behavior unless @ref
* RXKB_CONTEXT_NO_DEFAULT_INCLUDES is provided.
*
* Loading of the files is in **reverse order**, i.e. the last path appended is
* loaded first - in this case the ``/usr/share/X11/xkb`` path.
* Any models, layouts, variants and options defined in the "evdev" ruleset
* are loaded into the context. Then, any RMLVO found in the "evdev" ruleset of
* the user's path (``/home/user/.config/xkb`` in this example) are **appended**
* to the existing set.
*
* Note that data from previously loaded include paths is never overwritten,
* only appended to. It is not not possible to change the system-provided data,
* only to append new models, layouts, variants and options to it.
*
* In other words, to define a new variant of the "us" layout called "banana",
* the following XML is sufficient.
*
* @verbatim
* <xkbConfigRegistry version="1.1">
* <layoutList>
* <layout>
* <configItem>
* <name>us</name>
* </configItem>
* <variantList>
* <variant>
* <configItem>
* <name>banana</name>
* <description>English (Banana)</description>
* </configItem>
* </variant>
* </layout>
* </layoutList>
* </xkbConfigRegistry>
* @endverbatim
*
* The list of models, options and all other layouts (including "us" and its
* variants) is taken from the system files. The resulting list of layouts will
* thus have a "us" keyboard layout with the variant "banana" and all other
* system-provided variants (dvorak, colemak, intl, etc.)
*
* This function must be called before rxkb_context_parse() or
* rxkb_context_parse_default_ruleset().
*
* @returns true on success, or false if the include path could not be added
* or is inaccessible.
*/
bool
rxkb_context_include_path_append(struct rxkb_context *ctx, const char *path);
/**
* Append the default include paths to the context's include path.
* See rxkb_context_include_path_append() for details about the merge order.
*
* This function must be called before rxkb_context_parse() or
* rxkb_context_parse_default_ruleset().
*
* @returns true on success, or false if the include path could not be added
* or is inaccessible.
*/
bool
rxkb_context_include_path_append_default(struct rxkb_context *ctx);
/**
* Return the first model for this context. Use this to start iterating over
* the models, followed by calls to rxkb_model_next(). Models are not sorted.
*
* The refcount of the returned model is not increased. Use rxkb_model_ref() if
* you need to keep this struct outside the immediate scope.
*
* @return The first model in the model list.
*/
struct rxkb_model *
rxkb_model_first(struct rxkb_context *ctx);
/**
* Return the next model for this context. Returns NULL when no more models
* are available.
*
* The refcount of the returned model is not increased. Use rxkb_model_ref() if
* you need to keep this struct outside the immediate scope.
*
* @return the next model or NULL at the end of the list
*/
struct rxkb_model *
rxkb_model_next(struct rxkb_model *m);
/**
* Increase the refcount of the argument by one.
*
* @returns The argument passed in to this function.
*/
struct rxkb_model *
rxkb_model_ref(struct rxkb_model *m);
/**
* Decrease the refcount of the argument by one. When the refcount hits zero,
* all memory associated with this struct is freed.
*
* @returns always NULL
*/
struct rxkb_model *
rxkb_model_unref(struct rxkb_model *m);
/**
* Return the name of this model. This is the value for M in RMLVO, to be used
* with libxkbcommon.
*/
const char *
rxkb_model_get_name(struct rxkb_model *m);
/**
* Return a human-readable description of this model. This function may return
* NULL.
*/
const char *
rxkb_model_get_description(struct rxkb_model *m);
/**
* Return the vendor name for this model. This function may return NULL.
*/
const char *
rxkb_model_get_vendor(struct rxkb_model *m);
/**
* Return the popularity for this model.
*/
enum rxkb_popularity
rxkb_model_get_popularity(struct rxkb_model *m);
/**
* Return the first layout for this context. Use this to start iterating over
* the layouts, followed by calls to rxkb_layout_next(). Layouts are not sorted.
*
* The refcount of the returned layout is not increased. Use rxkb_layout_ref() if
* you need to keep this struct outside the immediate scope.
*
* @return The first layout in the layout list.
*/
struct rxkb_layout *
rxkb_layout_first(struct rxkb_context *ctx);
/**
* Return the next layout for this context. Returns NULL when no more layouts
* are available.
*
* The refcount of the returned layout is not increased. Use rxkb_layout_ref()
* if you need to keep this struct outside the immediate scope.
*
* @return the next layout or NULL at the end of the list
*/
struct rxkb_layout *
rxkb_layout_next(struct rxkb_layout *l);
/**
* Increase the refcount of the argument by one.
*
* @returns The argument passed in to this function.
*/
struct rxkb_layout *
rxkb_layout_ref(struct rxkb_layout *l);
/**
* Decrease the refcount of the argument by one. When the refcount hits zero,
* all memory associated with this struct is freed.
*
* @returns always NULL
*/
struct rxkb_layout *
rxkb_layout_unref(struct rxkb_layout *l);
/**
* Return the name of this layout. This is the value for L in RMLVO, to be used
* with libxkbcommon.
*/
const char *
rxkb_layout_get_name(struct rxkb_layout *l);
/**
* Return the variant of this layout. This is the value for V in RMLVO, to be
* used with libxkbcommon.
*
* A variant does not stand on its own, it always depends on the base layout.
* e.g. there may be multiple variants called "intl" but there is only one
* "us(intl)".
*
* Where the variant is NULL, the layout is the base layout (e.g. "us").
*/
const char *
rxkb_layout_get_variant(struct rxkb_layout *l);
/**
* Return a short (one-word) description of this layout. This function may
* return NULL.
*/
const char *
rxkb_layout_get_brief(struct rxkb_layout *l);
/**
* Return a human-readable description of this layout. This function may return
* NULL.
*/
const char *
rxkb_layout_get_description(struct rxkb_layout *l);
/**
* Return the popularity for this layout.
*/
enum rxkb_popularity
rxkb_layout_get_popularity(struct rxkb_layout *l);
/**
* Return the first option group for this context. Use this to start iterating
* over the option groups, followed by calls to rxkb_option_group_next().
* Option groups are not sorted.
*
* The refcount of the returned option group is not increased. Use
* rxkb_option_group_ref() if you need to keep this struct outside the immediate
* scope.
*
* @return The first option group in the option group list.
*/
struct rxkb_option_group *
rxkb_option_group_first(struct rxkb_context *ctx);
/**
* Return the next option group for this context. Returns NULL when no more
* option groups are available.
*
* The refcount of the returned option group is not increased. Use
* rxkb_option_group_ref() if you need to keep this struct outside the immediate
* scope.
*
* @return the next option group or NULL at the end of the list
*/
struct rxkb_option_group *
rxkb_option_group_next(struct rxkb_option_group *g);
/**
* Increase the refcount of the argument by one.
*
* @returns The argument passed in to this function.
*/
struct rxkb_option_group *
rxkb_option_group_ref(struct rxkb_option_group *g);
/**
* Decrease the refcount of the argument by one. When the refcount hits zero,
* all memory associated with this struct is freed.
*
* @returns always NULL
*/
struct rxkb_option_group *
rxkb_option_group_unref(struct rxkb_option_group *g);
/**
* Return the name of this option group. This is **not** the value for O in
* RMLVO, the name can be used for internal sorting in the caller. This function
* may return NULL.
*/
const char *
rxkb_option_group_get_name(struct rxkb_option_group *m);
/**
* Return a human-readable description of this option group. This function may
* return NULL.
*/
const char *
rxkb_option_group_get_description(struct rxkb_option_group *m);
/**
* @return true if multiple options within this option group can be selected
* simultaneously, false if all options within this option group
* are mutually exclusive.
*/
bool
rxkb_option_group_allows_multiple(struct rxkb_option_group *g);
/**
* Return the popularity for this option group.
*/
enum rxkb_popularity
rxkb_option_group_get_popularity(struct rxkb_option_group *g);
/**
* Return the first option for this option group. Use this to start iterating
* over the options, followed by calls to rxkb_option_next(). Options are not
* sorted.
*
* The refcount of the returned option is not increased. Use rxkb_option_ref()
* if you need to keep this struct outside the immediate scope.
*
* @return The first option in the option list.
*/
struct rxkb_option *
rxkb_option_first(struct rxkb_option_group *group);
/**
* Return the next option for this option group. Returns NULL when no more
* options are available.
*
* The refcount of the returned options is not increased. Use rxkb_option_ref()
* if you need to keep this struct outside the immediate scope.
*
* @returns The next option or NULL at the end of the list
*/
struct rxkb_option *
rxkb_option_next(struct rxkb_option *o);
/**
* Increase the refcount of the argument by one.
*
* @returns The argument passed in to this function.
*/
struct rxkb_option *
rxkb_option_ref(struct rxkb_option *o);
/**
* Decrease the refcount of the argument by one. When the refcount hits zero,
* all memory associated with this struct is freed.
*
* @returns always NULL
*/
struct rxkb_option *
rxkb_option_unref(struct rxkb_option *o);
/**
* Return the name of this option. This is the value for O in RMLVO, to be used
* with libxkbcommon.
*/
const char *
rxkb_option_get_name(struct rxkb_option *o);
/**
* Return a short (one-word) description of this option. This function may
* return NULL.
*/
const char *
rxkb_option_get_brief(struct rxkb_option *o);
/**
* Return a human-readable description of this option. This function may return
* NULL.
*/
const char *
rxkb_option_get_description(struct rxkb_option *o);
/**
* Return the popularity for this option.
*/
enum rxkb_popularity
rxkb_option_get_popularity(struct rxkb_option *o);
/**
* Increase the refcount of the argument by one.
*
* @returns The argument passed in to this function.
*/
struct rxkb_iso639_code *
rxkb_iso639_code_ref(struct rxkb_iso639_code *iso639);
/**
* Decrease the refcount of the argument by one. When the refcount hits zero,
* all memory associated with this struct is freed.
*
* @returns always NULL
*/
struct rxkb_iso639_code *
rxkb_iso639_code_unref(struct rxkb_iso639_code *iso639);
/**
* Return the ISO 639-3 code for this code (e.g. "eng", "fra").
*/
const char *
rxkb_iso639_code_get_code(struct rxkb_iso639_code *iso639);
/**
* Return the first ISO 639 for this layout. Use this to start iterating over
* the codes, followed by calls to rxkb_iso639_code_next(). Codes are not
* sorted.
*
* The refcount of the returned code is not increased. Use rxkb_iso639_code_ref()
* if you need to keep this struct outside the immediate scope.
*
* @return The first code in the code list.
*/
struct rxkb_iso639_code *
rxkb_layout_get_iso639_first(struct rxkb_layout *layout);
/**
* Return the next code in the list. Returns NULL when no more codes
* are available.
*
* The refcount of the returned codes is not increased. Use
* rxkb_iso639_code_ref() if you need to keep this struct outside the immediate
* scope.
*
* @returns The next code or NULL at the end of the list
*/
struct rxkb_iso639_code *
rxkb_iso639_code_next(struct rxkb_iso639_code *iso639);
/**
* Increase the refcount of the argument by one.
*
* @returns The argument passed in to this function.
*/
struct rxkb_iso3166_code *
rxkb_iso3166_code_ref(struct rxkb_iso3166_code *iso3166);
/**
* Decrease the refcount of the argument by one. When the refcount hits zero,
* all memory associated with this struct is freed.
*
* @returns always NULL
*/
struct rxkb_iso3166_code *
rxkb_iso3166_code_unref(struct rxkb_iso3166_code *iso3166);
/**
* Return the ISO 3166 Alpha 2 code for this code (e.g. "US", "FR").
*/
const char *
rxkb_iso3166_code_get_code(struct rxkb_iso3166_code *iso3166);
/**
* Return the first ISO 3166 for this layout. Use this to start iterating over
* the codes, followed by calls to rxkb_iso3166_code_next(). Codes are not
* sorted.
*
* The refcount of the returned code is not increased. Use
* rxkb_iso3166_code_ref() if you need to keep this struct outside the immediate
* scope.
*
* @return The first code in the code list.
*/
struct rxkb_iso3166_code *
rxkb_layout_get_iso3166_first(struct rxkb_layout *layout);
/**
* Return the next code in the list. Returns NULL when no more codes
* are available.
*
* The refcount of the returned codes is not increased. Use
* rxkb_iso3166_code_ref() if you need to keep this struct outside the immediate
* scope.
*
* @returns The next code or NULL at the end of the list
*/
struct rxkb_iso3166_code *
rxkb_iso3166_code_next(struct rxkb_iso3166_code *iso3166);
/** @} */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _XKBREGISTRY_H_ */

View File

@ -1,168 +0,0 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_gcc_builtin.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_GCC_BUILTIN(BUILTIN)
#
# DESCRIPTION
#
# This macro checks if the compiler supports one of GCC's built-in
# functions; many other compilers also provide those same built-ins.
#
# The BUILTIN parameter is the name of the built-in function.
#
# If BUILTIN is supported define HAVE_<BUILTIN>. Keep in mind that since
# builtins usually start with two underscores they will be copied over
# into the HAVE_<BUILTIN> definition (e.g. HAVE___BUILTIN_EXPECT for
# __builtin_expect()).
#
# The macro caches its result in the ax_cv_have_<BUILTIN> variable (e.g.
# ax_cv_have___builtin_expect).
#
# The macro currently supports the following built-in functions:
#
# __builtin_assume_aligned
# __builtin_bswap32
# __builtin_bswap64
# __builtin_choose_expr
# __builtin___clear_cache
# __builtin_clrsb
# __builtin_clrsbl
# __builtin_clrsbll
# __builtin_clz
# __builtin_clzl
# __builtin_clzll
# __builtin_complex
# __builtin_constant_p
# __builtin_ctz
# __builtin_ctzl
# __builtin_ctzll
# __builtin_expect
# __builtin_ffs
# __builtin_ffsl
# __builtin_ffsll
# __builtin_fpclassify
# __builtin_huge_val
# __builtin_huge_valf
# __builtin_huge_vall
# __builtin_inf
# __builtin_infd128
# __builtin_infd32
# __builtin_infd64
# __builtin_inff
# __builtin_infl
# __builtin_isinf_sign
# __builtin_nan
# __builtin_nand128
# __builtin_nand32
# __builtin_nand64
# __builtin_nanf
# __builtin_nanl
# __builtin_nans
# __builtin_nansf
# __builtin_nansl
# __builtin_object_size
# __builtin_parity
# __builtin_parityl
# __builtin_parityll
# __builtin_popcount
# __builtin_popcountl
# __builtin_popcountll
# __builtin_powi
# __builtin_powif
# __builtin_powil
# __builtin_prefetch
# __builtin_trap
# __builtin_types_compatible_p
# __builtin_unreachable
#
# Unsuppored built-ins will be tested with an empty parameter set and the
# result of the check might be wrong or meaningless so use with care.
#
# LICENSE
#
# Copyright (c) 2013 Gabriele Svelto <gabriele.svelto@gmail.com>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 2
AC_DEFUN([AX_GCC_BUILTIN], [
AS_VAR_PUSHDEF([ac_var], [ax_cv_have_$1])
AC_CACHE_CHECK([for $1], [ac_var], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [
m4_case([$1],
[__builtin_assume_aligned], [$1("", 0)],
[__builtin_bswap32], [$1(0)],
[__builtin_bswap64], [$1(0)],
[__builtin_choose_expr], [$1(0, 0, 0)],
[__builtin___clear_cache], [$1("", "")],
[__builtin_clrsb], [$1(0)],
[__builtin_clrsbl], [$1(0)],
[__builtin_clrsbll], [$1(0)],
[__builtin_clz], [$1(0)],
[__builtin_clzl], [$1(0)],
[__builtin_clzll], [$1(0)],
[__builtin_complex], [$1(0.0, 0.0)],
[__builtin_constant_p], [$1(0)],
[__builtin_ctz], [$1(0)],
[__builtin_ctzl], [$1(0)],
[__builtin_ctzll], [$1(0)],
[__builtin_expect], [$1(0, 0)],
[__builtin_ffs], [$1(0)],
[__builtin_ffsl], [$1(0)],
[__builtin_ffsll], [$1(0)],
[__builtin_fpclassify], [$1(0, 1, 2, 3, 4, 0.0)],
[__builtin_huge_val], [$1()],
[__builtin_huge_valf], [$1()],
[__builtin_huge_vall], [$1()],
[__builtin_inf], [$1()],
[__builtin_infd128], [$1()],
[__builtin_infd32], [$1()],
[__builtin_infd64], [$1()],
[__builtin_inff], [$1()],
[__builtin_infl], [$1()],
[__builtin_isinf_sign], [$1(0.0)],
[__builtin_nan], [$1("")],
[__builtin_nand128], [$1("")],
[__builtin_nand32], [$1("")],
[__builtin_nand64], [$1("")],
[__builtin_nanf], [$1("")],
[__builtin_nanl], [$1("")],
[__builtin_nans], [$1("")],
[__builtin_nansf], [$1("")],
[__builtin_nansl], [$1("")],
[__builtin_object_size], [$1("", 0)],
[__builtin_parity], [$1(0)],
[__builtin_parityl], [$1(0)],
[__builtin_parityll], [$1(0)],
[__builtin_popcount], [$1(0)],
[__builtin_popcountl], [$1(0)],
[__builtin_popcountll], [$1(0)],
[__builtin_powi], [$1(0, 0)],
[__builtin_powif], [$1(0, 0)],
[__builtin_powil], [$1(0, 0)],
[__builtin_prefetch], [$1("")],
[__builtin_trap], [$1()],
[__builtin_types_compatible_p], [$1(int, int)],
[__builtin_unreachable], [$1()],
[m4_warn([syntax], [Unsupported built-in $1, the test may fail])
$1()]
)
])],
[AS_VAR_SET([ac_var], [yes])],
[AS_VAR_SET([ac_var], [no])])
])
AS_IF([test yes = AS_VAR_GET([ac_var])],
[AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_$1), 1,
[Define to 1 if the system has the `$1' built-in function])], [])
AS_VAR_POPDEF([ac_var])
])

View File

@ -0,0 +1,830 @@
project(
'libxkbcommon',
'c',
version: '1.3.0',
default_options: [
'c_std=c11',
'warning_level=2',
'b_lundef=true',
],
meson_version : '>= 0.49.0',
)
pkgconfig = import('pkgconfig')
cc = meson.get_compiler('c')
dir_libexec = get_option('prefix')/get_option('libexecdir')/'xkbcommon'
# Compiler flags.
cflags = [
'-fno-strict-aliasing',
'-fsanitize-undefined-trap-on-error',
'-Wno-unused-parameter',
'-Wno-missing-field-initializers',
'-Wpointer-arith',
'-Wmissing-declarations',
'-Wformat=2',
'-Wstrict-prototypes',
'-Wmissing-prototypes',
'-Wnested-externs',
'-Wbad-function-cast',
'-Wshadow',
'-Wlogical-op',
'-Wdate-time',
'-Wwrite-strings',
'-Wno-documentation-deprecated-sync',
]
add_project_arguments(cc.get_supported_arguments(cflags), language: 'c')
# The XKB config root.
XKBCONFIGROOT = get_option('xkb-config-root')
if XKBCONFIGROOT == ''
xkeyboard_config_dep = dependency('xkeyboard-config', required: false)
if xkeyboard_config_dep.found()
XKBCONFIGROOT = xkeyboard_config_dep.get_pkgconfig_variable('xkb_base')
else
XKBCONFIGROOT = get_option('prefix')/get_option('datadir')/'X11'/'xkb'
endif
endif
XKBCONFIGEXTRAPATH = get_option('xkb-config-extra-path')
if XKBCONFIGEXTRAPATH == ''
XKBCONFIGEXTRAPATH = get_option('prefix')/get_option('sysconfdir')/'xkb'
endif
# The X locale directory for compose.
XLOCALEDIR = get_option('x-locale-root')
if XLOCALEDIR == ''
XLOCALEDIR = get_option('prefix')/get_option('datadir')/'X11'/'locale'
endif
# config.h.
configh_data = configuration_data()
configh_data.set('EXIT_INVALID_USAGE', '2')
configh_data.set_quoted('LIBXKBCOMMON_VERSION', meson.project_version())
configh_data.set_quoted('LIBXKBCOMMON_TOOL_PATH', dir_libexec)
# Like AC_USE_SYSTEM_EXTENSIONS, what #define to use to get extensions
# beyond the base POSIX function set.
if host_machine.system() == 'sunos'
system_extensions = '__EXTENSIONS__'
else
system_extensions = '_GNU_SOURCE'
endif
configh_data.set(system_extensions, 1)
system_ext_define = '#define ' + system_extensions
configh_data.set_quoted('DFLT_XKB_CONFIG_ROOT', XKBCONFIGROOT)
configh_data.set_quoted('DFLT_XKB_CONFIG_EXTRA_PATH', XKBCONFIGEXTRAPATH)
configh_data.set_quoted('XLOCALEDIR', XLOCALEDIR)
configh_data.set_quoted('DEFAULT_XKB_RULES', get_option('default-rules'))
configh_data.set_quoted('DEFAULT_XKB_MODEL', get_option('default-model'))
configh_data.set_quoted('DEFAULT_XKB_LAYOUT', get_option('default-layout'))
if get_option('default-variant') != ''
configh_data.set_quoted('DEFAULT_XKB_VARIANT', get_option('default-variant'))
else
configh_data.set('DEFAULT_XKB_VARIANT', 'NULL')
endif
if get_option('default-options') != ''
configh_data.set_quoted('DEFAULT_XKB_OPTIONS', get_option('default-options'))
else
configh_data.set('DEFAULT_XKB_OPTIONS', 'NULL')
endif
if cc.has_header('unistd.h')
configh_data.set('HAVE_UNISTD_H', 1)
endif
if cc.links('int main(){if(__builtin_expect(1<0,0)){}}', name: '__builtin_expect')
configh_data.set('HAVE___BUILTIN_EXPECT', 1)
endif
if cc.has_header_symbol('unistd.h', 'eaccess', prefix: system_ext_define)
configh_data.set('HAVE_EACCESS', 1)
endif
if cc.has_header_symbol('unistd.h', 'euidaccess', prefix: system_ext_define)
configh_data.set('HAVE_EUIDACCESS', 1)
endif
if cc.has_header_symbol('sys/mman.h', 'mmap')
configh_data.set('HAVE_MMAP', 1)
endif
if cc.has_header_symbol('stdlib.h', 'mkostemp', prefix: system_ext_define)
configh_data.set('HAVE_MKOSTEMP', 1)
endif
if cc.has_header_symbol('fcntl.h', 'posix_fallocate', prefix: system_ext_define)
configh_data.set('HAVE_POSIX_FALLOCATE', 1)
endif
if cc.has_header_symbol('string.h', 'strndup', prefix: system_ext_define)
configh_data.set('HAVE_STRNDUP', 1)
endif
if cc.has_header_symbol('stdio.h', 'asprintf', prefix: system_ext_define)
configh_data.set('HAVE_ASPRINTF', 1)
elif cc.has_header_symbol('stdio.h', 'vasprintf', prefix: system_ext_define)
configh_data.set('HAVE_VASPRINTF', 1)
endif
if cc.has_header_symbol('stdlib.h', 'secure_getenv', prefix: system_ext_define)
configh_data.set('HAVE_SECURE_GETENV', 1)
elif cc.has_header_symbol('stdlib.h', '__secure_getenv', prefix: system_ext_define)
configh_data.set('HAVE___SECURE_GETENV', 1)
else
message('C library does not support secure_getenv, using getenv instead')
endif
have_getopt_long = cc.has_header_symbol('getopt.h', 'getopt_long',
prefix: '#define _GNU_SOURCE')
if not cc.has_header_symbol('limits.h', 'PATH_MAX', prefix: system_ext_define)
if host_machine.system() == 'windows'
# see https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#maximum-path-length-limitation
configh_data.set('PATH_MAX', 260)
else
configh_data.set('PATH_MAX', 4096)
endif
endif
# Silence some security & deprecation warnings on MSVC
# for some unix/C functions we use.
# https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-3-c4996?view=vs-2019
configh_data.set('_CRT_SECURE_NO_WARNINGS', 1)
configh_data.set('_CRT_NONSTDC_NO_WARNINGS', 1)
configh_data.set('_CRT_NONSTDC_NO_DEPRECATE', 1)
# Reduce unnecessary includes on MSVC.
configh_data.set('WIN32_LEAN_AND_MEAN', 1)
# Supports -Wl,--version-script?
have_version_script = cc.links(
'int main(){}',
args: '-Wl,--version-script=' + meson.source_root()/'xkbcommon.map',
name: '-Wl,--version-script',
)
map_to_def = find_program('scripts/map-to-def')
# libxkbcommon.
# Note: we use some yacc extensions, which work with either GNU bison
# (preferred) or byacc (with backtracking enabled).
bison = find_program('bison', 'win_bison', required: false)
if bison.found()
yacc_gen = generator(
bison,
output: ['@BASENAME@.c', '@BASENAME@.h'],
arguments: ['--defines=@OUTPUT1@', '-o', '@OUTPUT0@', '-p', '_xkbcommon_', '@INPUT@'],
)
else
byacc = find_program('byacc', required: false)
if byacc.found()
yacc_gen = generator(
byacc,
output: ['@BASENAME@.c', '@BASENAME@.h'],
arguments: ['-H', '@OUTPUT1@', '-o', '@OUTPUT0@', '-p', '_xkbcommon_', '@INPUT@'],
)
else
error('Could not find a compatible YACC program (bison or byacc)')
endif
endif
libxkbcommon_sources = [
'src/compose/parser.c',
'src/compose/parser.h',
'src/compose/paths.c',
'src/compose/paths.h',
'src/compose/state.c',
'src/compose/table.c',
'src/compose/table.h',
'src/xkbcomp/action.c',
'src/xkbcomp/action.h',
'src/xkbcomp/ast.h',
'src/xkbcomp/ast-build.c',
'src/xkbcomp/ast-build.h',
'src/xkbcomp/compat.c',
'src/xkbcomp/expr.c',
'src/xkbcomp/expr.h',
'src/xkbcomp/include.c',
'src/xkbcomp/include.h',
'src/xkbcomp/keycodes.c',
'src/xkbcomp/keymap.c',
'src/xkbcomp/keymap-dump.c',
'src/xkbcomp/keywords.c',
yacc_gen.process('src/xkbcomp/parser.y'),
'src/xkbcomp/parser-priv.h',
'src/xkbcomp/rules.c',
'src/xkbcomp/rules.h',
'src/xkbcomp/scanner.c',
'src/xkbcomp/symbols.c',
'src/xkbcomp/types.c',
'src/xkbcomp/vmod.c',
'src/xkbcomp/vmod.h',
'src/xkbcomp/xkbcomp.c',
'src/xkbcomp/xkbcomp-priv.h',
'src/atom.c',
'src/atom.h',
'src/context.c',
'src/context.h',
'src/context-priv.c',
'src/darray.h',
'src/keysym.c',
'src/keysym.h',
'src/keysym-utf.c',
'src/ks_tables.h',
'src/keymap.c',
'src/keymap.h',
'src/keymap-priv.c',
'src/scanner-utils.h',
'src/state.c',
'src/text.c',
'src/text.h',
'src/utf8.c',
'src/utf8.h',
'src/utils.c',
'src/utils.h',
]
libxkbcommon_link_args = []
libxkbcommon_link_deps = []
if have_version_script
libxkbcommon_link_args += '-Wl,--version-script=' + meson.source_root()/'xkbcommon.map'
libxkbcommon_link_deps += 'xkbcommon.map'
elif cc.get_argument_syntax() == 'msvc'
libxkbcommon_def = custom_target('xkbcommon.def',
command: [map_to_def, '@INPUT@', '@OUTPUT@'],
input: 'xkbcommon.map',
output: 'kxbcommon.def',
)
libxkbcommon_link_deps += libxkbcommon_def
libxkbcommon_link_args += '/DEF:' + libxkbcommon_def.full_path()
endif
libxkbcommon = library(
'xkbcommon',
'include/xkbcommon/xkbcommon.h',
libxkbcommon_sources,
link_args: libxkbcommon_link_args,
link_depends: libxkbcommon_link_deps,
gnu_symbol_visibility: 'hidden',
version: '0.0.0',
install: true,
include_directories: include_directories('src', 'include'),
)
install_headers(
'include/xkbcommon/xkbcommon.h',
'include/xkbcommon/xkbcommon-compat.h',
'include/xkbcommon/xkbcommon-compose.h',
'include/xkbcommon/xkbcommon-keysyms.h',
'include/xkbcommon/xkbcommon-names.h',
subdir: 'xkbcommon',
)
dep_libxkbcommon = declare_dependency(
link_with: libxkbcommon,
include_directories: include_directories('include'),
)
pkgconfig.generate(
libxkbcommon,
name: 'xkbcommon',
filebase: 'xkbcommon',
version: meson.project_version(),
description: 'XKB API common to servers and clients',
)
# libxkbcommon-x11.
if get_option('enable-x11')
xcb_dep = dependency('xcb', version: '>=1.10', required: false)
xcb_xkb_dep = dependency('xcb-xkb', version: '>=1.10', required: false)
if not xcb_dep.found() or not xcb_xkb_dep.found()
error('''X11 support requires xcb-xkb >= 1.10 which was not found.
You can disable X11 support with -Denable-x11=false.''')
endif
libxkbcommon_x11_sources = [
'src/x11/keymap.c',
'src/x11/state.c',
'src/x11/util.c',
'src/x11/x11-priv.h',
'src/context.h',
'src/context-priv.c',
'src/keymap.h',
'src/keymap-priv.c',
'src/atom.h',
'src/atom.c',
]
libxkbcommon_x11_link_args = []
libxkbcommon_x11_link_deps = []
if have_version_script
libxkbcommon_x11_link_args += '-Wl,--version-script=' + meson.source_root()/'xkbcommon-x11.map'
libxkbcommon_x11_link_deps += 'xkbcommon-x11.map'
elif cc.get_argument_syntax() == 'msvc'
libxkbcommon_x11_def = custom_target('xkbcommon-x11.def',
command: [map_to_def, '@INPUT@', '@OUTPUT@'],
input: 'xkbcommon-x11.map',
output: 'xkbcommon-x11.def',
)
libxkbcommon_x11_link_deps += libxkbcommon_x11_def
libxkbcommon_x11_link_args += '/DEF:' + libxkbcommon_x11_def.full_path()
endif
libxkbcommon_x11 = library(
'xkbcommon-x11',
'include/xkbcommon/xkbcommon-x11.h',
libxkbcommon_x11_sources,
link_args: libxkbcommon_x11_link_args,
link_depends: libxkbcommon_x11_link_deps,
gnu_symbol_visibility: 'hidden',
version: '0.0.0',
install: true,
include_directories: include_directories('src', 'include'),
link_with: libxkbcommon,
dependencies: [
xcb_dep,
xcb_xkb_dep,
],
)
install_headers(
'include/xkbcommon/xkbcommon-x11.h',
subdir: 'xkbcommon',
)
dep_libxkbcommon_x11 = declare_dependency(
link_with: libxkbcommon_x11,
include_directories: include_directories('include'),
)
pkgconfig.generate(
libxkbcommon_x11,
name: 'xkbcommon-x11',
filebase: 'xkbcommon-x11',
version: meson.project_version(),
description: 'XKB API common to servers and clients - X11 support',
requires: ['xkbcommon'],
requires_private: ['xcb>=1.10', 'xcb-xkb>=1.10'],
)
endif
# libxkbregistry
if get_option('enable-xkbregistry')
dep_libxml = dependency('libxml-2.0')
deps_libxkbregistry = [dep_libxml]
libxkbregistry_sources = [
'src/registry.c',
'src/utils.h',
'src/utils.c',
'src/util-list.h',
'src/util-list.c',
]
libxkbregistry_link_args = []
libxkbregistry_link_deps = []
if have_version_script
libxkbregistry_link_args += '-Wl,--version-script=' + meson.source_root()/'xkbregistry.map'
libxkbregistry_link_deps += 'xkbregistry.map'
elif cc.get_argument_syntax() == 'msvc'
libxkbregistry_def = custom_target('xkbregistry.def',
command: [map_to_def, '@INPUT@', '@OUTPUT@'],
input: 'xkbregistry.map',
output: 'xkbregistry.def',
)
libxkbregistry_link_deps += libxkbregistry_def
libxkbregistry_link_args += '/DEF:' + libxkbregistry_def.full_path()
endif
libxkbregistry = library(
'xkbregistry',
'include/xkbcommon/xkbregistry.h',
libxkbregistry_sources,
link_args: libxkbregistry_link_args,
link_depends: libxkbregistry_link_deps,
gnu_symbol_visibility: 'hidden',
dependencies: deps_libxkbregistry,
version: '0.0.0',
install: true,
include_directories: include_directories('src', 'include'),
)
install_headers(
'include/xkbcommon/xkbregistry.h',
subdir: 'xkbcommon',
)
pkgconfig.generate(
libxkbregistry,
name: 'xkbregistry',
filebase: 'xkbregistry',
version: meson.project_version(),
description: 'XKB API to query available rules, models, layouts, variants and options',
)
dep_libxkbregistry = declare_dependency(
link_with: libxkbregistry,
include_directories: include_directories('include'),
)
endif
man_pages = []
# Tools
build_tools = have_getopt_long
if build_tools
libxkbcommon_tools_internal = static_library(
'tools-internal',
'tools/tools-common.h',
'tools/tools-common.c',
dependencies: dep_libxkbcommon,
)
tools_dep = declare_dependency(
include_directories: [include_directories('tools', 'include')],
link_with: libxkbcommon_tools_internal,
)
executable('xkbcli', 'tools/xkbcli.c',
dependencies: tools_dep, install: true)
install_man('tools/xkbcli.1')
xkbcli_compile_keymap = executable('xkbcli-compile-keymap',
'tools/compile-keymap.c',
dependencies: tools_dep,
install: true,
install_dir: dir_libexec)
install_man('tools/xkbcli-compile-keymap.1')
# The same tool again, but with access to some private APIs.
executable('compile-keymap',
'tools/compile-keymap.c',
libxkbcommon_sources,
dependencies: [tools_dep],
c_args: ['-DENABLE_PRIVATE_APIS'],
include_directories: [include_directories('src', 'include')],
install: false)
executable('compose',
'tools/compose.c',
dependencies: tools_dep,
include_directories: [include_directories('src', 'include')],
install: false)
configh_data.set10('HAVE_XKBCLI_COMPILE_KEYMAP', true)
executable('xkbcli-how-to-type',
'tools/how-to-type.c',
dependencies: tools_dep,
install: true,
install_dir: dir_libexec)
install_man('tools/xkbcli-how-to-type.1')
configh_data.set10('HAVE_XKBCLI_HOW_TO_TYPE', true)
if cc.has_header('linux/input.h')
executable('xkbcli-interactive-evdev',
'tools/interactive-evdev.c',
dependencies: tools_dep,
install: true,
install_dir: dir_libexec)
configh_data.set10('HAVE_XKBCLI_INTERACTIVE_EVDEV', true)
install_man('tools/xkbcli-interactive-evdev.1')
endif
if get_option('enable-x11')
x11_tools_dep = declare_dependency(
link_with: libxkbcommon_x11,
dependencies: [
tools_dep,
xcb_dep,
xcb_xkb_dep,
],
)
executable('xkbcli-interactive-x11',
'tools/interactive-x11.c',
dependencies: x11_tools_dep,
install: true,
install_dir: dir_libexec)
install_man('tools/xkbcli-interactive-x11.1')
configh_data.set10('HAVE_XKBCLI_INTERACTIVE_X11', true)
endif
if get_option('enable-wayland')
wayland_client_dep = dependency('wayland-client', version: '>=1.2.0', required: false)
wayland_protocols_dep = dependency('wayland-protocols', version: '>=1.12', required: false)
wayland_scanner_dep = dependency('wayland-scanner', required: false, native: true)
if not wayland_client_dep.found() or not wayland_protocols_dep.found() or not wayland_scanner_dep.found()
error('''The Wayland xkbcli programs require wayland-client >= 1.2.0, wayland-protocols >= 1.7 which were not found.
You can disable the Wayland xkbcli programs with -Denable-wayland=false.''')
endif
wayland_scanner = find_program(wayland_scanner_dep.get_pkgconfig_variable('wayland_scanner'))
wayland_scanner_code_gen = generator(
wayland_scanner,
output: '@BASENAME@-protocol.c',
arguments: ['code', '@INPUT@', '@OUTPUT@'],
)
wayland_scanner_client_header_gen = generator(
wayland_scanner,
output: '@BASENAME@-client-protocol.h',
arguments: ['client-header', '@INPUT@', '@OUTPUT@'],
)
wayland_protocols_datadir = wayland_protocols_dep.get_pkgconfig_variable('pkgdatadir')
xdg_shell_xml = wayland_protocols_datadir/'stable/xdg-shell/xdg-shell.xml'
xdg_shell_sources = [
wayland_scanner_code_gen.process(xdg_shell_xml),
wayland_scanner_client_header_gen.process(xdg_shell_xml),
]
executable('xkbcli-interactive-wayland',
'tools/interactive-wayland.c',
xdg_shell_sources,
dependencies: [tools_dep, wayland_client_dep],
install: true,
install_dir: dir_libexec)
install_man('tools/xkbcli-interactive-wayland.1')
configh_data.set10('HAVE_XKBCLI_INTERACTIVE_WAYLAND', true)
endif
if get_option('enable-xkbregistry')
configh_data.set10('HAVE_XKBCLI_LIST', true)
executable('xkbcli-list',
'tools/registry-list.c',
dependencies: dep_libxkbregistry,
install: true,
install_dir: dir_libexec)
install_man('tools/xkbcli-list.1')
endif
endif
# xkeyboard-config "verifier"
xkct_config = configuration_data()
xkct_config.set('MESON_BUILD_ROOT', meson.build_root())
xkct_config.set('XKB_CONFIG_ROOT', XKBCONFIGROOT)
configure_file(input: 'test/xkeyboard-config-test.py.in',
output: 'xkeyboard-config-test',
configuration: xkct_config)
# Tests
test_env = environment()
test_env.set('XKB_LOG_LEVEL', 'debug')
test_env.set('XKB_LOG_VERBOSITY', '10')
test_env.set('top_srcdir', meson.source_root())
test_env.set('top_builddir', meson.build_root())
test_env.set('HAVE_XKBCLI_INTERACTIVE_EVDEV', configh_data.get('HAVE_XKBCLI_INTERACTIVE_EVDEV', 0).to_string())
test_env.set('HAVE_XKBCLI_INTERACTIVE_WAYLAND', configh_data.get('HAVE_XKBCLI_INTERACTIVE_WAYLAND', 0).to_string())
test_env.set('HAVE_XKBCLI_INTERACTIVE_X11', configh_data.get('HAVE_XKBCLI_INTERACTIVE_X11', 0).to_string())
test_env.set('HAVE_XKBCLI_LIST', configh_data.get('HAVE_XKBCLI_LIST', 0).to_string())
test_configh_data = configuration_data()
test_configh_data.set_quoted('TEST_XKB_CONFIG_ROOT', meson.source_root()/'test'/'data')
configure_file(output: 'test-config.h', configuration: test_configh_data)
# Some tests need to use unexported symbols, so we link them against
# an internal copy of libxkbcommon with all symbols exposed.
libxkbcommon_test_internal = static_library(
'xkbcommon-test-internal',
'test/common.c',
'test/test.h',
'test/evdev-scancodes.h',
'bench/bench.c',
'bench/bench.h',
libxkbcommon_sources,
include_directories: include_directories('src', 'include'),
)
test_dep = declare_dependency(
include_directories: include_directories('src', 'include'),
link_with: libxkbcommon_test_internal,
)
if get_option('enable-x11')
libxkbcommon_x11_internal = static_library(
'xkbcommon-x11-internal',
libxkbcommon_x11_sources,
include_directories: include_directories('src', 'include'),
link_with: libxkbcommon_test_internal,
dependencies: [
xcb_dep,
xcb_xkb_dep,
],
)
x11_test_dep = declare_dependency(
link_with: libxkbcommon_x11_internal,
dependencies: [
test_dep,
xcb_dep,
xcb_xkb_dep,
],
)
endif
test(
'keysym',
executable('test-keysym', 'test/keysym.c', dependencies: test_dep),
env: test_env,
)
test(
'keymap',
executable('test-keymap', 'test/keymap.c', dependencies: test_dep),
env: test_env,
)
test(
'filecomp',
executable('test-filecomp', 'test/filecomp.c', dependencies: test_dep),
env: test_env,
)
# TODO: This test currently uses some functions that don't exist on Windows.
if cc.get_id() != 'msvc'
test(
'context',
executable('test-context', 'test/context.c', dependencies: test_dep),
env: test_env,
)
endif
test(
'rules-file',
executable('test-rules-file', 'test/rules-file.c', dependencies: test_dep),
env: test_env,
)
test(
'rules-file-includes',
executable('test-rules-file-includes', 'test/rules-file-includes.c', dependencies: test_dep),
env: test_env,
)
test(
'stringcomp',
executable('test-stringcomp', 'test/stringcomp.c', dependencies: test_dep),
env: test_env,
)
test(
'buffercomp',
executable('test-buffercomp', 'test/buffercomp.c', dependencies: test_dep),
env: test_env,
)
test(
'log',
executable('test-log', 'test/log.c', dependencies: test_dep),
env: test_env,
)
test(
'atom',
executable('test-atom', 'test/atom.c', dependencies: test_dep),
env: test_env,
)
test(
'utf8',
executable('test-utf8', 'test/utf8.c', dependencies: test_dep),
env: test_env,
)
test(
'state',
executable('test-state', 'test/state.c', dependencies: test_dep),
env: test_env,
)
test(
'keyseq',
executable('test-keyseq', 'test/keyseq.c', dependencies: test_dep),
env: test_env,
)
test(
'rulescomp',
executable('test-rulescomp', 'test/rulescomp.c', dependencies: test_dep),
env: test_env,
)
test(
'compose',
executable('test-compose', 'test/compose.c', dependencies: test_dep),
env: test_env,
)
test(
'utils',
executable('test-utils', 'test/utils.c', dependencies: test_dep),
env: test_env,
)
test(
'symbols-leak-test',
find_program('test/symbols-leak-test.py'),
env: test_env,
suite: ['python-tests'],
)
if get_option('enable-x11')
test(
'x11',
executable('test-x11', 'test/x11.c', dependencies: x11_test_dep),
env: test_env,
)
# test/x11comp is meant to be run, but it is (temporarily?) disabled.
# See: https://github.com/xkbcommon/libxkbcommon/issues/30
executable('test-x11comp', 'test/x11comp.c', dependencies: x11_test_dep)
endif
if get_option('enable-xkbregistry')
test(
'registry',
executable('test-registry', 'test/registry.c',
include_directories: include_directories('src'),
dependencies: dep_libxkbregistry),
env: test_env,
)
endif
if build_tools
test('tool-option-parsing',
find_program('test/tool-option-parsing.py'),
env: test_env,
suite: ['python-tests'])
# A set of keysyms to test for. Add one or two symbols to this array
# whenever the xorgproto gets updated to make sure we resolve them.
keysyms_to_test = [
'XF86Macro23',
]
env = environment()
env.set('XKB_CONFIG_ROOT', meson.source_root()/'test'/'data')
foreach keysym: keysyms_to_test
test('keysym-test-@0@'.format(keysym),
find_program('test/test-keysym.py'),
env: env,
args: [keysym, '--tool', xkbcli_compile_keymap],
suite: ['python-tests'])
endforeach
endif
valgrind = find_program('valgrind', required: false)
if valgrind.found()
add_test_setup('valgrind',
exe_wrapper: [valgrind,
'--leak-check=full',
'--track-origins=yes',
'--gen-suppressions=all',
'--error-exitcode=99'],
timeout_multiplier : 10)
else
message('valgrind not found, disabling valgrind test setup')
endif
# Fuzzing target programs.
executable('fuzz-keymap', 'fuzz/keymap/target.c', dependencies: test_dep)
executable('fuzz-compose', 'fuzz/compose/target.c', dependencies: test_dep)
# Benchmarks.
bench_env = environment()
bench_env.set('top_srcdir', meson.source_root())
benchmark(
'key-proc',
executable('bench-key-proc', 'bench/key-proc.c', dependencies: test_dep),
env: bench_env,
)
benchmark(
'rules',
executable('bench-rules', 'bench/rules.c', dependencies: test_dep),
env: bench_env,
)
benchmark(
'rulescomp',
executable('bench-rulescomp', 'bench/rulescomp.c', dependencies: test_dep),
env: bench_env,
)
benchmark(
'compose',
executable('bench-compose', 'bench/compose.c', dependencies: test_dep),
env: bench_env,
)
benchmark(
'atom',
executable('bench-atom', 'bench/atom.c', dependencies: test_dep),
env: bench_env,
)
if get_option('enable-x11')
benchmark(
'x11',
executable('bench-x11', 'bench/x11.c', dependencies: x11_test_dep),
env: bench_env,
)
endif
# Documentation.
if get_option('enable-docs')
doxygen = find_program('doxygen', required: false)
if not doxygen.found()
error('''Documentation requires doxygen which was not found.
You can disable the documentation with -Denable-docs=false.''')
endif
doxygen_wrapper = find_program('scripts/doxygen-wrapper')
doxygen_input = [
'README.md',
'doc/doxygen-extra.css',
'doc/quick-guide.md',
'doc/compat.md',
'doc/user-configuration.md',
'doc/rules-format.md',
'doc/keymap-format-text-v1.md',
'include/xkbcommon/xkbcommon.h',
'include/xkbcommon/xkbcommon-names.h',
'include/xkbcommon/xkbcommon-x11.h',
'include/xkbcommon/xkbcommon-compose.h',
'include/xkbcommon/xkbregistry.h',
]
doxygen_data = configuration_data()
doxygen_data.set('PACKAGE_NAME', meson.project_name())
doxygen_data.set('PACKAGE_VERSION', meson.project_version())
doxygen_data.set('INPUT', ' '.join(doxygen_input))
doxygen_data.set('OUTPUT_DIRECTORY', meson.build_root())
doxyfile = configure_file(
input: 'doc/Doxyfile.in',
output: 'Doxyfile',
configuration: doxygen_data,
)
# TODO: Meson should provide this.
docdir = get_option('datadir')/'doc'/meson.project_name()
custom_target(
'doc',
input: [doxyfile] + doxygen_input,
output: 'html',
command: [doxygen_wrapper, doxygen.path(), meson.build_root()/'Doxyfile', meson.source_root()],
install: true,
install_dir: docdir,
build_by_default: true,
)
endif
configure_file(output: 'config.h', configuration: configh_data)
# Stable variables for projects using xkbcommon as a subproject.
# These variables should not be renamed.
libxkbcommon_dep = dep_libxkbcommon
if get_option('enable-x11')
libxkbcommon_x11_dep = dep_libxkbcommon_x11
endif
if get_option('enable-xkbregistry')
libxkbregistry_dep = dep_libxkbregistry
endif

View File

@ -0,0 +1,69 @@
option(
'xkb-config-root',
type: 'string',
description: 'The XKB config root [default=xkeyboard-config install path]',
)
option(
'xkb-config-extra-path',
type: 'string',
description: 'Extra lookup path for system-wide XKB data [default=$sysconfdir/xkb]',
)
option(
'x-locale-root',
type: 'string',
description: 'The X locale root [default=$datadir/X11/locale]',
)
option(
'default-rules',
type: 'string',
value: 'evdev',
description: 'Default XKB ruleset',
)
option(
'default-model',
type: 'string',
value: 'pc105',
description: 'Default XKB model',
)
option(
'default-layout',
type: 'string',
value: 'us',
description: 'Default XKB layout',
)
option(
'default-variant',
type: 'string',
value: '',
description: 'Default XKB variant',
)
option(
'default-options',
type: 'string',
value: '',
description: 'Default XKB options',
)
option(
'enable-x11',
type: 'boolean',
value: true,
description: 'Enable building the xkbcommon-x11 library',
)
option(
'enable-docs',
type: 'boolean',
value: true,
description: 'Enable building the documentation',
)
option(
'enable-wayland',
type: 'boolean',
value: true,
description: 'Enable support for Wayland utility programs',
)
option(
'enable-xkbregistry',
type: 'boolean',
value: true,
description: 'Enable building libxkbregistry',
)

View File

@ -0,0 +1,8 @@
#!/bin/sh
# Run doxygen such that the working directory is the source root.
# This is needed for various reasons (e.g. relative references in md files).
# Do not use directly.
DOXYGEN="$1"
DOXYFILE="$2"
ABS_TOP_SRCDIR="$3"
cd "$ABS_TOP_SRCDIR" && exec "$DOXYGEN" "$DOXYFILE"

View File

@ -0,0 +1,52 @@
#!/usr/bin/env python
from __future__ import print_function
import re
import os
# expected format:
# #define XF86XK_FooBar _EVDEVK(0x123) /* some optional comment */
evdev_pattern = re.compile(r'^#define\s+XF86XK_(?P<name>\w+)\s+_EVDEVK\((?P<value>0x[0-9A-Fa-f]+)\)')
prefix = os.environ.get('X11_HEADERS_PREFIX', '/usr')
HEADERS = [
prefix + '/include/X11/keysymdef.h',
prefix + '/include/X11/XF86keysym.h',
prefix + '/include/X11/Sunkeysym.h',
prefix + '/include/X11/DECkeysym.h',
prefix + '/include/X11/HPkeysym.h',
]
print('''#ifndef _XKBCOMMON_KEYSYMS_H
#define _XKBCOMMON_KEYSYMS_H
/* This file is autogenerated; please do not commit directly. */
#define XKB_KEY_NoSymbol 0x000000 /* Special KeySym */
''')
for path in HEADERS:
with open(path) as header:
for line in header:
if '#ifdef' in line or '#ifndef' in line or '#endif' in line:
continue
# Remove #define _OSF_Keysyms and such.
if '#define _' in line:
continue
# Handle a duplicate definition in HPkeysyms.h which kicks in if
# it's not already defined.
if 'XK_Ydiaeresis' in line and '0x100000ee' in line:
continue
# Replace the xorgproto _EVDEVK macro with the actual value
# 0x10081000 is the base, the evdev hex code is added to that.
# We replace to make parsing of the keys later easier.
match = re.match(evdev_pattern, line)
if match:
value = 0x10081000 + int(match.group('value'), 16)
line = re.sub(r'_EVDEVK\(0x([0-9A-Fa-f]+)\)', '{:#x}'.format(value), line)
line = re.sub(r'#define\s*(\w*)XK_', r'#define XKB_KEY_\1', line)
print(line, end='')
print('\n\n#endif')

View File

@ -2,10 +2,15 @@
import re, sys, itertools
import perfect_hash
pattern = re.compile(r'^#define\s+XKB_KEY_(?P<name>\w+)\s+(?P<value>0x[0-9a-fA-F]+)\s')
matches = [pattern.match(line) for line in open(sys.argv[1])]
entries = [(m.group("name"), int(m.group("value"), 16)) for m in matches if m]
entries_isorted = sorted(entries, key=lambda e: e[0].lower())
entries_kssorted = sorted(entries, key=lambda e: e[1])
print('''
/**
* This file comes from libxkbcommon and was generated by makekeys.py
@ -17,20 +22,53 @@ print('''
entry_offsets = {}
print('''
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Woverlength-strings"
#endif
static const char *keysym_names =
'''.strip())
offs = 0
for (name, _) in sorted(entries, key=lambda e: e[0].lower()):
for (name, _) in entries_isorted:
entry_offsets[name] = offs
print(' "{name}\\0"'.format(name=name))
offs += len(name) + 1
print('''
;
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
'''.strip())
template = r'''
static const uint16_t keysym_name_G[] = {
$G
};
static size_t
keysym_name_hash_f(const char *key, const char *T)
{
size_t sum = 0;
for (size_t i = 0; key[i] != '\0'; i++)
sum += T[i % $NS] * key[i];
return sum % $NG;
}
static size_t
keysym_name_perfect_hash(const char *key)
{
return (
keysym_name_G[keysym_name_hash_f(key, "$S1")] +
keysym_name_G[keysym_name_hash_f(key, "$S2")]
) % $NG;
}
'''
print(perfect_hash.generate_code(
keys=[name for name, value in entries_isorted],
template=template,
))
print('''
struct name_keysym {
xkb_keysym_t keysym;
@ -42,10 +80,10 @@ def print_entries(x):
print(' {{ 0x{value:08x}, {offs} }}, /* {name} */'.format(offs=entry_offsets[name], value=value, name=name))
print('static const struct name_keysym name_to_keysym[] = {')
print_entries(sorted(entries, key=lambda e: e[0].lower()))
print_entries(entries_isorted)
print('};\n')
# *.sort() is stable so we always get the first keysym for duplicate
print('static const struct name_keysym keysym_to_name[] = {')
print_entries(next(g[1]) for g in itertools.groupby(sorted(entries, key=lambda e: e[1]), key=lambda e: e[1]))
print_entries(next(g[1]) for g in itertools.groupby(entries_kssorted, key=lambda e: e[1]))
print('};')

View File

@ -0,0 +1,30 @@
#!/usr/bin/env python
"""A script to generate MSVC Module-Definition files from version-script
files (which are maintained manually)."""
import re
import sys
import pathlib
def symbols_from_map(path):
return re.findall(r'^\s+(r?xkb_.*);', path.read_text('utf-8'), re.MULTILINE)
if 2 > len(sys.argv) > 3:
raise SystemExit("Usage: {} file.map [file.def]".format(sys.argv[0]))
map_file = pathlib.Path(sys.argv[1])
map_symbols = set(symbols_from_map(map_file))
if len(sys.argv) == 3:
def_file = open(sys.argv[2], "w", encoding="utf-8")
else:
def_file = sys.stdout
def_file.write("LIBRARY {}\n".format(map_file.stem))
def_file.write("EXPORTS\n")
for symbol in sorted(map_symbols):
def_file.write("\t{}\n".format(symbol))

View File

@ -0,0 +1,674 @@
# Derived from: https://github.com/ilanschnell/perfect-hash
# Commit: 6b7dd80a525dbd4349ea2c69f04a9c96f3c2fd54
# BSD 3-Clause License
#
# Copyright (c) 2019 - 2021, Ilan Schnell
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the Ilan Schnell nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL ILAN SCHNELL BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
Generate a minimal perfect hash function for the keys in a file,
desired hash values may be specified within this file as well.
A given code template is filled with parameters, such that the
output is code which implements the hash function.
Templates can easily be constructed for any programming language.
The code is based on an a program A.M. Kuchling wrote:
http://www.amk.ca/python/code/perfect-hash
The algorithm the program uses is described in the paper
'Optimal algorithms for minimal perfect hashing',
Z. J. Czech, G. Havas and B.S. Majewski.
http://citeseer.ist.psu.edu/122364.html
The algorithm works like this:
1. You have K keys, that you want to perfectly hash against some
desired hash values.
2. Choose a number N larger than K. This is the number of
vertices in a graph G, and also the size of the resulting table G.
3. Pick two random hash functions f1, f2, that return values from 0..N-1.
4. Now, for all keys, you draw an edge between vertices f1(key) and f2(key)
of the graph G, and associate the desired hash value with that edge.
5. If G is cyclic, go back to step 2.
6. Assign values to each vertex such that, for each edge, you can add
the values for the two vertices and get the desired (hash) value
for that edge. This task is easy, because the graph is acyclic.
This is done by picking a vertex, and assigning it a value of 0.
Then do a depth-first search, assigning values to new vertices so that
they sum up properly.
7. f1, f2, and vertex values of G now make up a perfect hash function.
For simplicity, the implementation of the algorithm combines steps 5 and 6.
That is, we check for loops in G and assign the vertex values in one procedure.
If this procedure succeeds, G is acyclic and the vertex values are assigned.
If the procedure fails, G is cyclic, and we go back to step 2, replacing G
with a new graph, and thereby discarding the vertex values from the failed
attempt.
"""
from __future__ import absolute_import, division, print_function
import sys
import random
import string
import subprocess
import shutil
import tempfile
from collections import defaultdict
from os.path import join
if sys.version_info[0] == 2:
from cStringIO import StringIO
else:
from io import StringIO
__version__ = '0.4.2'
verbose = False
trials = 150
class Graph(object):
"""
Implements a graph with 'N' vertices. First, you connect the graph with
edges, which have a desired value associated. Then the vertex values
are assigned, which will fail if the graph is cyclic. The vertex values
are assigned such that the two values corresponding to an edge add up to
the desired edge value (mod N).
"""
def __init__(self, N):
self.N = N # number of vertices
# maps a vertex number to the list of tuples (vertex, edge value)
# to which it is connected by edges.
self.adjacent = defaultdict(list)
def connect(self, vertex1, vertex2, edge_value):
"""
Connect 'vertex1' and 'vertex2' with an edge, with associated
value 'value'
"""
# Add vertices to each other's adjacent list
self.adjacent[vertex1].append((vertex2, edge_value))
self.adjacent[vertex2].append((vertex1, edge_value))
def assign_vertex_values(self):
"""
Try to assign the vertex values, such that, for each edge, you can
add the values for the two vertices involved and get the desired
value for that edge, i.e. the desired hash key.
This will fail when the graph is cyclic.
This is done by a Depth-First Search of the graph. If the search
finds a vertex that was visited before, there's a loop and False is
returned immediately, i.e. the assignment is terminated.
On success (when the graph is acyclic) True is returned.
"""
self.vertex_values = self.N * [-1] # -1 means unassigned
visited = self.N * [False]
# Loop over all vertices, taking unvisited ones as roots.
for root in range(self.N):
if visited[root]:
continue
# explore tree starting at 'root'
self.vertex_values[root] = 0 # set arbitrarily to zero
# Stack of vertices to visit, a list of tuples (parent, vertex)
tovisit = [(None, root)]
while tovisit:
parent, vertex = tovisit.pop()
visited[vertex] = True
# Loop over adjacent vertices, but skip the vertex we arrived
# here from the first time it is encountered.
skip = True
for neighbor, edge_value in self.adjacent[vertex]:
if skip and neighbor == parent:
skip = False
continue
if visited[neighbor]:
# We visited here before, so the graph is cyclic.
return False
tovisit.append((vertex, neighbor))
# Set new vertex's value to the desired edge value,
# minus the value of the vertex we came here from.
self.vertex_values[neighbor] = (
edge_value - self.vertex_values[vertex]) % self.N
# check if all vertices have a valid value
for vertex in range(self.N):
assert self.vertex_values[vertex] >= 0
# We got though, so the graph is acyclic,
# and all values are now assigned.
return True
class StrSaltHash(object):
"""
Random hash function generator.
Simple byte level hashing: each byte is multiplied to another byte from
a random string of characters, summed up, and finally modulo NG is
taken.
"""
chars = string.ascii_letters + string.digits
def __init__(self, N):
self.N = N
self.salt = ''
def __call__(self, key):
# XXX: xkbcommon modification: make the salt length a power of 2
# so that the % operation in the hash is fast.
while len(self.salt) < max(len(key), 32): # add more salt as necessary
self.salt += random.choice(self.chars)
return sum(ord(self.salt[i]) * ord(c)
for i, c in enumerate(key)) % self.N
template = """
def hash_f(key, T):
return sum(ord(T[i % $NS]) * ord(c) for i, c in enumerate(key)) % $NG
def perfect_hash(key):
return (G[hash_f(key, "$S1")] +
G[hash_f(key, "$S2")]) % $NG
"""
class IntSaltHash(object):
"""
Random hash function generator.
Simple byte level hashing, each byte is multiplied in sequence to a table
containing random numbers, summed tp, and finally modulo NG is taken.
"""
def __init__(self, N):
self.N = N
self.salt = []
def __call__(self, key):
while len(self.salt) < len(key): # add more salt as necessary
self.salt.append(random.randint(1, self.N - 1))
return sum(self.salt[i] * ord(c)
for i, c in enumerate(key)) % self.N
template = """
S1 = [$S1]
S2 = [$S2]
assert len(S1) == len(S2) == $NS
def hash_f(key, T):
return sum(T[i % $NS] * ord(c) for i, c in enumerate(key)) % $NG
def perfect_hash(key):
return (G[hash_f(key, S1)] + G[hash_f(key, S2)]) % $NG
"""
def builtin_template(Hash):
return """\
# =======================================================================
# ================= Python code for perfect hash function ===============
# =======================================================================
G = [$G]
""" + Hash.template + """
# ============================ Sanity check =============================
K = [$K]
assert len(K) == $NK
for h, k in enumerate(K):
assert perfect_hash(k) == h
"""
class TooManyInterationsError(Exception):
pass
def generate_hash(keys, Hash=StrSaltHash):
"""
Return hash functions f1 and f2, and G for a perfect minimal hash.
Input is an iterable of 'keys', whos indicies are the desired hash values.
'Hash' is a random hash function generator, that means Hash(N) returns a
returns a random hash function which returns hash values from 0..N-1.
"""
if not isinstance(keys, (list, tuple)):
raise TypeError("list or tuple expected")
NK = len(keys)
if NK != len(set(keys)):
raise ValueError("duplicate keys")
for key in keys:
if not isinstance(key, str):
raise TypeError("key a not string: %r" % key)
if NK > 10000 and Hash == StrSaltHash:
print("""\
WARNING: You have %d keys.
Using --hft=1 is likely to fail for so many keys.
Please use --hft=2 instead.
""" % NK)
# the number of vertices in the graph G
NG = NK + 1
if verbose:
print('NG = %d' % NG)
trial = 0 # Number of trial graphs so far
while True:
if (trial % trials) == 0: # trials failures, increase NG slightly
if trial > 0:
NG = max(NG + 1, int(1.05 * NG))
if verbose:
sys.stdout.write('\nGenerating graphs NG = %d ' % NG)
trial += 1
if NG > 100 * (NK + 1):
raise TooManyInterationsError("%d keys" % NK)
if verbose:
sys.stdout.write('.')
sys.stdout.flush()
G = Graph(NG) # Create graph with NG vertices
f1 = Hash(NG) # Create 2 random hash functions
f2 = Hash(NG)
# Connect vertices given by the values of the two hash functions
# for each key. Associate the desired hash value with each edge.
for hashval, key in enumerate(keys):
G.connect(f1(key), f2(key), hashval)
# Try to assign the vertex values. This will fail when the graph
# is cyclic. But when the graph is acyclic it will succeed and we
# break out, because we're done.
if G.assign_vertex_values():
break
if verbose:
print('\nAcyclic graph found after %d trials.' % trial)
print('NG = %d' % NG)
# Sanity check the result by actually verifying that all the keys
# hash to the right value.
for hashval, key in enumerate(keys):
assert hashval == (
G.vertex_values[f1(key)] + G.vertex_values[f2(key)]
) % NG
if verbose:
print('OK')
return f1, f2, G.vertex_values
class Format(object):
def __init__(self, width=76, indent=4, delimiter=', '):
self.width = width
self.indent = indent
self.delimiter = delimiter
def print_format(self):
print("Format options:")
for name in 'width', 'indent', 'delimiter':
print(' %s: %r' % (name, getattr(self, name)))
def __call__(self, data, quote=False):
if not isinstance(data, (list, tuple)):
return str(data)
lendel = len(self.delimiter)
aux = StringIO()
pos = 20
for i, elt in enumerate(data):
last = bool(i == len(data) - 1)
s = ('"%s"' if quote else '%s') % elt
if pos + len(s) + lendel > self.width:
aux.write('\n' + (self.indent * ' '))
pos = self.indent
aux.write(s)
pos += len(s)
if not last:
aux.write(self.delimiter)
pos += lendel
return '\n'.join(l.rstrip() for l in aux.getvalue().split('\n'))
def generate_code(keys, Hash=StrSaltHash, template=None, options=None):
"""
Takes a list of key value pairs and inserts the generated parameter
lists into the 'template' string. 'Hash' is the random hash function
generator, and the optional keywords are formating options.
The return value is the substituted code template.
"""
f1, f2, G = generate_hash(keys, Hash)
assert f1.N == f2.N == len(G)
try:
salt_len = len(f1.salt)
assert salt_len == len(f2.salt)
except TypeError:
salt_len = None
if template is None:
template = builtin_template(Hash)
if options is None:
fmt = Format()
else:
fmt = Format(width=options.width, indent=options.indent,
delimiter=options.delimiter)
if verbose:
fmt.print_format()
return string.Template(template).substitute(
NS = salt_len,
S1 = fmt(f1.salt),
S2 = fmt(f2.salt),
NG = len(G),
G = fmt(G),
NK = len(keys),
K = fmt(list(keys), quote=True))
def read_table(filename, options):
"""
Reads keys and desired hash value pairs from a file. If no column
for the hash value is specified, a sequence of hash values is generated,
from 0 to N-1, where N is the number of rows found in the file.
"""
if verbose:
print("Reading table from file `%s' to extract keys." % filename)
try:
fi = open(filename)
except IOError:
sys.exit("Error: Could not open `%s' for reading." % filename)
keys = []
if verbose:
print("Reader options:")
for name in 'comment', 'splitby', 'keycol':
print(' %s: %r' % (name, getattr(options, name)))
for n, line in enumerate(fi):
line = line.strip()
if not line or line.startswith(options.comment):
continue
if line.count(options.comment): # strip content after comment
line = line.split(options.comment)[0].strip()
row = [col.strip() for col in line.split(options.splitby)]
try:
key = row[options.keycol - 1]
except IndexError:
sys.exit("%s:%d: Error: Cannot read key, not enough columns." %
(filename, n + 1))
keys.append(key)
fi.close()
if not keys:
exit("Error: no keys found in file `%s'." % filename)
return keys
def read_template(filename):
if verbose:
print("Reading template from file `%s'" % filename)
try:
with open(filename, 'r') as fi:
return fi.read()
except IOError:
sys.exit("Error: Could not open `%s' for reading." % filename)
def run_code(code):
tmpdir = tempfile.mkdtemp()
path = join(tmpdir, 't.py')
with open(path, 'w') as fo:
fo.write(code)
try:
subprocess.check_call([sys.executable, path])
except subprocess.CalledProcessError as e:
raise AssertionError(e)
finally:
shutil.rmtree(tmpdir)
def main():
from optparse import OptionParser
usage = "usage: %prog [options] KEYS_FILE [TMPL_FILE]"
description = """\
Generates code for perfect hash functions from
a file with keywords and a code template.
If no template file is provided, a small built-in Python template
is processed and the output code is written to stdout.
"""
parser = OptionParser(usage = usage,
description = description,
prog = sys.argv[0],
version = "%prog: " + __version__)
parser.add_option("--delimiter",
action = "store",
default = ", ",
help = "Delimiter for list items used in output, "
"the default delimiter is '%default'",
metavar = "STR")
parser.add_option("--indent",
action = "store",
default = 4,
type = "int",
help = "Make INT spaces at the beginning of a "
"new line when generated list is wrapped. "
"Default is %default",
metavar = "INT")
parser.add_option("--width",
action = "store",
default = 76,
type = "int",
help = "Maximal width of generated list when "
"wrapped. Default width is %default",
metavar = "INT")
parser.add_option("--comment",
action = "store",
default = "#",
help = "STR is the character, or sequence of "
"characters, which marks the beginning "
"of a comment (which runs till "
"the end of the line), in the input "
"KEYS_FILE. "
"Default is '%default'",
metavar = "STR")
parser.add_option("--splitby",
action = "store",
default = ",",
help = "STR is the character by which the columns "
"in the input KEYS_FILE are split. "
"Default is '%default'",
metavar = "STR")
parser.add_option("--keycol",
action = "store",
default = 1,
type = "int",
help = "Specifies the column INT in the input "
"KEYS_FILE which contains the keys. "
"Default is %default, i.e. the first column.",
metavar = "INT")
parser.add_option("--trials",
action = "store",
default = 5,
type = "int",
help = "Specifies the number of trials before "
"NG is increased. A small INT will give "
"compute faster, but the array G will be "
"large. A large INT will take longer to "
"compute but G will be smaller. "
"Default is %default",
metavar = "INT")
parser.add_option("--hft",
action = "store",
default = 1,
type = "int",
help = "Hash function type INT. Possible values "
"are 1 (StrSaltHash) and 2 (IntSaltHash). "
"The default is %default",
metavar = "INT")
parser.add_option("-e", "--execute",
action = "store_true",
help = "Execute the generated code within "
"the Python interpreter.")
parser.add_option("-o", "--output",
action = "store",
help = "Specify output FILE explicitly. "
"`-o std' means standard output. "
"`-o no' means no output. "
"By default, the file name is obtained "
"from the name of the template file by "
"substituting `tmpl' to `code'.",
metavar = "FILE")
parser.add_option("-v", "--verbose",
action = "store_true",
help = "verbosity")
options, args = parser.parse_args()
if options.trials <= 0:
parser.error("trials before increasing N has to be larger than zero")
global trials
trials = options.trials
global verbose
verbose = options.verbose
if len(args) not in (1, 2):
parser.error("incorrect number of arguments")
if len(args) == 2 and not args[1].count('tmpl'):
parser.error("template filename does not contain 'tmpl'")
if options.hft == 1:
Hash = StrSaltHash
elif options.hft == 2:
Hash = IntSaltHash
else:
parser.error("Hash function %s not implemented." % options.hft)
# --------------------- end parsing and checking --------------
keys_file = args[0]
if verbose:
print("keys_file = %r" % keys_file)
keys = read_table(keys_file, options)
if verbose:
print("Number os keys: %d" % len(keys))
tmpl_file = args[1] if len(args) == 2 else None
if verbose:
print("tmpl_file = %r" % tmpl_file)
template = read_template(tmpl_file) if tmpl_file else None
if options.output:
outname = options.output
else:
if tmpl_file:
if 'tmpl' not in tmpl_file:
sys.exit("Hmm, template filename does not contain 'tmpl'")
outname = tmpl_file.replace('tmpl', 'code')
else:
outname = 'std'
if verbose:
print("outname = %r\n" % outname)
if outname == 'std':
outstream = sys.stdout
elif outname == 'no':
outstream = None
else:
try:
outstream = open(outname, 'w')
except IOError:
sys.exit("Error: Could not open `%s' for writing." % outname)
code = generate_code(keys, Hash, template, options)
if options.execute or template == builtin_template(Hash):
if verbose:
print('Executing code...\n')
run_code(code)
if outstream:
outstream.write(code)
if not outname == 'std':
outstream.close()
if __name__ == '__main__':
main()

View File

@ -0,0 +1,6 @@
#!/bin/sh
# Run this to regenerate xkbcommon-keysyms.h from the X11 headers
# defining the keysyms and update the name <-> keysym mapping.
export LC_CTYPE=C
scripts/makeheader > include/xkbcommon/xkbcommon-keysyms.h
scripts/makekeys include/xkbcommon/xkbcommon-keysyms.h > src/ks_tables.h

View File

@ -0,0 +1,4 @@
#!/bin/sh
# Run this if you add/remove a new keyword to the xkbcomp scanner,
# or just want to regenerate the gperf file.
gperf < src/xkbcomp/keywords.gperf > src/xkbcomp/keywords.c

View File

@ -70,33 +70,53 @@
*
********************************************************/
#include "utils.h"
#include "config.h"
#include <assert.h>
#include <inttypes.h>
#include <stdbool.h>
#include <string.h>
#include "atom.h"
#include "darray.h"
#include "utils.h"
struct atom_node {
xkb_atom_t left, right;
xkb_atom_t atom;
unsigned int fingerprint;
char *string;
};
/* FNV-1a (http://www.isthe.com/chongo/tech/comp/fnv/). */
static inline uint32_t
hash_buf(const char *string, size_t len)
{
uint32_t hash = 2166136261u;
for (size_t i = 0; i < (len + 1) / 2; i++) {
hash ^= (uint8_t) string[i];
hash *= 0x01000193;
hash ^= (uint8_t) string[len - 1 - i];
hash *= 0x01000193;
}
return hash;
}
/*
* The atom table is an insert-only linear probing hash table
* mapping strings to atoms. Another array maps the atoms to
* strings. The atom value is the position in the strings array.
*/
struct atom_table {
xkb_atom_t root;
darray(struct atom_node) table;
xkb_atom_t *index;
size_t index_size;
darray(char *) strings;
};
struct atom_table *
atom_table_new(void)
{
struct atom_table *table;
table = calloc(1, sizeof(*table));
struct atom_table *table = calloc(1, sizeof(*table));
if (!table)
return NULL;
darray_init(table->table);
/* The original throw-away root is here, at the illegal atom 0. */
darray_resize0(table->table, 1);
darray_init(table->strings);
darray_append(table->strings, NULL);
table->index_size = 4;
table->index = calloc(table->index_size, sizeof(*table->index));
return table;
}
@ -104,122 +124,70 @@ atom_table_new(void)
void
atom_table_free(struct atom_table *table)
{
struct atom_node *node;
if (!table)
return;
darray_foreach(node, table->table)
free(node->string);
darray_free(table->table);
char **string;
darray_foreach(string, table->strings)
free(*string);
darray_free(table->strings);
free(table->index);
free(table);
}
const char *
atom_text(struct atom_table *table, xkb_atom_t atom)
{
if (atom == XKB_ATOM_NONE || atom >= darray_size(table->table))
return NULL;
return darray_item(table->table, atom).string;
}
static bool
find_atom_pointer(struct atom_table *table, const char *string, size_t len,
xkb_atom_t **atomp_out, unsigned int *fingerprint_out)
{
xkb_atom_t *atomp = &table->root;
unsigned int fingerprint = 0;
bool found = false;
for (size_t i = 0; i < (len + 1) / 2; i++) {
fingerprint = fingerprint * 27 + string[i];
fingerprint = fingerprint * 27 + string[len - 1 - i];
}
while (*atomp != XKB_ATOM_NONE) {
struct atom_node *node = &darray_item(table->table, *atomp);
if (fingerprint < node->fingerprint) {
atomp = &node->left;
}
else if (fingerprint > node->fingerprint) {
atomp = &node->right;
}
else {
/* Now start testing the strings. */
const int cmp = strncmp(string, node->string, len);
if (cmp < 0 || (cmp == 0 && len < strlen(node->string))) {
atomp = &node->left;
}
else if (cmp > 0) {
atomp = &node->right;
}
else {
found = true;
break;
}
}
}
if (fingerprint_out)
*fingerprint_out = fingerprint;
if (atomp_out)
*atomp_out = atomp;
return found;
assert(atom < darray_size(table->strings));
return darray_item(table->strings, atom);
}
xkb_atom_t
atom_lookup(struct atom_table *table, const char *string, size_t len)
atom_intern(struct atom_table *table, const char *string, size_t len, bool add)
{
xkb_atom_t *atomp;
if (darray_size(table->strings) > 0.80 * table->index_size) {
table->index_size *= 2;
table->index = realloc(table->index, table->index_size * sizeof(*table->index));
memset(table->index, 0, table->index_size * sizeof(*table->index));
for (size_t j = 1; j < darray_size(table->strings); j++) {
const char *s = darray_item(table->strings, j);
uint32_t hash = hash_buf(s, strlen(s));
for (size_t i = 0; i < table->index_size; i++) {
size_t index_pos = (hash + i) & (table->index_size - 1);
if (index_pos == 0)
continue;
if (!string)
return XKB_ATOM_NONE;
xkb_atom_t atom = table->index[index_pos];
if (atom == XKB_ATOM_NONE) {
table->index[index_pos] = j;
break;
}
}
}
}
if (!find_atom_pointer(table, string, len, &atomp, NULL))
return XKB_ATOM_NONE;
uint32_t hash = hash_buf(string, len);
for (size_t i = 0; i < table->index_size; i++) {
size_t index_pos = (hash + i) & (table->index_size - 1);
if (index_pos == 0)
continue;
return *atomp;
}
/*
* If steal is true, we do not strdup @string; therefore it must be
* dynamically allocated, NUL-terminated, not be free'd by the caller
* and not be used afterwards. Use to avoid some redundant allocations.
*/
xkb_atom_t
atom_intern(struct atom_table *table, const char *string, size_t len,
bool steal)
{
xkb_atom_t *atomp;
struct atom_node node;
unsigned int fingerprint;
if (!string)
return XKB_ATOM_NONE;
if (find_atom_pointer(table, string, len, &atomp, &fingerprint)) {
if (steal)
free(UNCONSTIFY(string));
return *atomp;
}
if (steal) {
node.string = UNCONSTIFY(string);
}
else {
node.string = strndup(string, len);
if (!node.string)
return XKB_ATOM_NONE;
}
node.left = node.right = XKB_ATOM_NONE;
node.fingerprint = fingerprint;
node.atom = darray_size(table->table);
/* Do this before the append, as it may realloc and change the offsets. */
*atomp = node.atom;
darray_append(table->table, node);
return node.atom;
xkb_atom_t existing_atom = table->index[index_pos];
if (existing_atom == XKB_ATOM_NONE) {
if (add) {
xkb_atom_t new_atom = darray_size(table->strings);
darray_append(table->strings, strndup(string, len));
table->index[index_pos] = new_atom;
return new_atom;
} else {
return XKB_ATOM_NONE;
}
}
const char *existing_value = darray_item(table->strings, existing_atom);
if (strncmp(existing_value, string, len) == 0 && existing_value[len] == '\0')
return existing_atom;
}
assert(!"couldn't find an empty slot during probing");
}

View File

@ -37,11 +37,7 @@ void
atom_table_free(struct atom_table *table);
xkb_atom_t
atom_lookup(struct atom_table *table, const char *string, size_t len);
xkb_atom_t
atom_intern(struct atom_table *table, const char *string, size_t len,
bool steal);
atom_intern(struct atom_table *table, const char *string, size_t len, bool add);
const char *
atom_text(struct atom_table *table, xkb_atom_t atom);

View File

@ -0,0 +1,7 @@
#define _GNU_SOURCE_ 1
#define DFLT_XKB_CONFIG_EXTRA_PATH "/data/data/com.termux/files/home/.termux.wayland/xkb/config"
#define DEFAULT_XKB_VARIANT "NULL"
#define DEFAULT_XKB_OPTIONS "NULL"

View File

@ -52,6 +52,8 @@ OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
#include "config.h"
#include <errno.h>
#include "utils.h"
@ -64,45 +66,6 @@ OR PERFORMANCE OF THIS SOFTWARE.
#define MAX_LHS_LEN 10
#define MAX_INCLUDE_DEPTH 5
#define KEYSYM_FROM_NAME_CACHE_SIZE 8
/*
* xkb_keysym_from_name() is fairly slow, because for internal reasons
* it must use strcasecmp().
* A small cache reduces about 20% from the compilation time of
* en_US.UTF-8/Compose.
*/
struct keysym_from_name_cache {
struct {
char name[64];
unsigned len;
xkb_keysym_t keysym;
} cache[KEYSYM_FROM_NAME_CACHE_SIZE];
unsigned next;
};
static xkb_keysym_t
cached_keysym_from_name(struct keysym_from_name_cache *cache,
const char *name, size_t len)
{
xkb_keysym_t keysym;
if (len >= sizeof(cache->cache[0].name))
return XKB_KEY_NoSymbol;
for (unsigned i = 0; i < KEYSYM_FROM_NAME_CACHE_SIZE; i++)
if (cache->cache[i].len == len &&
memcmp(cache->cache[i].name, name, len) == 0)
return cache->cache[i].keysym;
keysym = xkb_keysym_from_name(name, XKB_KEYSYM_NO_FLAGS);
strcpy(cache->cache[cache->next].name, name);
cache->cache[cache->next].len = len;
cache->cache[cache->next].keysym = keysym;
cache->next = (cache->next + 1) % KEYSYM_FROM_NAME_CACHE_SIZE;
return keysym;
}
/*
* Grammar adapted from libX11/modules/im/ximcp/imLcPrs.c.
* See also the XCompose(5) manpage.
@ -113,8 +76,9 @@ cached_keysym_from_name(struct keysym_from_name_cache *cache,
* COMMENT ::= "#" {<any character except null or newline>}
* LHS ::= EVENT { EVENT }
* EVENT ::= [MODIFIER_LIST] "<" keysym ">"
* MODIFIER_LIST ::= ("!" {MODIFIER} ) | "None"
* MODIFIER ::= ["~"] modifier_name
* MODIFIER_LIST ::= (["!"] {MODIFIER} ) | "None"
* MODIFIER ::= ["~"] MODIFIER_NAME
* MODIFIER_NAME ::= ("Ctrl"|"Lock"|"Caps"|"Shift"|"Alt"|"Meta")
* RHS ::= ( STRING | keysym | STRING keysym )
* STRING ::= '"' { CHAR } '"'
* CHAR ::= GRAPHIC_CHAR | ESCAPED_CHAR
@ -182,7 +146,7 @@ skip_more_whitespace_and_comments:
/* LHS Keysym. */
if (chr(s, '<')) {
while (peek(s) != '>' && !eol(s))
while (peek(s) != '>' && !eol(s) && !eof(s))
buf_append(s, next(s));
if (!chr(s, '>')) {
scanner_err(s, "unterminated keysym literal");
@ -354,108 +318,123 @@ struct production {
unsigned int len;
xkb_keysym_t keysym;
char string[256];
/* At least one of these is true. */
bool has_keysym;
bool has_string;
xkb_mod_mask_t mods;
/* The matching is as follows: (active_mods & modmask) == mods. */
xkb_mod_mask_t modmask;
xkb_mod_mask_t mods;
};
static uint32_t
add_node(struct xkb_compose_table *table, xkb_keysym_t keysym)
{
struct compose_node new = {
.keysym = keysym,
.next = 0,
.is_leaf = true,
};
darray_append(table->nodes, new);
return darray_size(table->nodes) - 1;
}
static void
add_production(struct xkb_compose_table *table, struct scanner *s,
const struct production *production)
{
unsigned lhs_pos;
uint32_t curr;
struct compose_node *node;
unsigned lhs_pos = 0;
uint16_t curr = darray_size(table->nodes) == 1 ? 0 : 1;
uint16_t *pptr = NULL;
struct compose_node *node = NULL;
curr = 0;
node = &darray_item(table->nodes, curr);
/* Warn before potentially going over the limit, discard silently after. */
if (darray_size(table->nodes) + production->len + MAX_LHS_LEN > MAX_COMPOSE_NODES)
scanner_warn(s, "too many sequences for one Compose file; will ignore further lines");
if (darray_size(table->nodes) + production->len >= MAX_COMPOSE_NODES)
return;
/*
* Insert the sequence to the trie, creating new nodes as needed.
* Insert the sequence to the ternary search tree, creating new nodes as
* needed.
*
* TODO: This can be sped up a bit by first trying the path that the
* previous production took, and only then doing the linear search
* through the trie levels. This will work because sequences in the
* Compose files are often clustered by a common prefix; especially
* in the 1st and 2nd keysyms, which is where the largest variation
* (thus, longest search) is.
* TODO: We insert in the order given, this means some inputs can create
* long O(n) chains, which results in total O(n^2) parsing time. We should
* ensure the tree is reasonably balanced somehow.
*/
for (lhs_pos = 0; lhs_pos < production->len; lhs_pos++) {
while (production->lhs[lhs_pos] != node->keysym) {
if (node->next == 0) {
uint32_t next = add_node(table, production->lhs[lhs_pos]);
/* Refetch since add_node could have realloc()ed. */
node = &darray_item(table->nodes, curr);
node->next = next;
}
while (true) {
const xkb_keysym_t keysym = production->lhs[lhs_pos];
const bool last = lhs_pos + 1 == production->len;
curr = node->next;
node = &darray_item(table->nodes, curr);
if (curr == 0) {
/*
* Create a new node and update the parent pointer to it.
* Update the pointer first because the append invalidates it.
*/
struct compose_node new = {
.keysym = keysym,
.lokid = 0,
.hikid = 0,
.internal = {
.eqkid = 0,
.is_leaf = false,
},
};
curr = darray_size(table->nodes);
if (pptr != NULL) {
*pptr = curr;
pptr = NULL;
}
darray_append(table->nodes, new);
}
if (lhs_pos + 1 == production->len)
break;
if (node->is_leaf) {
if (node->u.leaf.utf8 != 0 ||
node->u.leaf.keysym != XKB_KEY_NoSymbol) {
scanner_warn(s, "a sequence already exists which is a prefix of this sequence; overriding");
node->u.leaf.utf8 = 0;
node->u.leaf.keysym = XKB_KEY_NoSymbol;
}
{
uint32_t successor = add_node(table, production->lhs[lhs_pos + 1]);
/* Refetch since add_node could have realloc()ed. */
node = &darray_item(table->nodes, curr);
node->is_leaf = false;
node->u.successor = successor;
}
}
curr = node->u.successor;
node = &darray_item(table->nodes, curr);
}
if (!node->is_leaf) {
scanner_warn(s, "this compose sequence is a prefix of another; skipping line");
return;
}
if (node->u.leaf.utf8 != 0 || node->u.leaf.keysym != XKB_KEY_NoSymbol) {
if (streq(&darray_item(table->utf8, node->u.leaf.utf8),
production->string) &&
node->u.leaf.keysym == production->keysym) {
scanner_warn(s, "this compose sequence is a duplicate of another; skipping line");
if (keysym < node->keysym) {
pptr = &node->lokid;
curr = node->lokid;
} else if (keysym > node->keysym) {
pptr = &node->hikid;
curr = node->hikid;
} else if (!last) {
if (node->is_leaf) {
scanner_warn(s, "a sequence already exists which is a prefix of this sequence; overriding");
node->internal.eqkid = node->lokid = node->hikid = 0;
node->internal.is_leaf = false;
}
lhs_pos++;
pptr = &node->internal.eqkid;
curr = node->internal.eqkid;
} else {
if (node->is_leaf) {
bool same_string =
(node->leaf.utf8 == 0 && !production->has_string) ||
(
node->leaf.utf8 != 0 && production->has_string &&
streq(&darray_item(table->utf8, node->leaf.utf8),
production->string)
);
bool same_keysym =
(node->leaf.keysym == XKB_KEY_NoSymbol && !production->has_keysym) ||
(
node->leaf.keysym != XKB_KEY_NoSymbol && production->has_keysym &&
node->leaf.keysym == production->keysym
);
if (same_string && same_keysym) {
scanner_warn(s, "this compose sequence is a duplicate of another; skipping line");
return;
} else {
scanner_warn(s, "this compose sequence already exists; overriding");
}
} else if (node->internal.eqkid != 0) {
scanner_warn(s, "this compose sequence is a prefix of another; skipping line");
return;
}
node->is_leaf = true;
if (production->has_string) {
node->leaf.utf8 = darray_size(table->utf8);
darray_append_items(table->utf8, production->string,
strlen(production->string) + 1);
}
if (production->has_keysym) {
node->leaf.keysym = production->keysym;
}
return;
}
scanner_warn(s, "this compose sequence already exists; overriding");
}
if (production->has_string) {
node->u.leaf.utf8 = darray_size(table->utf8);
darray_append_items(table->utf8, production->string,
strlen(production->string) + 1);
}
if (production->has_keysym) {
node->u.leaf.keysym = production->keysym;
}
}
/* Should match resolve_modifier(). */
#define ALL_MODS_MASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3))
static xkb_mod_index_t
resolve_modifier(const char *name)
{
@ -488,7 +467,7 @@ do_include(struct xkb_compose_table *table, struct scanner *s,
{
FILE *file;
bool ok;
const char *string;
char *string;
size_t size;
struct scanner new_s;
@ -498,7 +477,7 @@ do_include(struct xkb_compose_table *table, struct scanner *s,
return false;
}
file = fopen(path, "r");
file = fopen(path, "rb");
if (!file) {
scanner_err(s, "failed to open included Compose file \"%s\": %s",
path, strerror(errno));
@ -531,7 +510,6 @@ parse(struct xkb_compose_table *table, struct scanner *s,
{
enum rules_token tok;
union lvalue val;
struct keysym_from_name_cache *cache = s->priv;
xkb_keysym_t keysym;
struct production production;
enum { MAX_ERRORS = 10 };
@ -587,15 +565,16 @@ lhs_tok:
}
goto rhs;
case TOK_IDENT:
if (!streq(val.string.str, "None")) {
scanner_err(s, "unrecognized identifier \"%s\"", val.string.str);
goto error;
if (streq(val.string.str, "None")) {
production.mods = 0;
production.modmask = ALL_MODS_MASK;
goto lhs_keysym;
}
production.mods = 0;
/* XXX Should only include the mods in resolve_mods(). */
production.modmask = 0xff;
goto lhs_keysym;
goto lhs_mod_list_tok;
case TOK_TILDE:
goto lhs_mod_list_tok;
case TOK_BANG:
production.modmask = ALL_MODS_MASK;
goto lhs_mod_list;
default:
goto lhs_keysym_tok;
@ -606,7 +585,7 @@ lhs_keysym:
lhs_keysym_tok:
switch (tok) {
case TOK_LHS_KEYSYM:
keysym = cached_keysym_from_name(cache, val.string.str, val.string.len);
keysym = xkb_keysym_from_name(val.string.str, XKB_KEYSYM_NO_FLAGS);
if (keysym == XKB_KEY_NoSymbol) {
scanner_err(s, "unrecognized keysym \"%s\" on left-hand side",
val.string.str);
@ -625,21 +604,22 @@ lhs_keysym_tok:
goto unexpected;
}
lhs_mod_list: {
lhs_mod_list:
tok = lex(s, &val);
lhs_mod_list_tok: {
bool tilde = false;
xkb_mod_index_t mod;
tok = lex(s, &val);
if (tok != TOK_TILDE && tok != TOK_IDENT)
goto lhs_keysym_tok;
if (tok == TOK_TILDE) {
tilde = true;
tok = lex(s, &val);
}
if (tok != TOK_IDENT) {
if (tilde || production.modmask == 0)
goto unexpected;
goto lhs_keysym_tok;
}
if (tok != TOK_IDENT)
goto unexpected;
mod = resolve_modifier(val.string.str);
if (mod == XKB_MOD_INVALID) {
@ -676,7 +656,7 @@ rhs:
production.has_string = true;
goto rhs;
case TOK_IDENT:
keysym = cached_keysym_from_name(cache, val.string.str, val.string.len);
keysym = xkb_keysym_from_name(val.string.str, XKB_KEYSYM_NO_FLAGS);
if (keysym == XKB_KEY_NoSymbol) {
scanner_err(s, "unrecognized keysym \"%s\" on right-hand side",
val.string.str);
@ -688,6 +668,7 @@ rhs:
}
production.keysym = keysym;
production.has_keysym = true;
/* fallthrough */
case TOK_END_OF_LINE:
if (!production.has_string && !production.has_keysym) {
scanner_warn(s, "right-hand side must have at least one of string or keysym; skipping line");
@ -728,9 +709,7 @@ parse_string(struct xkb_compose_table *table, const char *string, size_t len,
const char *file_name)
{
struct scanner s;
struct keysym_from_name_cache cache;
memset(&cache, 0, sizeof(cache));
scanner_init(&s, table->ctx, string, len, file_name, &cache);
scanner_init(&s, table->ctx, string, len, file_name, NULL);
if (!parse(table, &s, 0))
return false;
/* Maybe the allocator can use the excess space. */
@ -743,7 +722,7 @@ bool
parse_file(struct xkb_compose_table *table, FILE *file, const char *file_name)
{
bool ok;
const char *string;
char *string;
size_t size;
ok = map_file(file, &string, &size);

View File

@ -21,8 +21,11 @@
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include "utils.h"
#include "paths.h"
#include "utils.h"
enum resolve_name_direction {
LEFT_TO_RIGHT,
@ -52,8 +55,9 @@ resolve_name(const char *filename, enum resolve_name_direction direction,
const char *xlocaledir;
char path[512];
FILE *file;
const char *string, *end;
char *string;
size_t string_size;
const char *end;
const char *s, *left, *right;
char *match;
size_t left_len, right_len, name_len;
@ -64,7 +68,7 @@ resolve_name(const char *filename, enum resolve_name_direction direction,
if (ret < 0 || (size_t) ret >= sizeof(path))
return false;
file = fopen(path, "r");
file = fopen(path, "rb");
if (!file)
return false;
@ -139,35 +143,44 @@ resolve_locale(const char *locale)
return alias ? alias : strdup(locale);
}
const char *
char *
get_xcomposefile_path(void)
{
return secure_getenv("XCOMPOSEFILE");
return strdup_safe(secure_getenv("XCOMPOSEFILE"));
}
char *
get_xdg_xcompose_file_path(void)
{
const char *xdg_config_home;
const char *home;
xdg_config_home = secure_getenv("XDG_CONFIG_HOME");
if (!xdg_config_home || xdg_config_home[0] != '/') {
home = secure_getenv("HOME");
if (!home)
return NULL;
return asprintf_safe("%s/.config/XCompose", home);
}
return asprintf_safe("%s/XCompose", xdg_config_home);
}
char *
get_home_xcompose_file_path(void)
{
int ret;
const char *home;
char *path;
home = secure_getenv("HOME");
if (!home)
return NULL;
ret = asprintf(&path, "%s/.XCompose", home);
if (ret <0)
return NULL;
return path;
return asprintf_safe("%s/.XCompose", home);
}
char *
get_locale_compose_file_path(const char *locale)
{
int ret;
const char *xlocaledir;
char *resolved;
char *path;
@ -193,11 +206,9 @@ get_locale_compose_file_path(const char *locale)
path = resolved;
}
else {
xlocaledir = get_xlocaledir_path();
ret = asprintf(&path, "%s/%s", xlocaledir, resolved);
const char *xlocaledir = get_xlocaledir_path();
path = asprintf_safe("%s/%s", xlocaledir, resolved);
free(resolved);
if (ret < 0)
return NULL;
}
return path;

View File

@ -30,9 +30,12 @@ resolve_locale(const char *locale);
const char *
get_xlocaledir_path(void);
const char *
char *
get_xcomposefile_path(void);
char *
get_xdg_xcompose_file_path(void);
char *
get_home_xcompose_file_path(void);

View File

@ -21,6 +21,8 @@
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include "table.h"
#include "utils.h"
#include "keysym.h"
@ -39,8 +41,8 @@ struct xkb_compose_state {
* This is also sufficient for inferring the current status; see
* xkb_compose_state_get_status().
*/
uint32_t prev_context;
uint32_t context;
uint16_t prev_context;
uint16_t context;
};
XKB_EXPORT struct xkb_compose_state *
@ -89,7 +91,7 @@ xkb_compose_state_get_compose_table(struct xkb_compose_state *state)
XKB_EXPORT enum xkb_compose_feed_result
xkb_compose_state_feed(struct xkb_compose_state *state, xkb_keysym_t keysym)
{
uint32_t context;
uint16_t context;
const struct compose_node *node;
/*
@ -107,17 +109,20 @@ xkb_compose_state_feed(struct xkb_compose_state *state, xkb_keysym_t keysym)
node = &darray_item(state->table->nodes, state->context);
context = (node->is_leaf ? 0 : node->u.successor);
node = &darray_item(state->table->nodes, context);
while (node->keysym != keysym && node->next != 0) {
context = node->next;
node = &darray_item(state->table->nodes, context);
}
if (node->keysym != keysym)
context = (node->is_leaf ? 1 : node->internal.eqkid);
if (context == 1 && darray_size(state->table->nodes) == 1)
context = 0;
while (context != 0) {
node = &darray_item(state->table->nodes, context);
if (keysym < node->keysym)
context = node->lokid;
else if (keysym > node->keysym)
context = node->hikid;
else
break;
}
state->prev_context = state->context;
state->context = context;
return XKB_COMPOSE_FEED_ACCEPTED;
@ -162,11 +167,11 @@ xkb_compose_state_get_utf8(struct xkb_compose_state *state,
/* If there's no string specified, but only a keysym, try to do the
* most helpful thing. */
if (node->u.leaf.utf8 == 0 && node->u.leaf.keysym != XKB_KEY_NoSymbol) {
if (node->leaf.utf8 == 0 && node->leaf.keysym != XKB_KEY_NoSymbol) {
char name[64];
int ret;
ret = xkb_keysym_to_utf8(node->u.leaf.keysym, name, sizeof(name));
ret = xkb_keysym_to_utf8(node->leaf.keysym, name, sizeof(name));
if (ret < 0 || ret == 0) {
/* ret < 0 is impossible.
* ret == 0 means the keysym has no string representation. */
@ -177,7 +182,7 @@ xkb_compose_state_get_utf8(struct xkb_compose_state *state,
}
return snprintf(buffer, size, "%s",
&darray_item(state->table->utf8, node->u.leaf.utf8));
&darray_item(state->table->utf8, node->leaf.utf8));
fail:
if (size > 0)
@ -192,5 +197,5 @@ xkb_compose_state_get_one_sym(struct xkb_compose_state *state)
&darray_item(state->table->nodes, state->context);
if (!node->is_leaf)
return XKB_KEY_NoSymbol;
return node->u.leaf.keysym;
return node->leaf.keysym;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright © 2013 Ran Benita <ran234@gmail.com>
* Copyright © 2013,2021 Ran Benita <ran234@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -21,6 +21,8 @@
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include "utils.h"
#include "table.h"
#include "parser.h"
@ -34,7 +36,7 @@ xkb_compose_table_new(struct xkb_context *ctx,
{
char *resolved_locale;
struct xkb_compose_table *table;
struct compose_node root;
struct compose_node dummy;
resolved_locale = resolve_locale(locale);
if (!resolved_locale)
@ -56,12 +58,11 @@ xkb_compose_table_new(struct xkb_context *ctx,
darray_init(table->nodes);
darray_init(table->utf8);
root.keysym = XKB_KEY_NoSymbol;
root.next = 0;
root.is_leaf = true;
root.u.leaf.utf8 = 0;
root.u.leaf.keysym = XKB_KEY_NoSymbol;
darray_append(table->nodes, root);
dummy.keysym = XKB_KEY_NoSymbol;
dummy.leaf.is_leaf = true;
dummy.leaf.utf8 = 0;
dummy.leaf.keysym = XKB_KEY_NoSymbol;
darray_append(table->nodes, dummy);
darray_append(table->utf8, '\0');
@ -159,8 +160,7 @@ xkb_compose_table_new_from_locale(struct xkb_context *ctx,
enum xkb_compose_compile_flags flags)
{
struct xkb_compose_table *table;
char *path = NULL;
const char *cpath;
char *path;
FILE *file;
bool ok;
@ -174,39 +174,48 @@ xkb_compose_table_new_from_locale(struct xkb_context *ctx,
if (!table)
return NULL;
cpath = get_xcomposefile_path();
if (cpath) {
file = fopen(cpath, "r");
if (file)
goto found_path;
}
cpath = path = get_home_xcompose_file_path();
path = get_xcomposefile_path();
if (path) {
file = fopen(path, "r");
file = fopen(path, "rb");
if (file)
goto found_path;
}
free(path);
path = NULL;
cpath = path = get_locale_compose_file_path(table->locale);
path = get_xdg_xcompose_file_path();
if (path) {
file = fopen(path, "r");
file = fopen(path, "rb");
if (file)
goto found_path;
}
free(path);
path = NULL;
log_err(ctx, "couldn't find a Compose file for locale \"%s\"\n", locale);
path = get_home_xcompose_file_path();
if (path) {
file = fopen(path, "rb");
if (file)
goto found_path;
}
free(path);
path = get_locale_compose_file_path(table->locale);
if (path) {
file = fopen(path, "rb");
if (file)
goto found_path;
}
free(path);
log_err(ctx, "couldn't find a Compose file for locale \"%s\" (mapped to \"%s\")\n",
locale, table->locale);
xkb_compose_table_unref(table);
return NULL;
found_path:
ok = parse_file(table, file, cpath);
ok = parse_file(table, file, path);
fclose(file);
if (!ok) {
free(path);
xkb_compose_table_unref(table);
return NULL;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright © 2013 Ran Benita <ran234@gmail.com>
* Copyright © 2013,2021 Ran Benita <ran234@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -29,36 +29,43 @@
#include "context.h"
/*
* The compose table data structure is a simple trie. An example will
* help. Given these sequences:
* The compose table data structure is a ternary search tree.
*
* <A> <B> : "first" dead_a
* <A> <C> <D> : "second" dead_b
* <E> <F> : "third" dead_c
* Reference: https://www.drdobbs.com/database/ternary-search-trees/184410528
* Visualization: https://www.cs.usfca.edu/~galles/visualization/TST.html
*
* the trie would look like:
* Short example. Given these sequences:
*
* <B> <C> : "first" dead_a
* <B> <D> <E> : "second" dead_b
* <A> <F> : "third" dead_c
*
* the tree would look like:
*
* -------- [<B>]---------
* | | #
* v V
* -- [<A>] -- [<C>] --------
* # | # | |
* v # -- [<D>] --
* -- [<F>] -- # | #
* # | # v
* # -- [<E>] --
* # | #
* #
*
* [root] ---> [<A>] -----------------> [<E>] -#
* | | |
* # v v
* [<B>] ---> [<C>] -# [<F>] -#
* | | -
* # v #
* [<D>] -#
* |
* #
* where:
* - [root] is a special empty root node.
* - [<X>] is a node for a sequence keysym <X>.
* - right arrows are `next` pointers.
* - down arrows are `successor` pointers.
* - right arrows are `hikid` pointers.
* - left arrows are `lokid` pointers.
* - down arrows are `eqkid` pointers.
* - # is a nil pointer.
*
* The nodes are all kept in a contiguous array. Pointers are represented
* as integer offsets into this array. A nil pointer is represented as 0
* (which, helpfully, is the offset of the empty root node).
* (which, helpfully, is the offset of an empty dummy node).
*
* Nodes without a successor are leaf nodes. Since a sequence cannot be a
* Nodes without an eqkid are leaf nodes. Since a sequence cannot be a
* prefix of another, these are exactly the nodes which terminate the
* sequences (in a bijective manner).
*
@ -68,21 +75,35 @@
* \0 is so offset 0 points to an empty string).
*/
/* Fits in uint16_t, also a good idea to have some limit. */
#define MAX_COMPOSE_NODES 65535
struct compose_node {
xkb_keysym_t keysym;
/* Offset into xkb_compose_table::nodes. */
unsigned int next:31;
bool is_leaf:1;
/* Offset into xkb_compose_table::nodes or 0. */
uint16_t lokid;
/* Offset into xkb_compose_table::nodes or 0. */
uint16_t hikid;
union {
/* Offset into xkb_compose_table::nodes. */
uint32_t successor;
struct {
uint32_t _pad:31;
bool is_leaf:1;
};
struct {
uint32_t _pad:31;
bool is_leaf:1;
/* Offset into xkb_compose_table::nodes or 0. */
uint16_t eqkid;
} internal;
struct {
/* Offset into xkb_compose_table::utf8. */
uint32_t utf8;
uint32_t utf8:31;
bool is_leaf:1;
xkb_keysym_t keysym;
} leaf;
} u;
};
};
struct xkb_compose_table {

View File

@ -0,0 +1,7 @@
#define _GNU_SOURCE_ 1
#define DFLT_XKB_CONFIG_EXTRA_PATH "/data/data/com.termux/files/home/.termux.wayland/xkb/config"
#define DEFAULT_XKB_VARIANT "NULL"
#define DEFAULT_XKB_OPTIONS "NULL"

View File

@ -24,10 +24,11 @@
* Author: Daniel Stone <daniel@fooishbar.org>
*/
#include "config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include "xkbcommon/xkbcommon.h"
#include "utils.h"
@ -52,19 +53,13 @@ xkb_context_failed_include_path_get(struct xkb_context *ctx,
xkb_atom_t
xkb_atom_lookup(struct xkb_context *ctx, const char *string)
{
return atom_lookup(ctx->atom_table, string, strlen(string));
return atom_intern(ctx->atom_table, string, strlen(string), false);
}
xkb_atom_t
xkb_atom_intern(struct xkb_context *ctx, const char *string, size_t len)
{
return atom_intern(ctx->atom_table, string, len, false);
}
xkb_atom_t
xkb_atom_steal(struct xkb_context *ctx, char *string)
{
return atom_intern(ctx->atom_table, string, strlen(string), true);
return atom_intern(ctx->atom_table, string, len, true);
}
const char *
@ -104,14 +99,6 @@ xkb_context_get_buffer(struct xkb_context *ctx, size_t size)
return rtrn;
}
#ifndef DEFAULT_XKB_VARIANT
#define DEFAULT_XKB_VARIANT NULL
#endif
#ifndef DEFAULT_XKB_OPTIONS
#define DEFAULT_XKB_OPTIONS NULL
#endif
static const char *
xkb_context_get_default_rules(struct xkb_context *ctx)
{

View File

@ -24,10 +24,20 @@
* Author: Daniel Stone <daniel@fooishbar.org>
*/
#include "config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#ifdef _MSC_VER
# include <direct.h>
# include <io.h>
# ifndef S_ISDIR
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
# endif
#else
# include <unistd.h>
#endif
#include "xkbcommon/xkbcommon.h"
#include "utils.h"
@ -40,7 +50,7 @@ XKB_EXPORT int
xkb_context_include_path_append(struct xkb_context *ctx, const char *path)
{
struct stat stat_buf;
int err;
int err = ENOMEM;
char *tmp;
tmp = strdup(path);
@ -48,48 +58,85 @@ xkb_context_include_path_append(struct xkb_context *ctx, const char *path)
goto err;
err = stat(path, &stat_buf);
if (err != 0)
if (err != 0) {
err = errno;
goto err;
if (!S_ISDIR(stat_buf.st_mode))
}
if (!S_ISDIR(stat_buf.st_mode)) {
err = ENOTDIR;
goto err;
}
#if defined(HAVE_EACCESS)
if (eaccess(path, R_OK | X_OK) != 0)
if (!check_eaccess(path, R_OK | X_OK)) {
err = EACCES;
goto err;
#elif defined(HAVE_EUIDACCESS)
if (euidaccess(path, R_OK | X_OK) != 0)
goto err;
#endif
}
darray_append(ctx->includes, tmp);
log_dbg(ctx, "Include path added: %s\n", tmp);
return 1;
err:
darray_append(ctx->failed_includes, tmp);
log_dbg(ctx, "Include path failed: %s (%s)\n", tmp, strerror(err));
return 0;
}
const char *
xkb_context_include_path_get_extra_path(struct xkb_context *ctx)
{
const char *extra = secure_getenv("XKB_CONFIG_EXTRA_PATH");
return extra ? extra : DFLT_XKB_CONFIG_EXTRA_PATH;
}
const char *
xkb_context_include_path_get_system_path(struct xkb_context *ctx)
{
const char *root = secure_getenv("XKB_CONFIG_ROOT");
return root ? root : DFLT_XKB_CONFIG_ROOT;
}
/**
* Append the default include directories to the context.
*/
XKB_EXPORT int
xkb_context_include_path_append_default(struct xkb_context *ctx)
{
const char *home;
const char *home, *xdg, *root, *extra;
char *user_path;
int err;
int ret = 0;
ret |= xkb_context_include_path_append(ctx, DFLT_XKB_CONFIG_ROOT);
home = secure_getenv("HOME");
if (!home)
return ret;
err = asprintf(&user_path, "%s/.xkb", home);
if (err <= 0)
return ret;
ret |= xkb_context_include_path_append(ctx, user_path);
free(user_path);
xdg = secure_getenv("XDG_CONFIG_HOME");
if (xdg != NULL) {
user_path = asprintf_safe("%s/xkb", xdg);
if (user_path) {
ret |= xkb_context_include_path_append(ctx, user_path);
free(user_path);
}
} else if (home != NULL) {
/* XDG_CONFIG_HOME fallback is $HOME/.config/ */
user_path = asprintf_safe("%s/.config/xkb", home);
if (user_path) {
ret |= xkb_context_include_path_append(ctx, user_path);
free(user_path);
}
}
if (home != NULL) {
user_path = asprintf_safe("%s/.xkb", home);
if (user_path) {
ret |= xkb_context_include_path_append(ctx, user_path);
free(user_path);
}
}
extra = xkb_context_include_path_get_extra_path(ctx);
ret |= xkb_context_include_path_append(ctx, extra);
root = xkb_context_include_path_get_system_path(ctx);
ret |= xkb_context_include_path_append(ctx, root);
return ret;
}
@ -163,6 +210,7 @@ xkb_context_unref(struct xkb_context *ctx)
if (!ctx || --ctx->refcnt > 0)
return;
free(ctx->x11_atom_cache);
xkb_context_include_path_clear(ctx);
atom_table_free(ctx->atom_table);
free(ctx);
@ -276,6 +324,8 @@ xkb_context_new(enum xkb_context_flags flags)
return NULL;
}
ctx->x11_atom_cache = NULL;
return ctx;
}

View File

@ -45,6 +45,9 @@ struct xkb_context {
struct atom_table *atom_table;
/* Used and allocated by xkbcommon-x11, free()d with the context. */
void *x11_atom_cache;
/* Buffer for the *Text() functions. */
char text_buffer[2048];
size_t text_next;
@ -59,6 +62,12 @@ const char *
xkb_context_failed_include_path_get(struct xkb_context *ctx,
unsigned int idx);
const char *
xkb_context_include_path_get_extra_path(struct xkb_context *ctx);
const char *
xkb_context_include_path_get_system_path(struct xkb_context *ctx);
/*
* Returns XKB_ATOM_NONE if @string was not previously interned,
* otherwise returns the atom.
@ -101,14 +110,16 @@ xkb_context_sanitize_rule_names(struct xkb_context *ctx,
* format is supplied without arguments. Not supplying it would still
* result in an error, though.
*/
#define log_dbg(ctx, ...) \
xkb_log((ctx), XKB_LOG_LEVEL_DEBUG, 0, __VA_ARGS__)
#define log_info(ctx, ...) \
xkb_log((ctx), XKB_LOG_LEVEL_INFO, 0, __VA_ARGS__)
#define log_warn(ctx, ...) \
xkb_log((ctx), XKB_LOG_LEVEL_WARNING, 0, __VA_ARGS__)
xkb_log((ctx), XKB_LOG_LEVEL_WARNING, 0, __VA_ARGS__)
#define log_err(ctx, ...) \
xkb_log((ctx), XKB_LOG_LEVEL_ERROR, 0, __VA_ARGS__)
xkb_log((ctx), XKB_LOG_LEVEL_ERROR, 0, __VA_ARGS__)
#define log_wsgo(ctx, ...) \
xkb_log((ctx), XKB_LOG_LEVEL_CRITICAL, 0, __VA_ARGS__)
#define log_vrb(ctx, vrb, ...) \

View File

@ -23,7 +23,7 @@
#ifndef CCAN_DARRAY_H
#define CCAN_DARRAY_H
/* Originally taken from: http://ccodearchive.net/info/darray.html
/* Originally taken from: https://ccodearchive.net/info/darray.html
* But modified for libxkbcommon. */
#include <stdlib.h>
@ -104,12 +104,16 @@ typedef darray (unsigned long) darray_ulong;
#define darray_from_items(arr, items, count) do { \
unsigned __count = (count); \
darray_resize(arr, __count); \
memcpy((arr).item, items, __count * sizeof(*(arr).item)); \
if (__count != 0) \
memcpy((arr).item, items, __count * sizeof(*(arr).item)); \
} while (0)
#define darray_copy(arr_to, arr_from) \
darray_from_items((arr_to), (arr_from).item, (arr_from).size)
#define darray_concat(arr_to, arr_from) \
darray_append_items((arr_to), (arr_from).item, (arr_from).size)
/*** String buffer ***/
#define darray_append_string(arr, str) do { \
@ -202,4 +206,7 @@ darray_next_alloc(unsigned alloc, unsigned need, unsigned itemSize)
(idx) < (arr).size; \
(idx)++, (val)++)
#define darray_foreach_reverse(i, arr) \
for ((i) = &(arr).item[(arr).size - 1]; (arr).size > 0 && (i) >= &(arr).item[0]; (i)--)
#endif /* CCAN_DARRAY_H */

View File

@ -24,6 +24,8 @@
* Author: Daniel Stone <daniel@fooishbar.org>
*/
#include "config.h"
#include "keymap.h"
static void
@ -118,7 +120,8 @@ XkbEscapeMapName(char *name)
return;
while (*name) {
if (!(legal[*name / 8] & (1 << (*name % 8))))
unsigned char c = *name;
if (!(legal[c / 8] & (1 << (c % 8))))
*name = '_';
name++;
}
@ -137,3 +140,13 @@ XkbModNameToIndex(const struct xkb_mod_set *mods, xkb_atom_t name,
return XKB_MOD_INVALID;
}
bool
XkbLevelsSameSyms(const struct xkb_level *a, const struct xkb_level *b)
{
if (a->num_syms != b->num_syms)
return false;
if (a->num_syms <= 1)
return a->u.sym == b->u.sym;
return memcmp(a->u.syms, b->u.syms, sizeof(*a->u.syms) * a->num_syms) == 0;
}

View File

@ -50,6 +50,8 @@
*
* ********************************************************/
#include "config.h"
#include "keymap.h"
#include "text.h"
@ -407,6 +409,66 @@ xkb_keymap_led_get_index(struct xkb_keymap *keymap, const char *name)
return XKB_LED_INVALID;
}
XKB_EXPORT size_t
xkb_keymap_key_get_mods_for_level(struct xkb_keymap *keymap,
xkb_keycode_t kc,
xkb_layout_index_t layout,
xkb_level_index_t level,
xkb_mod_mask_t *masks_out,
size_t masks_size)
{
const struct xkb_key *key = XkbKey(keymap, kc);
if (!key)
return 0;
layout = XkbWrapGroupIntoRange(layout, key->num_groups,
key->out_of_range_group_action,
key->out_of_range_group_number);
if (layout == XKB_LAYOUT_INVALID)
return 0;
if (level >= XkbKeyNumLevels(key, layout))
return 0;
const struct xkb_key_type *type = key->groups[layout].type;
size_t count = 0;
/*
* If the active set of modifiers doesn't match any explicit entry of
* the key type, the resulting level is 0 (i.e. Level 1).
* So, if we are asked to find the modifiers for level==0, we can offer
* an ~infinite supply, which is not very workable.
* What we do instead, is special case the empty set of modifiers for
* this purpose. If the empty set isn't explicit mapped to a level, we
* take it to map to Level 1.
* This is almost always what we want. If applicable, given it priority
* over other ways to generate the level.
*/
if (level == 0) {
bool empty_mapped = false;
for (unsigned i = 0; i < type->num_entries && count < masks_size; i++)
if (entry_is_active(&type->entries[i]) &&
type->entries[i].mods.mask == 0) {
empty_mapped = true;
break;
}
if (!empty_mapped && count < masks_size) {
masks_out[count++] = 0;
}
}
/* Now search explicit mappings. */
for (unsigned i = 0; i < type->num_entries && count < masks_size; i++) {
if (entry_is_active(&type->entries[i]) &&
type->entries[i].level == level) {
masks_out[count++] = type->entries[i].mods.mask;
}
}
return count;
}
/**
* As below, but takes an explicit layout/level rather than state.
*/
@ -470,6 +532,40 @@ xkb_keymap_key_for_each(struct xkb_keymap *keymap, xkb_keymap_key_iter_t iter,
iter(keymap, key->keycode, data);
}
XKB_EXPORT const char *
xkb_keymap_key_get_name(struct xkb_keymap *keymap, xkb_keycode_t kc)
{
const struct xkb_key *key = XkbKey(keymap, kc);
if (!key)
return NULL;
return xkb_atom_text(keymap->ctx, key->name);
}
XKB_EXPORT xkb_keycode_t
xkb_keymap_key_by_name(struct xkb_keymap *keymap, const char *name)
{
struct xkb_key *key;
xkb_atom_t atom;
atom = xkb_atom_lookup(keymap->ctx, name);
if (atom) {
xkb_atom_t ratom = XkbResolveKeyAlias(keymap, atom);
if (ratom)
atom = ratom;
}
if (!atom)
return XKB_KEYCODE_INVALID;
xkb_keys_foreach(key, keymap) {
if (key->name == atom)
return key->keycode;
}
return XKB_KEYCODE_INVALID;
}
/**
* Simple boolean specifying whether or not the key should repeat.
*/

View File

@ -253,6 +253,7 @@ struct xkb_key_type {
xkb_atom_t name;
struct xkb_mods mods;
xkb_level_index_t num_levels;
unsigned int num_level_names;
xkb_atom_t *level_names;
unsigned int num_entries;
struct xkb_key_type_entry *entries;
@ -324,7 +325,7 @@ struct xkb_group {
bool explicit_type;
/* Points to a type in keymap->types. */
const struct xkb_key_type *type;
/* Use XkbKeyGroupWidth for the number of levels. */
/* Use XkbKeyNumLevels for the number of levels. */
struct xkb_level *levels;
};
@ -437,6 +438,17 @@ XkbKeyNumLevels(const struct xkb_key *key, xkb_layout_index_t layout)
return key->groups[layout].type->num_levels;
}
/*
* If the virtual modifiers are not bound to anything, the entry
* is not active and should be skipped. xserver does this with
* cached entry->active field.
*/
static inline bool
entry_is_active(const struct xkb_key_type_entry *entry)
{
return entry->mods.mods == 0 || entry->mods.mask != 0;
}
struct xkb_keymap *
xkb_keymap_new(struct xkb_context *ctx,
enum xkb_keymap_format format,
@ -455,6 +467,9 @@ xkb_mod_index_t
XkbModNameToIndex(const struct xkb_mod_set *mods, xkb_atom_t name,
enum mod_type type);
bool
XkbLevelsSameSyms(const struct xkb_level *a, const struct xkb_level *b);
xkb_layout_index_t
XkbWrapGroupIntoRange(int32_t group,
xkb_layout_index_t num_groups,

View File

@ -35,6 +35,8 @@
*
*/
#include "config.h"
#include "xkbcommon/xkbcommon.h"
#include "utils.h"
#include "utf8.h"
@ -521,7 +523,7 @@ static const struct codepair keysymtab[] = {
{ 0x0aa8, 0x200a }, /* hairspace HAIR SPACE */
{ 0x0aa9, 0x2014 }, /* emdash — EM DASH */
{ 0x0aaa, 0x2013 }, /* endash EN DASH */
/* 0x0aac signifblank ? ??? */
{ 0x0aac, 0x2423 }, /* signifblank ␣ OPEN BOX */
{ 0x0aae, 0x2026 }, /* ellipsis … HORIZONTAL ELLIPSIS */
{ 0x0aaf, 0x2025 }, /* doubbaselinedot ‥ TWO DOT LEADER */
{ 0x0ab0, 0x2153 }, /* onethird ⅓ VULGAR FRACTION ONE THIRD */
@ -534,9 +536,9 @@ static const struct codepair keysymtab[] = {
{ 0x0ab7, 0x215a }, /* fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */
{ 0x0ab8, 0x2105 }, /* careof ℅ CARE OF */
{ 0x0abb, 0x2012 }, /* figdash FIGURE DASH */
{ 0x0abc, 0x2329 }, /* leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */
{ 0x0abc, 0x27e8 }, /* leftanglebracket ⟨ MATHEMATICAL LEFT ANGLE BRACKET */
{ 0x0abd, 0x002e }, /* decimalpoint . FULL STOP */
{ 0x0abe, 0x232a }, /* rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */
{ 0x0abe, 0x27e9 }, /* rightanglebracket ⟩ MATHEMATICAL RIGHT ANGLE BRACKET */
/* 0x0abf marker ? ??? */
{ 0x0ac3, 0x215b }, /* oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */
{ 0x0ac4, 0x215c }, /* threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */
@ -554,6 +556,7 @@ static const struct codepair keysymtab[] = {
{ 0x0ad2, 0x201c }, /* leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */
{ 0x0ad3, 0x201d }, /* rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */
{ 0x0ad4, 0x211e }, /* prescription ℞ PRESCRIPTION TAKE */
{ 0x0ad5, 0x2030 }, /* permille ‰ PER MILLE SIGN */
{ 0x0ad6, 0x2032 }, /* minutes PRIME */
{ 0x0ad7, 0x2033 }, /* seconds ″ DOUBLE PRIME */
{ 0x0ad9, 0x271d }, /* latincross ✝ LATIN CROSS */
@ -611,8 +614,8 @@ static const struct codepair keysymtab[] = {
{ 0x0bd6, 0x222a }, /* downshoe UNION */
{ 0x0bd8, 0x2283 }, /* rightshoe ⊃ SUPERSET OF */
{ 0x0bda, 0x2282 }, /* leftshoe ⊂ SUBSET OF */
{ 0x0bdc, 0x22a2 }, /* lefttack ⊢ RIGHT TACK */
{ 0x0bfc, 0x22a3 }, /* righttack ⊣ LEFT TACK */
{ 0x0bdc, 0x22a3 }, /* lefttack ⊣ LEFT TACK */
{ 0x0bfc, 0x22a2 }, /* righttack ⊢ RIGHT TACK */
{ 0x0cdf, 0x2017 }, /* hebrew_doublelowline ‗ DOUBLE LOW LINE */
{ 0x0ce0, 0x05d0 }, /* hebrew_aleph א HEBREW LETTER ALEF */
{ 0x0ce1, 0x05d1 }, /* hebrew_bet ב HEBREW LETTER BET */
@ -807,7 +810,7 @@ static const struct codepair keysymtab[] = {
{ 0x0ef0, 0x3171 }, /* Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */
{ 0x0ef1, 0x3178 }, /* Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */
{ 0x0ef2, 0x317f }, /* Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */
/* 0x0ef3 Hangul_KkogjiDalrinIeung ? ??? */
{ 0x0ef3, 0x3181 }, /* Hangul_KkogjiDalrinIeung ㆁ HANGUL LETTER YESIEUNG */
{ 0x0ef4, 0x3184 }, /* Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */
{ 0x0ef5, 0x3186 }, /* Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */
{ 0x0ef6, 0x318d }, /* Hangul_AraeA ㆍ HANGUL LETTER ARAEA */
@ -880,14 +883,49 @@ xkb_keysym_to_utf32(xkb_keysym_t keysym)
keysym == XKB_KEY_KP_Enter || keysym == XKB_KEY_KP_Equal)
return keysym & 0x7f;
/* also check for directly encoded 24-bit UCS characters */
if ((keysym & 0xff000000) == 0x01000000)
return keysym & 0x00ffffff;
/* also check for directly encoded Unicode codepoints */
/*
* In theory, this is supposed to start from 0x100100, such that the ASCII
* range, which is already covered by 0x00-0xff, can't be encoded in two
* ways. However, changing this after a couple of decades probably won't
* go well, so it stays as it is.
*/
if (0x01000000 <= keysym && keysym <= 0x0110ffff)
return keysym - 0x01000000;
/* search main table */
return bin_search(keysymtab, ARRAY_SIZE(keysymtab) - 1, keysym);
}
XKB_EXPORT xkb_keysym_t
xkb_utf32_to_keysym(uint32_t ucs)
{
/* first check for Latin-1 characters (1:1 mapping) */
if ((ucs >= 0x0020 && ucs <= 0x007e) ||
(ucs >= 0x00a0 && ucs <= 0x00ff))
return ucs;
/* special keysyms */
if ((ucs >= (XKB_KEY_BackSpace & 0x7f) && ucs <= (XKB_KEY_Clear & 0x7f)) ||
ucs == (XKB_KEY_Return & 0x7f) || ucs == (XKB_KEY_Escape & 0x7f))
return ucs | 0xff00;
if (ucs == (XKB_KEY_Delete & 0x7f))
return XKB_KEY_Delete;
/* Unicode non-symbols and code points outside Unicode planes */
if ((ucs >= 0xfdd0 && ucs <= 0xfdef) ||
ucs > 0x10ffff || (ucs & 0xfffe) == 0xfffe)
return XKB_KEY_NoSymbol;
/* search main table */
for (size_t i = 0; i < ARRAY_SIZE(keysymtab); i++)
if (keysymtab[i].ucs == ucs)
return keysymtab[i].keysym;
/* Use direct encoding if everything else fails */
return ucs | 0x01000000;
}
/*
* Copyright © 2012 Intel Corporation
*

View File

@ -47,6 +47,8 @@
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include <stdlib.h>
#include "xkbcommon/xkbcommon.h"
#include "utils.h"
@ -59,42 +61,25 @@ get_name(const struct name_keysym *entry)
return keysym_names + entry->offset;
}
static int
compare_by_keysym(const void *a, const void *b)
{
const xkb_keysym_t *key = a;
const struct name_keysym *entry = b;
if (*key < entry->keysym)
return -1;
if (*key > entry->keysym)
return 1;
return 0;
}
static int
compare_by_name(const void *a, const void *b)
{
const char *key = a;
const struct name_keysym *entry = b;
return strcasecmp(key, get_name(entry));
}
XKB_EXPORT int
xkb_keysym_get_name(xkb_keysym_t ks, char *buffer, size_t size)
{
const struct name_keysym *entry;
if ((ks & ((unsigned long) ~0x1fffffff)) != 0) {
snprintf(buffer, size, "Invalid");
return -1;
}
entry = bsearch(&ks, keysym_to_name,
ARRAY_SIZE(keysym_to_name),
sizeof(*keysym_to_name),
compare_by_keysym);
if (entry)
return snprintf(buffer, size, "%s", get_name(entry));
int32_t lo = 0, hi = ARRAY_SIZE(keysym_to_name) - 1;
while (hi >= lo) {
int32_t mid = (lo + hi) / 2;
if (ks > keysym_to_name[mid].keysym) {
lo = mid + 1;
} else if (ks < keysym_to_name[mid].keysym) {
hi = mid - 1;
} else {
return snprintf(buffer, size, "%s", get_name(&keysym_to_name[mid]));
}
}
/* Unnamed Unicode codepoint. */
if (ks >= 0x01000100 && ks <= 0x0110ffff) {
@ -107,108 +92,135 @@ xkb_keysym_get_name(xkb_keysym_t ks, char *buffer, size_t size)
}
/*
* Find the correct keysym if one case-insensitive match is given.
*
* The name_to_keysym table is sorted by strcasecmp(). So bsearch() may return
* _any_ of all possible case-insensitive duplicates. This function searches the
* returned entry @entry, all previous and all next entries that match by
* case-insensitive comparison and returns the exact match to @name. If @icase
* is true, then this returns the best case-insensitive match instead of a
* correct match.
* The "best" case-insensitive match is the lower-case keysym which we find with
* the help of xkb_keysym_is_lower().
* The only keysyms that only differ by letter-case are keysyms that are
* available as lower-case and upper-case variant (like KEY_a and KEY_A). So
* returning the first lower-case match is enough in this case.
* Parse the numeric part of a 0xXXXX and UXXXX keysym.
* Not using strtoul -- it's slower and accepts a bunch of stuff
* we don't want to allow, like signs, spaces, even locale stuff.
*/
static const struct name_keysym *
find_sym(const struct name_keysym *entry, const char *name, bool icase)
static bool
parse_keysym_hex(const char *s, uint32_t *out)
{
const struct name_keysym *iter, *last;
size_t len = ARRAY_SIZE(name_to_keysym);
if (!entry)
return NULL;
if (!icase && strcmp(get_name(entry), name) == 0)
return entry;
if (icase && xkb_keysym_is_lower(entry->keysym))
return entry;
for (iter = entry - 1; iter >= name_to_keysym; --iter) {
if (!icase && strcmp(get_name(iter), name) == 0)
return iter;
if (strcasecmp(get_name(iter), get_name(entry)) != 0)
break;
if (icase && xkb_keysym_is_lower(iter->keysym))
return iter;
uint32_t result = 0;
int i;
for (i = 0; i < 8 && s[i] != '\0'; i++) {
result <<= 4;
if ('0' <= s[i] && s[i] <= '9')
result += s[i] - '0';
else if ('a' <= s[i] && s[i] <= 'f')
result += 10 + s[i] - 'a';
else if ('A' <= s[i] && s[i] <= 'F')
result += 10 + s[i] - 'A';
else
return false;
}
last = name_to_keysym + len;
for (iter = entry + 1; iter < last; ++iter) {
if (!icase && strcmp(get_name(iter), name) == 0)
return iter;
if (strcasecmp(get_name(iter), get_name(entry)) != 0)
break;
if (icase && xkb_keysym_is_lower(iter->keysym))
return iter;
}
if (icase)
return entry;
return NULL;
*out = result;
return s[i] == '\0' && i > 0;
}
XKB_EXPORT xkb_keysym_t
xkb_keysym_from_name(const char *s, enum xkb_keysym_flags flags)
xkb_keysym_from_name(const char *name, enum xkb_keysym_flags flags)
{
const struct name_keysym *entry;
const struct name_keysym *entry = NULL;
char *tmp;
xkb_keysym_t val;
uint32_t val;
bool icase = (flags & XKB_KEYSYM_CASE_INSENSITIVE);
if (flags & ~XKB_KEYSYM_CASE_INSENSITIVE)
return XKB_KEY_NoSymbol;
entry = bsearch(s, name_to_keysym,
ARRAY_SIZE(name_to_keysym),
sizeof(*name_to_keysym),
compare_by_name);
entry = find_sym(entry, s, icase);
if (entry)
return entry->keysym;
/*
* We need to !icase case to be fast, for e.g. Compose file parsing.
* So do it in a fast path.
*/
if (!icase) {
size_t pos = keysym_name_perfect_hash(name);
if (pos < ARRAY_SIZE(name_to_keysym)) {
const char *s = get_name(&name_to_keysym[pos]);
if (strcmp(name, s) == 0)
return name_to_keysym[pos].keysym;
}
}
/*
* Find the correct keysym for case-insensitive match.
*
* The name_to_keysym table is sorted by istrcmp(). So the binary
* search may return _any_ of all possible case-insensitive duplicates. This
* code searches the entry, all previous and all next entries that match by
* case-insensitive comparison and returns the "best" case-insensitive
* match.
*
* The "best" case-insensitive match is the lower-case keysym which we find
* with the help of xkb_keysym_is_lower(). The only keysyms that only differ
* by letter-case are keysyms that are available as lower-case and
* upper-case variant (like KEY_a and KEY_A). So returning the first
* lower-case match is enough in this case.
*/
else {
int32_t lo = 0, hi = ARRAY_SIZE(name_to_keysym) - 1;
while (hi >= lo) {
int32_t mid = (lo + hi) / 2;
int cmp = istrcmp(name, get_name(&name_to_keysym[mid]));
if (cmp > 0) {
lo = mid + 1;
} else if (cmp < 0) {
hi = mid - 1;
} else {
entry = &name_to_keysym[mid];
break;
}
}
if (entry) {
const struct name_keysym *iter, *last;
if (*s == 'U' || (icase && *s == 'u')) {
val = strtoul(&s[1], &tmp, 16);
if (tmp && *tmp != '\0')
if (icase && xkb_keysym_is_lower(entry->keysym))
return entry->keysym;
for (iter = entry - 1; iter >= name_to_keysym; --iter) {
if (istrcmp(get_name(iter), get_name(entry)) != 0)
break;
if (xkb_keysym_is_lower(iter->keysym))
return iter->keysym;
}
last = name_to_keysym + ARRAY_SIZE(name_to_keysym);
for (iter = entry + 1; iter < last; ++iter) {
if (istrcmp(get_name(iter), get_name(entry)) != 0)
break;
if (xkb_keysym_is_lower(iter->keysym))
return iter->keysym;
}
return entry->keysym;
}
}
if (*name == 'U' || (icase && *name == 'u')) {
if (!parse_keysym_hex(&name[1], &val))
return XKB_KEY_NoSymbol;
if (val < 0x20 || (val > 0x7e && val < 0xa0))
return XKB_KEY_NoSymbol;
if (val < 0x100)
return val;
return (xkb_keysym_t) val;
if (val > 0x10ffff)
return XKB_KEY_NoSymbol;
return val | 0x01000000;
return (xkb_keysym_t) val | 0x01000000;
}
else if (s[0] == '0' && (s[1] == 'x' || (icase && s[1] == 'X'))) {
val = strtoul(&s[2], &tmp, 16);
if (tmp && *tmp != '\0')
else if (name[0] == '0' && (name[1] == 'x' || (icase && name[1] == 'X'))) {
if (!parse_keysym_hex(&name[2], &val))
return XKB_KEY_NoSymbol;
return val;
return (xkb_keysym_t) val;
}
/* Stupid inconsistency between the headers and XKeysymDB: the former has
* no separating underscore, while some XF86* syms in the latter did.
* As a last ditch effort, try without. */
if (strncmp(s, "XF86_", 5) == 0 ||
(icase && strncasecmp(s, "XF86_", 5) == 0)) {
if (strncmp(name, "XF86_", 5) == 0 ||
(icase && istrncmp(name, "XF86_", 5) == 0)) {
xkb_keysym_t ret;
tmp = strdup(s);
tmp = strdup(name);
if (!tmp)
return XKB_KEY_NoSymbol;
memmove(&tmp[4], &tmp[5], strlen(s) - 5 + 1);
memmove(&tmp[4], &tmp[5], strlen(name) - 5 + 1);
ret = xkb_keysym_from_name(tmp, flags);
free(tmp);
return ret;
@ -264,7 +276,7 @@ xkb_keysym_is_upper(xkb_keysym_t ks)
return (ks == upper ? true : false);
}
xkb_keysym_t
XKB_EXPORT xkb_keysym_t
xkb_keysym_to_lower(xkb_keysym_t ks)
{
xkb_keysym_t lower, upper;
@ -274,7 +286,7 @@ xkb_keysym_to_lower(xkb_keysym_t ks)
return lower;
}
xkb_keysym_t
XKB_EXPORT xkb_keysym_t
xkb_keysym_to_upper(xkb_keysym_t ks)
{
xkb_keysym_t lower, upper;
@ -478,6 +490,8 @@ UCSConvertCase(uint32_t code, xkb_keysym_t *lower, xkb_keysym_t *upper)
*upper = 0x0178;
else if (code == 0x00b5) /* micro sign */
*upper = 0x039c;
else if (code == 0x00df) /* ssharp */
*upper = 0x1e9e;
return;
}
@ -607,6 +621,8 @@ UCSConvertCase(uint32_t code, xkb_keysym_t *lower, xkb_keysym_t *upper)
}
else if (code == 0x1e9b)
*upper = 0x1e60;
else if (code == 0x1e9e)
*lower = 0x00df; /* ssharp */
}
/* Greek Extended, U+1F00 to U+1FFF */

View File

@ -62,10 +62,4 @@ xkb_keysym_is_keypad(xkb_keysym_t keysym);
bool
xkb_keysym_is_modifier(xkb_keysym_t keysym);
xkb_keysym_t
xkb_keysym_to_upper(xkb_keysym_t ks);
xkb_keysym_t
xkb_keysym_to_lower(xkb_keysym_t ks);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -49,9 +49,9 @@ struct scanner {
size_t len;
char buf[1024];
size_t buf_pos;
unsigned line, column;
size_t line, column;
/* The line/column of the start of the current token. */
unsigned token_line, token_column;
size_t token_line, token_column;
const char *file_name;
struct xkb_context *ctx;
void *priv;
@ -59,7 +59,7 @@ struct scanner {
#define scanner_log(scanner, level, fmt, ...) \
xkb_log((scanner)->ctx, (level), 0, \
"%s:%u:%u: " fmt "\n", \
"%s:%zu:%zu: " fmt "\n", \
(scanner)->file_name, \
(scanner)->token_line, (scanner)->token_column, ##__VA_ARGS__)

View File

@ -59,6 +59,8 @@
* - messages (very unlikely)
*/
#include "config.h"
#include "keymap.h"
#include "keysym.h"
#include "utf8.h"
@ -116,27 +118,23 @@ struct xkb_state {
struct xkb_keymap *keymap;
};
static const struct xkb_key_type_entry *
get_entry_for_mods(const struct xkb_key_type *type, xkb_mod_mask_t mods)
{
for (unsigned i = 0; i < type->num_entries; i++)
if (entry_is_active(&type->entries[i]) &&
type->entries[i].mods.mask == mods)
return &type->entries[i];
return NULL;
}
static const struct xkb_key_type_entry *
get_entry_for_key_state(struct xkb_state *state, const struct xkb_key *key,
xkb_layout_index_t group)
{
const struct xkb_key_type *type = key->groups[group].type;
xkb_mod_mask_t active_mods = state->components.mods & type->mods.mask;
for (unsigned i = 0; i < type->num_entries; i++) {
/*
* If the virtual modifiers are not bound to anything, we're
* supposed to skip the entry (xserver does this with cached
* entry->active field).
*/
if (type->entries[i].mods.mods != 0 && type->entries[i].mods.mask == 0)
continue;
if (type->entries[i].mods.mask == active_mods)
return &type->entries[i];
}
return NULL;
return get_entry_for_mods(type, active_mods);
}
/**
@ -215,21 +213,21 @@ xkb_state_key_get_layout(struct xkb_state *state, xkb_keycode_t kc)
key->out_of_range_group_number);
}
static const union xkb_action fake = { .type = ACTION_TYPE_NONE };
static const union xkb_action *
xkb_key_get_action(struct xkb_state *state, const struct xkb_key *key)
{
static const union xkb_action dummy = { .type = ACTION_TYPE_NONE };
xkb_layout_index_t layout;
xkb_level_index_t level;
layout = xkb_state_key_get_layout(state, key->keycode);
if (layout == XKB_LAYOUT_INVALID)
return &fake;
return &dummy;
level = xkb_state_key_get_level(state, key->keycode, layout);
if (level == XKB_LEVEL_INVALID)
return &fake;
return &dummy;
return &key->groups[layout].levels[level].action;
}
@ -257,33 +255,20 @@ xkb_filter_new(struct xkb_state *state)
/***====================================================================***/
static bool
xkb_filter_group_set_func(struct xkb_state *state,
struct xkb_filter *filter,
const struct xkb_key *key,
enum xkb_key_direction direction)
{
if (key != filter->key) {
filter->action.group.flags &= ~ACTION_LOCK_CLEAR;
return true;
}
if (direction == XKB_KEY_DOWN) {
filter->refcnt++;
return false;
}
else if (--filter->refcnt > 0) {
return false;
}
state->components.base_group = filter->priv;
if (filter->action.group.flags & ACTION_LOCK_CLEAR)
state->components.locked_group = 0;
filter->func = NULL;
return true;
}
enum xkb_filter_result {
/*
* The event is consumed by the filters.
*
* An event is always processed by all filters, but any filter can
* prevent it from being processed further by consuming it.
*/
XKB_FILTER_CONSUME,
/*
* The event may continue to be processed as far as this filter is
* concerned.
*/
XKB_FILTER_CONTINUE,
};
static void
xkb_filter_group_set_new(struct xkb_state *state, struct xkb_filter *filter)
@ -296,23 +281,31 @@ xkb_filter_group_set_new(struct xkb_state *state, struct xkb_filter *filter)
}
static bool
xkb_filter_group_lock_func(struct xkb_state *state,
struct xkb_filter *filter,
const struct xkb_key *key,
enum xkb_key_direction direction)
xkb_filter_group_set_func(struct xkb_state *state,
struct xkb_filter *filter,
const struct xkb_key *key,
enum xkb_key_direction direction)
{
if (key != filter->key)
return true;
if (key != filter->key) {
filter->action.group.flags &= ~ACTION_LOCK_CLEAR;
return XKB_FILTER_CONTINUE;
}
if (direction == XKB_KEY_DOWN) {
filter->refcnt++;
return false;
return XKB_FILTER_CONSUME;
}
if (--filter->refcnt > 0)
return false;
else if (--filter->refcnt > 0) {
return XKB_FILTER_CONSUME;
}
state->components.base_group = filter->priv;
if (filter->action.group.flags & ACTION_LOCK_CLEAR)
state->components.locked_group = 0;
filter->func = NULL;
return true;
return XKB_FILTER_CONTINUE;
}
static void
@ -325,30 +318,23 @@ xkb_filter_group_lock_new(struct xkb_state *state, struct xkb_filter *filter)
}
static bool
xkb_filter_mod_set_func(struct xkb_state *state,
struct xkb_filter *filter,
const struct xkb_key *key,
enum xkb_key_direction direction)
xkb_filter_group_lock_func(struct xkb_state *state,
struct xkb_filter *filter,
const struct xkb_key *key,
enum xkb_key_direction direction)
{
if (key != filter->key) {
filter->action.mods.flags &= ~ACTION_LOCK_CLEAR;
return true;
}
if (key != filter->key)
return XKB_FILTER_CONTINUE;
if (direction == XKB_KEY_DOWN) {
filter->refcnt++;
return false;
return XKB_FILTER_CONSUME;
}
else if (--filter->refcnt > 0) {
return false;
}
state->clear_mods = filter->action.mods.mods.mask;
if (filter->action.mods.flags & ACTION_LOCK_CLEAR)
state->components.locked_mods &= ~filter->action.mods.mods.mask;
if (--filter->refcnt > 0)
return XKB_FILTER_CONSUME;
filter->func = NULL;
return true;
return XKB_FILTER_CONTINUE;
}
static void
@ -358,27 +344,30 @@ xkb_filter_mod_set_new(struct xkb_state *state, struct xkb_filter *filter)
}
static bool
xkb_filter_mod_lock_func(struct xkb_state *state,
struct xkb_filter *filter,
const struct xkb_key *key,
enum xkb_key_direction direction)
xkb_filter_mod_set_func(struct xkb_state *state,
struct xkb_filter *filter,
const struct xkb_key *key,
enum xkb_key_direction direction)
{
if (key != filter->key)
return true;
if (key != filter->key) {
filter->action.mods.flags &= ~ACTION_LOCK_CLEAR;
return XKB_FILTER_CONTINUE;
}
if (direction == XKB_KEY_DOWN) {
filter->refcnt++;
return false;
return XKB_FILTER_CONSUME;
}
else if (--filter->refcnt > 0) {
return XKB_FILTER_CONSUME;
}
if (--filter->refcnt > 0)
return false;
state->clear_mods |= filter->action.mods.mods.mask;
if (!(filter->action.mods.flags & ACTION_LOCK_NO_UNLOCK))
state->components.locked_mods &= ~filter->priv;
state->clear_mods = filter->action.mods.mods.mask;
if (filter->action.mods.flags & ACTION_LOCK_CLEAR)
state->components.locked_mods &= ~filter->action.mods.mods.mask;
filter->func = NULL;
return true;
return XKB_FILTER_CONTINUE;
}
static void
@ -391,6 +380,30 @@ xkb_filter_mod_lock_new(struct xkb_state *state, struct xkb_filter *filter)
state->components.locked_mods |= filter->action.mods.mods.mask;
}
static bool
xkb_filter_mod_lock_func(struct xkb_state *state,
struct xkb_filter *filter,
const struct xkb_key *key,
enum xkb_key_direction direction)
{
if (key != filter->key)
return XKB_FILTER_CONTINUE;
if (direction == XKB_KEY_DOWN) {
filter->refcnt++;
return XKB_FILTER_CONSUME;
}
if (--filter->refcnt > 0)
return XKB_FILTER_CONSUME;
state->clear_mods |= filter->action.mods.mods.mask;
if (!(filter->action.mods.flags & ACTION_LOCK_NO_UNLOCK))
state->components.locked_mods &= ~filter->priv;
filter->func = NULL;
return XKB_FILTER_CONTINUE;
}
enum xkb_key_latch_state {
NO_LATCH,
LATCH_KEY_DOWN,
@ -414,6 +427,13 @@ xkb_action_breaks_latch(const union xkb_action *action)
}
}
static void
xkb_filter_mod_latch_new(struct xkb_state *state, struct xkb_filter *filter)
{
filter->priv = LATCH_KEY_DOWN;
state->set_mods = filter->action.mods.mods.mask;
}
static bool
xkb_filter_mod_latch_func(struct xkb_state *state,
struct xkb_filter *filter,
@ -445,14 +465,14 @@ xkb_filter_mod_latch_func(struct xkb_state *state,
filter->key = key;
state->components.latched_mods &= ~filter->action.mods.mods.mask;
/* XXX beep beep! */
return false;
return XKB_FILTER_CONSUME;
}
else if (xkb_action_breaks_latch(action)) {
/* XXX: This may be totally broken, we might need to break the
* latch in the next run after this press? */
state->components.latched_mods &= ~filter->action.mods.mods.mask;
filter->func = NULL;
return true;
return XKB_FILTER_CONTINUE;
}
}
else if (direction == XKB_KEY_UP && key == filter->key) {
@ -492,14 +512,7 @@ xkb_filter_mod_latch_func(struct xkb_state *state,
filter->priv = latch;
return true;
}
static void
xkb_filter_mod_latch_new(struct xkb_state *state, struct xkb_filter *filter)
{
filter->priv = LATCH_KEY_DOWN;
state->set_mods = filter->action.mods.mods.mask;
return XKB_FILTER_CONTINUE;
}
static const struct {
@ -531,17 +544,19 @@ xkb_filter_apply_all(struct xkb_state *state,
{
struct xkb_filter *filter;
const union xkb_action *action;
bool send = true;
bool consumed;
/* First run through all the currently active filters and see if any of
* them have claimed this event. */
* them have consumed this event. */
consumed = false;
darray_foreach(filter, state->filters) {
if (!filter->func)
continue;
send = filter->func(state, filter, key, direction) && send;
}
if (!send || direction == XKB_KEY_UP)
if (filter->func(state, filter, key, direction) == XKB_FILTER_CONSUME)
consumed = true;
}
if (consumed || direction == XKB_KEY_UP)
return;
action = xkb_key_get_action(state, key);
@ -560,9 +575,6 @@ xkb_filter_apply_all(struct xkb_state *state,
return;
filter = xkb_filter_new(state);
if (!filter)
return; /* WSGO */
filter->key = key;
filter->func = filter_action_funcs[action->type].func;
filter->action = *action;
@ -855,7 +867,7 @@ err:
}
/*
* http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier
* https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier
*/
static bool
should_do_caps_transformation(struct xkb_state *state, xkb_keycode_t kc)
@ -869,7 +881,7 @@ should_do_caps_transformation(struct xkb_state *state, xkb_keycode_t kc)
}
/*
* http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier
* https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier
*/
static bool
should_do_ctrl_transformation(struct xkb_state *state, xkb_keycode_t kc)
@ -1133,7 +1145,7 @@ xkb_state_mod_index_is_active(struct xkb_state *state,
* Helper function for xkb_state_mod_indices_are_active and
* xkb_state_mod_names_are_active.
*/
static int
static bool
match_mod_masks(struct xkb_state *state,
enum xkb_state_component type,
enum xkb_state_match match,
@ -1142,14 +1154,12 @@ match_mod_masks(struct xkb_state *state,
xkb_mod_mask_t active = xkb_state_serialize_mods(state, type);
if (!(match & XKB_STATE_MATCH_NON_EXCLUSIVE) && (active & ~wanted))
return 0;
return false;
if (match & XKB_STATE_MATCH_ANY)
return !!(active & wanted);
else
return (active & wanted) == wanted;
return active & wanted;
return 0;
return (active & wanted) == wanted;
}
/**
@ -1163,14 +1173,13 @@ xkb_state_mod_indices_are_active(struct xkb_state *state,
...)
{
va_list ap;
xkb_mod_index_t idx = 0;
xkb_mod_mask_t wanted = 0;
int ret = 0;
xkb_mod_index_t num_mods = xkb_keymap_num_mods(state->keymap);
va_start(ap, match);
while (1) {
idx = va_arg(ap, xkb_mod_index_t);
xkb_mod_index_t idx = va_arg(ap, xkb_mod_index_t);
if (idx == XKB_MOD_INVALID)
break;
if (idx >= num_mods) {
@ -1214,12 +1223,12 @@ xkb_state_mod_names_are_active(struct xkb_state *state,
...)
{
va_list ap;
xkb_mod_index_t idx = 0;
xkb_mod_mask_t wanted = 0;
int ret = 0;
va_start(ap, match);
while (1) {
xkb_mod_index_t idx;
const char *str = va_arg(ap, const char *);
if (str == NULL)
break;
@ -1307,13 +1316,20 @@ xkb_state_led_name_is_active(struct xkb_state *state, const char *name)
return xkb_state_led_index_is_active(state, idx);
}
/**
* See:
* - XkbTranslateKeyCode(3), mod_rtrn return value, from libX11.
* - MyEnhancedXkbTranslateKeyCode(), a modification of the above, from GTK+.
*/
static xkb_mod_mask_t
key_get_consumed(struct xkb_state *state, const struct xkb_key *key)
key_get_consumed(struct xkb_state *state, const struct xkb_key *key,
enum xkb_consumed_mode mode)
{
const struct xkb_key_type *type;
const struct xkb_key_type_entry *entry;
xkb_mod_mask_t preserve;
const struct xkb_key_type_entry *matching_entry;
xkb_mod_mask_t preserve = 0;
xkb_layout_index_t group;
xkb_mod_mask_t consumed = 0;
group = xkb_state_key_get_layout(state, key->keycode);
if (group == XKB_LAYOUT_INVALID)
@ -1321,47 +1337,64 @@ key_get_consumed(struct xkb_state *state, const struct xkb_key *key)
type = key->groups[group].type;
entry = get_entry_for_key_state(state, key, group);
if (entry)
preserve = entry->preserve.mask;
else
preserve = 0;
matching_entry = get_entry_for_key_state(state, key, group);
if (matching_entry)
preserve = matching_entry->preserve.mask;
return type->mods.mask & ~preserve;
switch (mode) {
case XKB_CONSUMED_MODE_XKB:
consumed = type->mods.mask;
break;
case XKB_CONSUMED_MODE_GTK: {
const struct xkb_key_type_entry *no_mods_entry;
xkb_level_index_t no_mods_leveli;
const struct xkb_level *no_mods_level, *level;
no_mods_entry = get_entry_for_mods(type, 0);
no_mods_leveli = no_mods_entry ? no_mods_entry->level : 0;
no_mods_level = &key->groups[group].levels[no_mods_leveli];
for (unsigned i = 0; i < type->num_entries; i++) {
const struct xkb_key_type_entry *entry = &type->entries[i];
if (!entry_is_active(entry))
continue;
level = &key->groups[group].levels[entry->level];
if (XkbLevelsSameSyms(level, no_mods_level))
continue;
if (entry == matching_entry || one_bit_set(entry->mods.mask))
consumed |= entry->mods.mask & ~entry->preserve.mask;
}
break;
}
}
return consumed & ~preserve;
}
/**
* Tests to see if a modifier is used up by our translation of a
* keycode to keysyms, taking note of the current modifier state and
* the appropriate key type's preserve information, if any. This allows
* the user to mask out the modifier in later processing of the
* modifiers, e.g. when implementing hot keys or accelerators.
*
* See also, for example:
* - XkbTranslateKeyCode(3), mod_rtrn return value, from libX11.
* - gdk_keymap_translate_keyboard_state, consumed_modifiers return value,
* from gtk+.
*/
XKB_EXPORT int
xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t kc,
xkb_mod_index_t idx)
xkb_state_mod_index_is_consumed2(struct xkb_state *state, xkb_keycode_t kc,
xkb_mod_index_t idx,
enum xkb_consumed_mode mode)
{
const struct xkb_key *key = XkbKey(state->keymap, kc);
if (!key || idx >= xkb_keymap_num_mods(state->keymap))
return -1;
return !!((1u << idx) & key_get_consumed(state, key));
return !!((1u << idx) & key_get_consumed(state, key, mode));
}
XKB_EXPORT int
xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t kc,
xkb_mod_index_t idx)
{
return xkb_state_mod_index_is_consumed2(state, kc, idx,
XKB_CONSUMED_MODE_XKB);
}
/**
* Calculates which modifiers should be consumed during key processing,
* and returns the mask with all these modifiers removed. e.g. if
* given a state of Alt and Shift active for a two-level alphabetic
* key containing plus and equal on the first and second level
* respectively, will return a mask of only Alt, as Shift has been
* consumed by the type handling.
*/
XKB_EXPORT xkb_mod_mask_t
xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t kc,
xkb_mod_mask_t mask)
@ -1371,16 +1404,34 @@ xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t kc,
if (!key)
return 0;
return mask & ~key_get_consumed(state, key);
return mask & ~key_get_consumed(state, key, XKB_CONSUMED_MODE_XKB);
}
XKB_EXPORT xkb_mod_mask_t
xkb_state_key_get_consumed_mods2(struct xkb_state *state, xkb_keycode_t kc,
enum xkb_consumed_mode mode)
{
const struct xkb_key *key;
switch (mode) {
case XKB_CONSUMED_MODE_XKB:
case XKB_CONSUMED_MODE_GTK:
break;
default:
log_err_func(state->keymap->ctx,
"unrecognized consumed modifiers mode: %d\n", mode);
return 0;
}
key = XkbKey(state->keymap, kc);
if (!key)
return 0;
return key_get_consumed(state, key, mode);
}
XKB_EXPORT xkb_mod_mask_t
xkb_state_key_get_consumed_mods(struct xkb_state *state, xkb_keycode_t kc)
{
const struct xkb_key *key = XkbKey(state->keymap, kc);
if (!key)
return 0;
return key_get_consumed(state, key);
return xkb_state_key_get_consumed_mods2(state, kc, XKB_CONSUMED_MODE_XKB);
}

View File

@ -24,6 +24,8 @@
*
********************************************************/
#include "config.h"
#include "keymap.h"
#include "text.h"
@ -204,6 +206,7 @@ const LookupEntry symInterpretMatchMaskNames[] = {
{ "AnyOf", MATCH_ANY },
{ "AllOf", MATCH_ALL },
{ "Exactly", MATCH_EXACTLY },
{ NULL, 0 },
};
const char *
@ -254,7 +257,7 @@ const char *
ModMaskText(struct xkb_context *ctx, const struct xkb_mod_set *mods,
xkb_mod_mask_t mask)
{
char buf[1024];
char buf[1024] = {0};
size_t pos = 0;
xkb_mod_index_t i;
const struct xkb_mod *mod;

View File

@ -24,6 +24,8 @@
* Author: Rob Bradford <rob@linux.intel.com>
*/
#include "config.h"
#include <stddef.h>
#include <stdbool.h>
#include <inttypes.h>
@ -49,17 +51,13 @@ utf32_to_utf8(uint32_t unichar, char *buffer)
length = 3;
head = 0xe0;
}
else if (unichar <= 0x1fffff) {
else if (unichar <= 0x10ffff) {
length = 4;
head = 0xf0;
}
else if (unichar <= 0x3ffffff) {
length = 5;
head = 0xf8;
}
else {
length = 6;
head = 0xfc;
buffer[0] = '\0';
return 0;
}
for (count = length - 1, shift = 0; count > 0; count--, shift += 6)
@ -80,7 +78,7 @@ is_valid_utf8(const char *ss, size_t len)
/* This beauty is from:
* The Unicode Standard Version 6.2 - Core Specification, Table 3.7
* http://www.unicode.org/versions/Unicode6.2.0/ch03.pdf#G7404
* https://www.unicode.org/versions/Unicode6.2.0/ch03.pdf#G7404
* We can optimize if needed. */
while (i < len)
{

View File

@ -0,0 +1,94 @@
/*
* Copyright © 2008-2011 Kristian Høgsberg
* Copyright © 2011 Intel Corporation
* Copyright © 2013-2015 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include <assert.h>
#include <stddef.h>
#include <stdbool.h>
#include "util-list.h"
void
list_init(struct list *list)
{
list->prev = list;
list->next = list;
}
void
list_insert(struct list *list, struct list *elm)
{
assert((list->next != NULL && list->prev != NULL) ||
!"list->next|prev is NULL, possibly missing list_init()");
assert(((elm->next == NULL && elm->prev == NULL) || list_empty(elm)) ||
!"elm->next|prev is not NULL, list node used twice?");
elm->prev = list;
elm->next = list->next;
list->next = elm;
elm->next->prev = elm;
}
void
list_append(struct list *list, struct list *elm)
{
assert((list->next != NULL && list->prev != NULL) ||
!"list->next|prev is NULL, possibly missing list_init()");
assert(((elm->next == NULL && elm->prev == NULL) || list_empty(elm)) ||
!"elm->next|prev is not NULL, list node used twice?");
elm->next = list;
elm->prev = list->prev;
list->prev = elm;
elm->prev->next = elm;
}
void
list_remove(struct list *elm)
{
assert((elm->next != NULL && elm->prev != NULL) ||
!"list->next|prev is NULL, possibly missing list_init()");
elm->prev->next = elm->next;
elm->next->prev = elm->prev;
elm->next = NULL;
elm->prev = NULL;
}
bool
list_empty(const struct list *list)
{
assert((list->next != NULL && list->prev != NULL) ||
!"list->next|prev is NULL, possibly missing list_init()");
return list->next == list;
}
bool
list_is_last(const struct list *list, const struct list *elm)
{
return elm->next == list;
}

View File

@ -0,0 +1,71 @@
/*
* Copyright © 2008-2011 Kristian Høgsberg
* Copyright © 2011 Intel Corporation
* Copyright © 2013-2015 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include "config.h"
#include <stdbool.h>
#include <stddef.h>
/*
* This list data structure is a verbatim copy from wayland-util.h from the
* Wayland project; except that wl_ prefix has been removed.
*/
struct list {
struct list *prev;
struct list *next;
};
void list_init(struct list *list);
void list_insert(struct list *list, struct list *elm);
void list_append(struct list *list, struct list *elm);
void list_remove(struct list *elm);
bool list_empty(const struct list *list);
bool list_is_last(const struct list *list, const struct list *elm);
#define container_of(ptr, type, member) \
(__typeof__(type) *)((char *)(ptr) - \
offsetof(__typeof__(type), member))
#define list_first_entry(head, pos, member) \
container_of((head)->next, __typeof__(*pos), member)
#define list_last_entry(head, pos, member) \
container_of((head)->prev, __typeof__(*pos), member)
#define list_for_each(pos, head, member) \
for (pos = 0, pos = list_first_entry(head, pos, member); \
&pos->member != (head); \
pos = list_first_entry(&pos->member, pos, member))
#define list_for_each_safe(pos, tmp, head, member) \
for (pos = 0, tmp = 0, \
pos = list_first_entry(head, pos, member), \
tmp = list_first_entry(&pos->member, tmp, member); \
&pos->member != (head); \
pos = tmp, \
tmp = list_first_entry(&pos->member, tmp, member))

View File

@ -21,6 +21,8 @@
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include "utils.h"
#ifdef HAVE_MMAP
@ -32,13 +34,16 @@
#include <sys/types.h>
bool
map_file(FILE *file, const char **string_out, size_t *size_out)
map_file(FILE *file, char **string_out, size_t *size_out)
{
struct stat stat_buf;
const int fd = fileno(file);
int fd;
char *string;
/* Make sure to keep the errno on failure! */
fd = fileno(file);
if (fd < 0)
return false;
if (fstat(fd, &stat_buf) != 0)
return false;
@ -53,15 +58,15 @@ map_file(FILE *file, const char **string_out, size_t *size_out)
}
void
unmap_file(const char *str, size_t size)
unmap_file(char *str, size_t size)
{
munmap(UNCONSTIFY(str), size);
munmap(str, size);
}
#else
bool
map_file(FILE *file, const char **string_out, size_t *size_out)
map_file(FILE *file, char **string_out, size_t *size_out)
{
long ret;
size_t ret_s;
@ -99,9 +104,107 @@ map_file(FILE *file, const char **string_out, size_t *size_out)
}
void
unmap_file(const char *str, size_t size)
unmap_file(char *str, size_t size)
{
free(UNCONSTIFY(str));
free(str);
}
#endif
// ASCII lower-case map.
static const unsigned char lower_map[] = {
0, 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, 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,
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, 162, 163, 164, 165, 166, 167,
168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212,
213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242,
243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
};
// ASCII tolower (to avoid locale issues).
char
to_lower(char c)
{
return (char) lower_map[(unsigned char) c];
}
// ASCII strcasecmp (to avoid locale issues).
int
istrcmp(const char *a, const char *b)
{
for (size_t i = 0; ; i++) {
if (to_lower(a[i]) != to_lower(b[i]))
return (int) to_lower(a[i]) - (int) to_lower(b[i]);
if (!a[i])
break;
}
return 0;
}
// ASCII strncasecmp (to avoid locale issues).
int
istrncmp(const char *a, const char *b, size_t n)
{
for (size_t i = 0; i < n; i++) {
if (to_lower(a[i]) != to_lower(b[i]))
return (int) to_lower(a[i]) - (int) to_lower(b[i]);
if (!a[i])
break;
}
return 0;
}
#if !(defined(HAVE_ASPRINTF) && HAVE_ASPRINTF)
int
asprintf(char **strp, const char *fmt, ...)
{
int ret;
va_list ap;
va_start(ap, fmt);
ret = vasprintf(strp, fmt, ap);
va_end(ap);
return ret;
}
# if !(defined(HAVE_VASPRINTF) && HAVE_VASPRINTF)
int
vasprintf(char **strp, const char *fmt, va_list ap)
{
int ret;
char *buf;
va_list ap_copy;
/*
* The value of the va_list parameter is undefined after the call to
* vsnprintf() returns: pass a copy to make sure "ap" remains valid.
*/
va_copy(ap_copy, ap);
ret = vsnprintf(NULL, 0, fmt, ap_copy);
va_end(ap_copy);
if (ret < 0)
return ret;
if (!(buf = malloc(ret + 1)))
return -1;
if ((ret = vsnprintf(buf, ret + 1, fmt, ap)) < 0) {
free(buf);
return ret;
}
*strp = buf;
return ret;
}
# endif /* !HAVE_VASPRINTF */
#endif /* !HAVE_ASPRINTF */

View File

@ -26,30 +26,58 @@
#include <errno.h>
#include <inttypes.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#else
/* Required on Windows where unistd.h doesn't exist */
#define R_OK 4 /* Test for read permission. */
#define W_OK 2 /* Test for write permission. */
#define X_OK 1 /* Test for execute permission. */
#define F_OK 0 /* Test for existence. */
#endif
#include "darray.h"
/*
* We sometimes malloc strings and then expose them as const char*'s. This
* macro is used when we free these strings in order to avoid -Wcast-qual
* errors.
*/
#define UNCONSTIFY(const_ptr) ((void *) (uintptr_t) (const_ptr))
#define STATIC_ASSERT(expr, message) do { \
switch (0) { case 0: case (expr): ; } \
} while (0)
#define ARRAY_SIZE(arr) ((sizeof(arr) / sizeof(*(arr))))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
/* Round up @a so it's divisible by @b. */
#define ROUNDUP(a, b) (((a) + (b) - 1) / (b) * (b))
char
to_lower(char c);
int
istrcmp(const char *a, const char *b);
int
istrncmp(const char *a, const char *b, size_t n);
static inline bool
streq(const char *s1, const char *s2)
{
assert(s1 && s2);
return strcmp(s1, s2) == 0;
}
static inline bool
streq_null(const char *s1, const char *s2)
{
if (s1 == NULL || s2 == NULL)
return s1 == s2;
return streq(s1, s2);
}
static inline bool
streq_not_null(const char *s1, const char *s2)
{
@ -61,13 +89,13 @@ streq_not_null(const char *s1, const char *s2)
static inline bool
istreq(const char *s1, const char *s2)
{
return strcasecmp(s1, s2) == 0;
return istrcmp(s1, s2) == 0;
}
static inline bool
istreq_prefix(const char *s1, const char *s2)
{
return strncasecmp(s1, s2, strlen(s1)) == 0;
return istrncmp(s1, s2, strlen(s1)) == 0;
}
static inline char *
@ -108,18 +136,22 @@ memdup(const void *mem, size_t nmemb, size_t size)
memcpy(p, mem, nmemb * size);
return p;
}
static inline int
min(int misc, int other)
#ifndef ANDROID
#if !(defined(HAVE_STRNDUP) && HAVE_STRNDUP)
static inline char *
strndup(const char *s, size_t n)
{
return (misc < other) ? misc : other;
}
static inline int
max(int misc, int other)
{
return (misc > other) ? misc : other;
size_t slen = strlen(s);
size_t len = MIN(slen, n);
char *p = malloc(len + 1);
if (!p)
return NULL;
memcpy(p, s, len);
p[len] = '\0';
return p;
}
#endif
#endif
/* ctype.h is locale-dependent and has other oddities. */
static inline bool
@ -178,21 +210,31 @@ msb_pos(uint32_t mask)
return pos;
}
static inline int
one_bit_set(uint32_t x)
{
return x && (x & (x - 1)) == 0;
}
bool
map_file(FILE *file, const char **string_out, size_t *size_out);
map_file(FILE *file, char **string_out, size_t *size_out);
void
unmap_file(const char *str, size_t size);
unmap_file(char *string, size_t size);
#define ARRAY_SIZE(arr) ((sizeof(arr) / sizeof(*(arr))))
static inline bool
check_eaccess(const char *path, int mode)
{
#if defined(HAVE_EACCESS)
if (eaccess(path, mode) != 0)
return false;
#elif defined(HAVE_EUIDACCESS)
if (euidaccess(path, mode) != 0)
return false;
#endif
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MIN3(a, b, c) MIN(MIN((a), (b)), (c))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MAX3(a, b, c) MAX(MAX((a), (b)), (c))
/* Round up @a so it's divisible by @b. */
#define ROUNDUP(a, b) (((a) + (b) - 1) / (b) * (b))
return true;
}
#if defined(HAVE_SECURE_GETENV)
# define secure_getenv secure_getenv
@ -251,4 +293,58 @@ unmap_file(const char *str, size_t size);
#define ATTR_PACKED
#endif
#if !(defined(HAVE_ASPRINTF) && HAVE_ASPRINTF)
int asprintf(char **strp, const char *fmt, ...) ATTR_PRINTF(2, 3);
# if !(defined(HAVE_VASPRINTF) && HAVE_VASPRINTF)
# include <stdarg.h>
int vasprintf(char **strp, const char *fmt, va_list ap);
# endif /* !HAVE_VASPRINTF */
#endif /* !HAVE_ASPRINTF */
static inline bool
ATTR_PRINTF(3, 4)
snprintf_safe(char *buf, size_t sz, const char *format, ...)
{
va_list ap;
int rc;
va_start(ap, format);
rc = vsnprintf(buf, sz, format, ap);
va_end(ap);
return rc >= 0 && (size_t)rc < sz;
}
static inline char *
ATTR_PRINTF(1, 0)
vasprintf_safe(const char *fmt, va_list args)
{
char *str;
int len;
len = vasprintf(&str, fmt, args);
if (len == -1)
return NULL;
return str;
}
/**
* A version of asprintf that returns the allocated string or NULL on error.
*/
static inline char *
ATTR_PRINTF(1, 2)
asprintf_safe(const char *fmt, ...)
{
va_list args;
char *str;
va_start(args, fmt);
str = vasprintf_safe(fmt, args);
va_end(args);
return str;
}
#endif /* UTILS_H */

View File

@ -21,12 +21,14 @@
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include "x11-priv.h"
/*
* References for the lonesome traveler:
* Xkb protocol specification:
* http://www.x.org/releases/current/doc/kbproto/xkbproto.html
* https://www.x.org/releases/current/doc/kbproto/xkbproto.html
* The XCB xkb XML protocol file:
* /user/share/xcb/xkb.xml
* The XCB xkb header file:
@ -86,6 +88,33 @@
} \
} while (0)
static const xcb_xkb_map_part_t get_map_required_components =
(XCB_XKB_MAP_PART_KEY_TYPES |
XCB_XKB_MAP_PART_KEY_SYMS |
XCB_XKB_MAP_PART_MODIFIER_MAP |
XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS |
XCB_XKB_MAP_PART_KEY_ACTIONS |
XCB_XKB_MAP_PART_VIRTUAL_MODS |
XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP);
static const xcb_xkb_name_detail_t get_names_wanted =
(XCB_XKB_NAME_DETAIL_KEYCODES |
XCB_XKB_NAME_DETAIL_SYMBOLS |
XCB_XKB_NAME_DETAIL_TYPES |
XCB_XKB_NAME_DETAIL_COMPAT |
XCB_XKB_NAME_DETAIL_KEY_TYPE_NAMES |
XCB_XKB_NAME_DETAIL_KT_LEVEL_NAMES |
XCB_XKB_NAME_DETAIL_INDICATOR_NAMES |
XCB_XKB_NAME_DETAIL_KEY_NAMES |
XCB_XKB_NAME_DETAIL_KEY_ALIASES |
XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES |
XCB_XKB_NAME_DETAIL_GROUP_NAMES);
static const xcb_xkb_name_detail_t get_names_required =
(XCB_XKB_NAME_DETAIL_KEY_TYPE_NAMES |
XCB_XKB_NAME_DETAIL_KT_LEVEL_NAMES |
XCB_XKB_NAME_DETAIL_KEY_NAMES |
XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES);
static xkb_mod_mask_t
translate_mods(uint8_t rmods, uint16_t vmods_low, uint16_t vmods_high)
@ -218,8 +247,8 @@ translate_action(union xkb_action *action, const xcb_xkb_action_t *wire)
case XCB_XKB_SA_TYPE_MOVE_PTR:
action->type = ACTION_TYPE_PTR_MOVE;
action->ptr.x = (wire->moveptr.xLow | (wire->moveptr.xHigh << 8));
action->ptr.y = (wire->moveptr.yLow | (wire->moveptr.yHigh << 8));
action->ptr.x = (int16_t) (wire->moveptr.xLow | ((uint16_t) wire->moveptr.xHigh << 8));
action->ptr.y = (int16_t) (wire->moveptr.yLow | ((uint16_t) wire->moveptr.yHigh << 8));
if (!(wire->moveptr.flags & XCB_XKB_SA_MOVE_PTR_FLAG_NO_ACCELERATION))
action->ptr.flags |= ACTION_ACCEL;
@ -443,18 +472,19 @@ get_sym_maps(struct xkb_keymap *keymap, xcb_connection_t *conn,
FAIL_UNLESS((unsigned) syms_length == wire_sym_map->width * key->num_groups);
for (int j = 0; j < syms_length; j++) {
xcb_keysym_t wire_keysym = *syms_iter;
const xkb_layout_index_t group = j / wire_sym_map->width;
const xkb_level_index_t level = j % wire_sym_map->width;
for (xkb_layout_index_t group = 0; group < key->num_groups; group++) {
for (xkb_level_index_t level = 0; level < wire_sym_map->width; level++) {
xcb_keysym_t wire_keysym = *syms_iter;
if (level < key->groups[group].type->num_levels &&
wire_keysym != XKB_KEY_NoSymbol) {
key->groups[group].levels[level].num_syms = 1;
key->groups[group].levels[level].u.sym = wire_keysym;
assert(key->groups[group].type != NULL);
if (level < key->groups[group].type->num_levels &&
wire_keysym != XKB_KEY_NoSymbol) {
key->groups[group].levels[level].num_syms = 1;
key->groups[group].levels[level].u.sym = wire_keysym;
}
syms_iter++;
}
syms_iter++;
}
}
@ -489,21 +519,23 @@ get_actions(struct xkb_keymap *keymap, xcb_connection_t *conn,
uint8_t wire_count = *acts_count_iter;
struct xkb_key *key = &keymap->keys[reply->firstKeyAction + i];
FAIL_UNLESS((unsigned) syms_length == wire_sym_map->width * key->num_groups);
FAIL_UNLESS(wire_count == 0 || wire_count == syms_length);
for (int j = 0; j < wire_count; j++) {
xcb_xkb_action_t *wire_action = acts_iter.data;
const xkb_layout_index_t group = j / wire_sym_map->width;
const xkb_level_index_t level = j % wire_sym_map->width;
if (wire_count != 0) {
for (xkb_layout_index_t group = 0; group < key->num_groups; group++) {
for (xkb_level_index_t level = 0; level < wire_sym_map->width; level++) {
xcb_xkb_action_t *wire_action = acts_iter.data;
if (level < key->groups[group].type->num_levels) {
union xkb_action *action =
&key->groups[group].levels[level].action;
if (level < key->groups[group].type->num_levels) {
union xkb_action *action = &key->groups[group].levels[level].action;
translate_action(action, wire_action);
translate_action(action, wire_action);
}
xcb_xkb_action_next(&acts_iter);
}
}
xcb_xkb_action_next(&acts_iter);
}
acts_count_iter++;
@ -640,26 +672,15 @@ fail:
}
static bool
get_map(struct xkb_keymap *keymap, xcb_connection_t *conn, uint16_t device_id)
get_map(struct xkb_keymap *keymap, xcb_connection_t *conn,
xcb_xkb_get_map_cookie_t cookie)
{
static const xcb_xkb_map_part_t required_components =
(XCB_XKB_MAP_PART_KEY_TYPES |
XCB_XKB_MAP_PART_KEY_SYMS |
XCB_XKB_MAP_PART_MODIFIER_MAP |
XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS |
XCB_XKB_MAP_PART_KEY_ACTIONS |
XCB_XKB_MAP_PART_VIRTUAL_MODS |
XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP);
xcb_xkb_get_map_cookie_t cookie =
xcb_xkb_get_map(conn, device_id, required_components,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
xcb_xkb_get_map_reply_t *reply = xcb_xkb_get_map_reply(conn, cookie, NULL);
xcb_xkb_get_map_map_t map;
FAIL_IF_BAD_REPLY(reply, "XkbGetMap");
if ((reply->present & required_components) != required_components)
if ((reply->present & get_map_required_components) != get_map_required_components)
goto fail;
xcb_xkb_get_map_map_unpack(xcb_xkb_get_map_map(reply),
@ -744,10 +765,8 @@ get_indicators(struct xkb_keymap *keymap, xcb_connection_t *conn,
static bool
get_indicator_map(struct xkb_keymap *keymap, xcb_connection_t *conn,
uint16_t device_id)
xcb_xkb_get_indicator_map_cookie_t cookie)
{
xcb_xkb_get_indicator_map_cookie_t cookie =
xcb_xkb_get_indicator_map(conn, device_id, ALL_INDICATORS_MASK);
xcb_xkb_get_indicator_map_reply_t *reply =
xcb_xkb_get_indicator_map_reply(conn, cookie, NULL);
@ -826,10 +845,8 @@ fail:
static bool
get_compat_map(struct xkb_keymap *keymap, xcb_connection_t *conn,
uint16_t device_id)
xcb_xkb_get_compat_map_cookie_t cookie)
{
xcb_xkb_get_compat_map_cookie_t cookie =
xcb_xkb_get_compat_map(conn, device_id, 0, true, 0, 0);
xcb_xkb_get_compat_map_reply_t *reply =
xcb_xkb_get_compat_map_reply(conn, cookie, NULL);
@ -847,7 +864,7 @@ fail:
}
static bool
get_type_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
get_type_names(struct xkb_keymap *keymap, struct x11_atom_interner *interner,
xcb_xkb_get_names_reply_t *reply,
xcb_xkb_get_names_value_list_t *list)
{
@ -875,14 +892,13 @@ get_type_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
ALLOC_OR_FAIL(type->level_names, type->num_levels);
if (!adopt_atom(keymap->ctx, conn, wire_type_name, &type->name))
goto fail;
if (!adopt_atoms(keymap->ctx, conn,
kt_level_names_iter, type->level_names,
wire_num_levels))
goto fail;
x11_atom_interner_adopt_atom(interner, wire_type_name, &type->name);
for (size_t j = 0; j < wire_num_levels; j++) {
x11_atom_interner_adopt_atom(interner, kt_level_names_iter[j],
&type->level_names[j]);
}
type->num_level_names = type->num_levels;
kt_level_names_iter += wire_num_levels;
key_type_names_iter++;
n_levels_per_type_iter++;
@ -895,7 +911,8 @@ fail:
}
static bool
get_indicator_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
get_indicator_names(struct xkb_keymap *keymap,
struct x11_atom_interner *interner,
xcb_xkb_get_names_reply_t *reply,
xcb_xkb_get_names_value_list_t *list)
{
@ -908,8 +925,7 @@ get_indicator_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
xcb_atom_t wire = *iter;
struct xkb_led *led = &keymap->leds[i];
if (!adopt_atom(keymap->ctx, conn, wire, &led->name))
return false;
x11_atom_interner_adopt_atom(interner, wire, &led->name);
iter++;
}
@ -922,7 +938,7 @@ fail:
}
static bool
get_vmod_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
get_vmod_names(struct xkb_keymap *keymap, struct x11_atom_interner *interner,
xcb_xkb_get_names_reply_t *reply,
xcb_xkb_get_names_value_list_t *list)
{
@ -941,8 +957,7 @@ get_vmod_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
xcb_atom_t wire = *iter;
struct xkb_mod *mod = &keymap->mods.mods[NUM_REAL_MODS + i];
if (!adopt_atom(keymap->ctx, conn, wire, &mod->name))
return false;
x11_atom_interner_adopt_atom(interner, wire, &mod->name);
iter++;
}
@ -952,7 +967,7 @@ get_vmod_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
}
static bool
get_group_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
get_group_names(struct xkb_keymap *keymap, struct x11_atom_interner *interner,
xcb_xkb_get_names_reply_t *reply,
xcb_xkb_get_names_value_list_t *list)
{
@ -962,9 +977,10 @@ get_group_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
keymap->num_group_names = msb_pos(reply->groupNames);
ALLOC_OR_FAIL(keymap->group_names, keymap->num_group_names);
if (!adopt_atoms(keymap->ctx, conn,
iter, keymap->group_names, length))
goto fail;
for (int i = 0; i < length; i++) {
x11_atom_interner_adopt_atom(interner, iter[i],
&keymap->group_names[i]);
}
return true;
@ -1045,36 +1061,17 @@ fail:
}
static bool
get_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
uint16_t device_id)
get_names(struct xkb_keymap *keymap, struct x11_atom_interner *interner,
xcb_xkb_get_names_cookie_t cookie)
{
static const xcb_xkb_name_detail_t wanted =
(XCB_XKB_NAME_DETAIL_KEYCODES |
XCB_XKB_NAME_DETAIL_SYMBOLS |
XCB_XKB_NAME_DETAIL_TYPES |
XCB_XKB_NAME_DETAIL_COMPAT |
XCB_XKB_NAME_DETAIL_KEY_TYPE_NAMES |
XCB_XKB_NAME_DETAIL_KT_LEVEL_NAMES |
XCB_XKB_NAME_DETAIL_INDICATOR_NAMES |
XCB_XKB_NAME_DETAIL_KEY_NAMES |
XCB_XKB_NAME_DETAIL_KEY_ALIASES |
XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES |
XCB_XKB_NAME_DETAIL_GROUP_NAMES);
static const xcb_xkb_name_detail_t required =
(XCB_XKB_NAME_DETAIL_KEY_TYPE_NAMES |
XCB_XKB_NAME_DETAIL_KT_LEVEL_NAMES |
XCB_XKB_NAME_DETAIL_KEY_NAMES |
XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES);
xcb_xkb_get_names_cookie_t cookie =
xcb_xkb_get_names(conn, device_id, wanted);
xcb_connection_t *conn = interner->conn;
xcb_xkb_get_names_reply_t *reply =
xcb_xkb_get_names_reply(conn, cookie, NULL);
xcb_xkb_get_names_value_list_t list;
FAIL_IF_BAD_REPLY(reply, "XkbGetNames");
FAIL_UNLESS((reply->which & required) == required);
FAIL_UNLESS((reply->which & get_names_required) == get_names_required);
xcb_xkb_get_names_value_list_unpack(xcb_xkb_get_names_value_list(reply),
reply->nTypes,
@ -1087,23 +1084,22 @@ get_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
reply->which,
&list);
if (!get_atom_name(conn, list.keycodesName, &keymap->keycodes_section_name) ||
!get_atom_name(conn, list.symbolsName, &keymap->symbols_section_name) ||
!get_atom_name(conn, list.typesName, &keymap->types_section_name) ||
!get_atom_name(conn, list.compatName, &keymap->compat_section_name) ||
!get_type_names(keymap, conn, reply, &list) ||
!get_indicator_names(keymap, conn, reply, &list) ||
!get_vmod_names(keymap, conn, reply, &list) ||
!get_group_names(keymap, conn, reply, &list) ||
x11_atom_interner_get_escaped_atom_name(interner, list.keycodesName,
&keymap->keycodes_section_name);
x11_atom_interner_get_escaped_atom_name(interner, list.symbolsName,
&keymap->symbols_section_name);
x11_atom_interner_get_escaped_atom_name(interner, list.typesName,
&keymap->types_section_name);
x11_atom_interner_get_escaped_atom_name(interner, list.compatName,
&keymap->compat_section_name);
if (!get_type_names(keymap, interner, reply, &list) ||
!get_indicator_names(keymap, interner, reply, &list) ||
!get_vmod_names(keymap, interner, reply, &list) ||
!get_group_names(keymap, interner, reply, &list) ||
!get_key_names(keymap, conn, reply, &list) ||
!get_aliases(keymap, conn, reply, &list))
goto fail;
XkbEscapeMapName(keymap->keycodes_section_name);
XkbEscapeMapName(keymap->symbols_section_name);
XkbEscapeMapName(keymap->types_section_name);
XkbEscapeMapName(keymap->compat_section_name);
free(reply);
return true;
@ -1114,10 +1110,8 @@ fail:
static bool
get_controls(struct xkb_keymap *keymap, xcb_connection_t *conn,
uint16_t device_id)
xcb_xkb_get_controls_cookie_t cookie)
{
xcb_xkb_get_controls_cookie_t cookie =
xcb_xkb_get_controls(conn, device_id);
xcb_xkb_get_controls_reply_t *reply =
xcb_xkb_get_controls_reply(conn, cookie, NULL);
@ -1154,7 +1148,7 @@ xkb_x11_keymap_new_from_device(struct xkb_context *ctx,
return NULL;
}
if (device_id < 0 || device_id > 255) {
if (device_id < 0 || device_id > 127) {
log_err_func(ctx, "illegal device ID: %d\n", device_id);
return NULL;
}
@ -1163,11 +1157,31 @@ xkb_x11_keymap_new_from_device(struct xkb_context *ctx,
if (!keymap)
return NULL;
if (!get_map(keymap, conn, device_id) ||
!get_indicator_map(keymap, conn, device_id) ||
!get_compat_map(keymap, conn, device_id) ||
!get_names(keymap, conn, device_id) ||
!get_controls(keymap, conn, device_id)) {
struct x11_atom_interner interner;
x11_atom_interner_init(&interner, ctx, conn);
xcb_xkb_get_map_cookie_t get_map_cookie =
xcb_xkb_get_map(conn, device_id, get_map_required_components,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
xcb_xkb_get_indicator_map_cookie_t indicator_map_cookie =
xcb_xkb_get_indicator_map(conn, device_id, ALL_INDICATORS_MASK);
xcb_xkb_get_compat_map_cookie_t compat_map_cookie =
xcb_xkb_get_compat_map(conn, device_id, 0, true, 0, 0);
xcb_xkb_get_names_cookie_t get_names_cookie =
xcb_xkb_get_names(conn, device_id, get_names_wanted);
xcb_xkb_get_controls_cookie_t get_controls_cookie =
xcb_xkb_get_controls(conn, device_id);
bool had_error = false;
had_error |= !get_map(keymap, conn, get_map_cookie);
had_error |= !get_indicator_map(keymap, conn, indicator_map_cookie);
had_error |= !get_compat_map(keymap, conn, compat_map_cookie);
had_error |= !get_names(keymap, &interner, get_names_cookie);
had_error |= !get_controls(keymap, conn, get_controls_cookie);
x11_atom_interner_round_trip(&interner);
had_error |= interner.had_error;
if (had_error) {
xkb_keymap_unref(keymap);
return NULL;
}

View File

@ -21,6 +21,8 @@
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include "x11-priv.h"
static bool

Some files were not shown because too many files have changed in this diff Show More