/
niceSOFT
/
kbd
Обзор
Документация
Войти
/
niceSOFT
/
kbd
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/libkeymap/parser.y
435 строк
10 KB
Nicolas Pitre
Add Backtab keysym and update keymaps to use it for Shift+Tab
22 фев 2026, 20:24
Не верифицирован
22 фев 2026, 20:24
5416a19
Код
Авторство
О чём код?
/* parser.y * * This file is part of kbd project. * Copyright (C) 1993 Risto Kankkunen. * Copyright (C) 1993 Eugene G. Crosser. * Copyright (C) 1994-2007 Andries E. Brouwer. * Copyright (C) 2007-2013 Alexey Gladkov <gladkov.alexey@gmail.com> * * This file is covered by the GNU General Public License, * which should be included with kbd as the file COPYING. */ %{ #include "config.h" #include "array_size.h" #include "contextP.h" #include "ksyms.h" #include "modifiers.h" #include "parser.h" #include "analyze.h" %} %code requires { #include <kbdfile.h> #include "keymap.h" #ifndef STRDATA_STRUCT #define STRDATA_STRUCT #define MAX_PARSER_STRING 512 // Maximum length of kbsentry.kb_string struct string { size_t str_len; char str_data[MAX_PARSER_STRING]; }; #endif } %language "C" %defines %debug %define parse.error verbose /* Pure yylex. */ %define api.pure %lex-param { yyscan_t scanner } /* Pure yyparse. */ %parse-param { void *scanner } %parse-param { struct lk_ctx *ctx } %token EOL NUMBER LITERAL CHARSET KEYMAPS KEYCODE EQUALS %token PLAIN SHIFT CONTROL ALT ALTGR SHIFTL SHIFTR CTRLL CTRLR CAPSSHIFT %token COMMA DASH STRING STRLITERAL COMPOSE TO CCHAR ERROR PLUS %token UNUMBER ALT_IS_META STRINGS AS USUAL ON FOR %union { int num; struct string str; } %type <str> STRLITERAL %type <num> CCHAR %type <num> LITERAL %type <num> NUMBER %type <num> UNUMBER %type <num> compsym %type <num> rvalue %{ static int yyerror(yyscan_t scanner KBD_ATTR_UNUSED, struct lk_ctx *ctx, const char *s) { ERR(ctx, "%s", s); return 0; } static int strings_as_usual(struct lk_ctx *ctx) { /* * 26 strings, mostly inspired by the VT100 family */ const char *stringvalues[] = { /* F1 .. F20 */ "\033[[A", "\033[[B", "\033[[C", "\033[[D", "\033[[E", "\033[17~", "\033[18~", "\033[19~", "\033[20~", "\033[21~", "\033[23~", "\033[24~", "\033[25~", "\033[26~", "\033[28~", "\033[29~", "\033[31~", "\033[32~", "\033[33~", "\033[34~", /* Find, Insert, Remove, Select, Prior */ "\033[1~", "\033[2~", "\033[3~", "\033[4~", "\033[5~", /* Next, Macro, Help, Do, Pause */ "\033[6~", NULL, NULL, NULL, NULL }; unsigned char i; for (i = 0; i < ARRAY_SIZE(stringvalues); i++) { if (stringvalues[i]) { struct kbsentry ke; ke.kb_func = i; strlcpy((char *)ke.kb_string, stringvalues[i], sizeof(ke.kb_string)); if (lk_add_func(ctx, &ke) == -1) return -1; } } /* * Backtab (Shift+Tab) is assigned to KT_FN index 255, the last * available slot with no kernel UAPI name (K_F245 = KT_FN index 254 * is the last kernel-defined entry). It cannot be added to the array * above without displacing the existing named entries F21..F245. */ { struct kbsentry ke; ke.kb_func = 255; /* Backtab, see syms.ktyp.h */ strlcpy((char *)ke.kb_string, "\033[Z", sizeof(ke.kb_string)); if (lk_add_func(ctx, &ke) == -1) return -1; } return 0; } static int compose_as_usual(struct lk_ctx *ctx, char *charset) { struct lk_kbdiacr def_latin1_composes[] = { { '`' , 'A', 0300 }, { '`' , 'a', 0340 }, { '\'', 'A', 0301 }, { '\'', 'a', 0341 }, { '^' , 'A', 0302 }, { '^' , 'a', 0342 }, { '~' , 'A', 0303 }, { '~' , 'a', 0343 }, { '"' , 'A', 0304 }, { '"' , 'a', 0344 }, { 'O' , 'A', 0305 }, { 'o' , 'a', 0345 }, { '0' , 'A', 0305 }, { '0' , 'a', 0345 }, { 'A' , 'A', 0305 }, { 'a' , 'a', 0345 }, { 'A' , 'E', 0306 }, { 'a' , 'e', 0346 }, { ',' , 'C', 0307 }, { ',' , 'c', 0347 }, { '`' , 'E', 0310 }, { '`' , 'e', 0350 }, { '\'', 'E', 0311 }, { '\'', 'e', 0351 }, { '^' , 'E', 0312 }, { '^' , 'e', 0352 }, { '"' , 'E', 0313 }, { '"' , 'e', 0353 }, { '`' , 'I', 0314 }, { '`' , 'i', 0354 }, { '\'', 'I', 0315 }, { '\'', 'i', 0355 }, { '^' , 'I', 0316 }, { '^' , 'i', 0356 }, { '"' , 'I', 0317 }, { '"' , 'i', 0357 }, { '-' , 'D', 0320 }, { '-' , 'd', 0360 }, { '~' , 'N', 0321 }, { '~' , 'n', 0361 }, { '`' , 'O', 0322 }, { '`' , 'o', 0362 }, { '\'', 'O', 0323 }, { '\'', 'o', 0363 }, { '^' , 'O', 0324 }, { '^' , 'o', 0364 }, { '~' , 'O', 0325 }, { '~' , 'o', 0365 }, { '"' , 'O', 0326 }, { '"' , 'o', 0366 }, { '/' , 'O', 0330 }, { '/' , 'o', 0370 }, { '`' , 'U', 0331 }, { '`' , 'u', 0371 }, { '\'', 'U', 0332 }, { '\'', 'u', 0372 }, { '^' , 'U', 0333 }, { '^' , 'u', 0373 }, { '"' , 'U', 0334 }, { '"' , 'u', 0374 }, { '\'', 'Y', 0335 }, { '\'', 'y', 0375 }, { 'T' , 'H', 0336 }, { 't' , 'h', 0376 }, { 's' , 's', 0337 }, { '"' , 'y', 0377 }, { 's' , 'z', 0337 }, { 'i' , 'j', 0377 } }; if (charset && strcmp(charset, "iso-8859-1")) { ERR(ctx, _("loadkeys: don't know how to compose for %s"), charset); return -1; } for (unsigned int i = 0; i < ARRAY_SIZE(def_latin1_composes); i++) { if (lk_append_compose(ctx, &def_latin1_composes[i]) == -1) return -1; } return 0; } %} %% keytable : | keytable line ; line : EOL | charsetline | altismetaline | usualstringsline | usualcomposeline | keymapline | singleline | strline | compline ; charsetline : CHARSET STRLITERAL EOL { if (lk_set_charset(ctx, $2.str_data)) { ERR(ctx, _("unknown charset %s - ignoring charset request\n"), $2.str_data); YYERROR; } ctx->keywords |= LK_KEYWORD_CHARSET; /* Unicode: The first 256 code points were made identical to the content of ISO 8859-1 */ if (ctx->flags & LK_FLAG_PREFER_UNICODE && !strcasecmp($2.str_data, "iso-8859-1")) ctx->flags ^= LK_FLAG_PREFER_UNICODE; } ; altismetaline : ALT_IS_META EOL { ctx->keywords |= LK_KEYWORD_ALTISMETA; } ; usualstringsline: STRINGS AS USUAL EOL { if (strings_as_usual(ctx) == -1) YYERROR; ctx->keywords |= LK_KEYWORD_STRASUSUAL; } ; usualcomposeline: COMPOSE AS USUAL FOR STRLITERAL EOL { if (compose_as_usual(ctx, $5.str_data) == -1) YYERROR; } | COMPOSE AS USUAL EOL { if (compose_as_usual(ctx, NULL) == -1) YYERROR; } ; keymapline : KEYMAPS range EOL { ctx->keywords |= LK_KEYWORD_KEYMAPS; } ; range : range COMMA range0 | range0 ; range0 : NUMBER DASH NUMBER { int i; for (i = $1; i <= $3; i++) { if (lk_add_map(ctx, i) == -1) YYERROR; } } | NUMBER { if (lk_add_map(ctx, $1) == -1) YYERROR; } ; strline : STRING LITERAL EQUALS STRLITERAL EOL { struct kbsentry ke; if (KTYP($2) != KT_FN) { ERR(ctx, _("'%s' is not a function key symbol"), get_sym(ctx, KTYP($2), KVAL($2))); YYERROR; } ke.kb_func = (unsigned char) KVAL($2); strlcpy((char *) ke.kb_string, $4.str_data, sizeof(ke.kb_string)); if (lk_add_func(ctx, &ke) == -1) YYERROR; } ; compline : COMPOSE compsym compsym TO CCHAR EOL { struct lk_kbdiacr ptr; ptr.diacr = (unsigned int) $2; ptr.base = (unsigned int) $3; ptr.result = (unsigned int) $5; if (lk_append_compose(ctx, &ptr) == -1) YYERROR; } | COMPOSE compsym compsym TO rvalue EOL { struct lk_kbdiacr ptr; ptr.diacr = (unsigned int) $2; ptr.base = (unsigned int) $3; ptr.result = (unsigned int) $5; if (lk_append_compose(ctx, &ptr) == -1) YYERROR; } ; compsym : CCHAR { $$ = $1; } | UNUMBER { $$ = U($1); } ; singleline : KEYCODE NUMBER EQUALS rvalue0 EOL { int j, i, keycode; int *val; if (ctx->key_line->count == 1) { char one = 1; /* Some files do not have a keymaps line, and * we have to wait until all input has been read * before we know which maps to fill. */ if (lk_array_set(ctx->key_constant, $2, &one) < 0) { ERR(ctx, _("out of memory")); YYERROR; } /* On the other hand, we now have include files, * and it should be possible to override lines * from an include file. So, kill old defs. */ for (j = 0; j < ctx->keymap->total; j++) { if (!lk_map_exists(ctx, j)) continue; if (lk_del_key(ctx, j, $2) < 0) YYERROR; } } if (ctx->keywords & LK_KEYWORD_KEYMAPS) { i = 0; for (j = 0; j < ctx->keymap->total; j++) { if (!lk_map_exists(ctx, j)) continue; if (ctx->key_line->count != 1 || i == 0) { keycode = K_HOLE; if (i < ctx->key_line->count) { val = lk_array_get(ctx->key_line, i); keycode = *val; } if (lk_add_key(ctx, j, $2, keycode) < 0) YYERROR; } i++; } if (i < ctx->key_line->count) { ERR(ctx, _("too many (%ld) entries on one line"), ctx->key_line->count); YYERROR; } } else { for (i = 0; i < ctx->key_line->count; i++) { val = lk_array_get(ctx->key_line, i); if (lk_add_key(ctx, i, $2, *val) < 0) YYERROR; } } } | modifiers KEYCODE NUMBER EQUALS rvalue EOL { if (lk_add_key(ctx, ctx->mod, $3, $5) < 0) YYERROR; ctx->mod = 0; } | PLAIN KEYCODE NUMBER EQUALS rvalue EOL { if (lk_add_key(ctx, 0, $3, $5) < 0) YYERROR; ctx->mod = 0; } ; modifiers : modifiers modifier | modifier ; modifier : SHIFT { ctx->mod |= M_SHIFT; } | CONTROL { ctx->mod |= M_CTRL; } | ALT { ctx->mod |= M_ALT; } | ALTGR { ctx->mod |= M_ALTGR; } | SHIFTL { ctx->mod |= M_SHIFTL; } | SHIFTR { ctx->mod |= M_SHIFTR; } | CTRLL { ctx->mod |= M_CTRLL; } | CTRLR { ctx->mod |= M_CTRLR; } | CAPSSHIFT { ctx->mod |= M_CAPSSHIFT; } ; ; rvalue0 : | rvalue1 rvalue0 ; rvalue1 : rvalue { int val = $1; if (lk_array_append(ctx->key_line, &val) < 0) { ERR(ctx, _("out of memory")); YYERROR; } } ; rvalue : NUMBER { $$ = convert_code(ctx, $1, TO_AUTO); } | PLUS NUMBER { $$ = add_capslock(ctx, $2); } | UNUMBER { $$ = convert_code(ctx, U($1), TO_AUTO); } | PLUS UNUMBER { $$ = add_capslock(ctx, U($2)); } | LITERAL { $$ = $1; } | PLUS LITERAL { $$ = add_capslock(ctx, $2); } ; %% int lk_parse_keymap(struct lk_ctx *ctx, struct kbdfile *fp) { yyscan_t scanner; int ret = 0; INFO(ctx, _("Loading %s"), kbdfile_get_pathname(fp)); ctx->mod = 0; yylex_init_extra(ctx, &scanner); ret = ret ?: stack_push(ctx, fp, scanner); ret = ret ?: yyparse(scanner, ctx); stack_pop(ctx, scanner); yylex_destroy(scanner); return (ret ? -1 : 0); }