diff options
Diffstat (limited to 'console-client/xkb/parser.y')
-rw-r--r-- | console-client/xkb/parser.y | 1529 |
1 files changed, 1529 insertions, 0 deletions
diff --git a/console-client/xkb/parser.y b/console-client/xkb/parser.y new file mode 100644 index 00000000..9fe2a394 --- /dev/null +++ b/console-client/xkb/parser.y @@ -0,0 +1,1529 @@ +/* parser.y -- XKB parser. + + Copyright (C) 2003, 2004 Marco Gerards + + Written by Marco Gerards <marco@student.han.nl> + + 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 of the License, 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. */ + +%{ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include "xkb.h" + +void yyerror(char *); +int yylex (void); +static error_t include_section (char *incl, int sectionsymbol, char *dirname, + mergemode); +static error_t include_sections (char *incl, int sectionsymbol, char *dirname, + mergemode); +void close_include (); +static void skipsection (void); +static error_t set_default_action (struct xkb_action *, struct xkb_action **); +static void key_set_keysym (struct key *key, group_t group, int level, + symbol ks); +static void key_new (char *keyname); +static void key_delete (char *keyname); +void scanner_unput (int c); +static void remove_symbols (struct key *key, group_t group); + +struct xkb_interpret *current_interpretation; +struct xkb_action *current_action; +struct xkb_indicator indi; +struct xkb_indicator *current_indicator = &indi; +struct key defkey; +struct key *default_key = &defkey; + +/* The default settings for actions. */ +struct xkb_action default_setmods = { SA_SetMods }; +struct xkb_action default_lockmods = { SA_LockMods }; +struct xkb_action default_latchmods = { SA_LatchMods }; +struct xkb_action default_setgroup = { SA_SetGroup }; +struct xkb_action default_latchgroup = { SA_LatchGroup }; +struct xkb_action default_lockgroup = { SA_LockGroup }; +struct xkb_action default_moveptr = { SA_MovePtr }; +struct xkb_action default_ptrbtn = { SA_PtrBtn }; +struct xkb_action default_lockptrbtn = { SA_LockPtrBtn }; +struct xkb_action default_ptrdflt = { SA_SetPtrDflt }; +struct xkb_action default_setcontrols = { SA_SetControls }; +struct xkb_action default_lockcontrols = { SA_LockControls }; +struct xkb_action default_isolock = { SA_ISOLock }; +struct xkb_action default_switchscrn = { SA_SwitchScreen }; +struct xkb_action default_consscroll = { SA_ConsScroll }; + +static struct key *current_key; + +/* The dummy gets used when the original may not be overwritten. */ +static struct key dummy_key; + +/* The current parsed group. */ +static int current_group; +static int current_rmod = 0; + +/* The current symbol in the currently parsed key. */ +static int symbolcnt; +static int actioncnt; + +mergemode merge_mode = override; + +//#define YYDEBUG 1 + +static struct keytype *current_keytype; +%} + +%union { + int val; + char *str; + modmap_t modmap; + struct xkb_action *action; + double dbl; + mergemode mergemode; +} + +%token XKBKEYMAP "xkb_keymap" +%token XKBKEYCODES "xkb_keycodes" +%token XKBCOMPAT "xkb_compatibility" +%token XKBGEOMETRY "xkb_geometry" +%token XKBTYPES "xkb_types" +%token XKBSYMBOLS "xkb_symbols" +%token STR +%token HEX +%token FLAGS +%token KEYCODE +%token NUM +%token MINIMUM "minimum" +%token MAXIMUM "maximum" +%token VIRTUAL "virtual" +%token INDICATOR "indicator" +%token ALIAS "alias" +%token IDENTIFIER +%token VMODS "virtualmods" +%token TYPE "type" +%token DATA "data" +%token MAP "map" +%token LEVEL_NAME "level_name" +%token PRESERVE "preserve" +%token LEVEL +%token USEMODMAP "usemodmap" +%token REPEAT "repeat" +%token LOCKING "locking" +%token VIRTUALMODIFIER "virtualmod" +%token BOOLEAN +%token INTERPRET "interpret" +%token INTERPMATCH +%token CLEARLOCKS "clearlocks" +%token MODS "mods" +%token SETMODS "setmods" +%token LATCHMODS "latchmods" +%token LOCKMODS "lockmods" +%token ACTION "action" +%token LATCHTOLOCK "latchtolock" +%token GROUP "group" +%token GROUPS "groups" +%token SETGROUP "setgroup" +%token LATCHGROUP "latchgroup" +%token LOCKGROUP "lockgroup" +%token ACCEL "accel" +%token MOVEPTR "moveptr" +%token PRIVATE "private" +%token BUTTON "button" +%token BUTTONNUM +%token DEFAULT "default" +%token COUNT "count" +%token PTRBTN "ptrbtn" +%token DEFAULTBTN "defaultbutton" +%token ALL "all" +%token NONE "none" +%token ANY "any" +%token CONTROLFLAG +%token AFFECT "affect" +%token PTRDFLT "setptrdflt" +%token LOCKPTRBTN "lockptrbtn" +%token SETCONTROLS "setcontrols" +%token LOCKCONTROLS "lockcontrols" +%token CONTROLS "controls" +%token TERMINATE "terminate" +%token WHICHMODSTATE "whichmodstate" +%token WHICHGROUPSTATE "whichgroupstate" +%token WHICHSTATE "whichstate" +%token INDEX "index" +%token ALLOWEXPLICIT "allowexplicit" +%token DRIVESKBD "driveskbd" +//%token AFFECTBTNLOCK +%token SYMBOLS "symbols" +%token NAME "name" +%token GROUPNUM +%token ACTIONS "actions" +%token KEY "key" +%token MODMAP "modifier_map" +%token SHIFT "shift" +%token LOCK "lock" +%token CONTROL "control" +%token MOD1 "mod1" +%token MOD2 "mod2" +%token MOD3 "mod3" +%token MOD4 "mod4" +%token MOD5 "mod5" +%token UNLOCK "unlock" +%token BOTH "both" +%token NEITHER "neither" + +%token INCLUDE "include" +%token AUGMENT "augment" +%token OVERRIDE "override" +%token REPLACE "replace" + + +%token ISOLOCK "isolock" +%token POINTERS "pointers" +%token NOACTION "noaction" +%token GROUPSWRAP "groupswrap" +%token GROUPSCLAMP "groupsclamp" +%token GROUPSREDIRECT "groupsredirect" +%token OVERLAY "overlay" +%token SWITCHSCREEN "switchscreen" +%token SAMESERVER "sameserver" +%token SCREEN "screen" +%token LINE "line" +%token PERCENT "percent" +%token CONSSCROLL "consscroll" +%token FLOAT "float" +%type <str> STR KEYCODE IDENTIFIER +%type <val> FLAGS NUM HEX vmod level LEVEL rmod BOOLEAN symbol INTERPMATCH +%type <val> clearlocks usemodmap latchtolock noaccel button BUTTONNUM +%type <val> ctrlflags allowexplicit driveskbd +%type <val> DRIVESKBD GROUPNUM group symbolname groups whichstate WHICHSTATE +/* Booleans */ +%type <val> locking repeat groupswrap groupsclamp sameserver +%type <modmap> mods +%type <action> action +%type <action> ctrlparams +%type <mergemode> include +%type <dbl> FLOAT +//%debug + +%% +/* A XKB keymap. */ +xkbkeymap: + "xkb_keymap" '{' keymap '}' ';' { YYACCEPT } +| "xkb_keymap" STR '{' keymap '}' ';' { YYACCEPT } +| '{' keymap '}' { YYACCEPT } ';' +; + +/* A XKB configuration has many sections. */ +keymap: + /* empty */ +| keymap types +| keymap keycodes +| keymap compat +| keymap symbols +| keymap geometry +; + +include: + "include" { $$ = defaultmm } +| "augment" { $$ = augment } +| "replace" { $$ = replace } +| "override" { $$= override } +; + +/* All flags assigned to a section. */ +flags: + /* empty */ +| flags FLAGS +; + +/* The header of a keycode section. */ +keycodes: + flags "xkb_keycodes" '{' keycodesect '}' ';' +| flags "xkb_keycodes" STR '{' keycodesect '}' ';' +; + +/* Process the includes on the stack. */ +keycodesinclude: + '{' keycodesect '}' { close_include () } +| keycodesinclude '{' keycodesect '}' { close_include () } +; + +/* The first lines of a keycode section. The amount of keycodes are + declared here. */ +keycodesect: +/* empty */ +| "minimum" '=' NUM ';' keycodesect + { + min_keys = $3; + current_key = &keys[$3]; + } +| MAXIMUM '=' NUM ';' keycodesect + { + max_keys = $3; + keys = calloc ($3, sizeof (struct key)); + } +| KEYCODE '=' NUM ';' + { keyname_add ($1, $3); } + keycodesect +| "replace" KEYCODE '=' NUM ';' + { keyname_add ($2, $4); } + keycodesect +| "indicator" NUM '=' STR ';' keycodesect { } +| "virtual" INDICATOR NUM '=' STR ';' keycodesect +| "alias" KEYCODE '=' KEYCODE ';' + { + keycode_t key = keyname_find ($4); + if (key) + keyname_add ($2, key); + else + { + key = keyname_find ($2); + if (key) + keyname_add ($4, key); + } + } + keycodesect +| include STR + { include_sections ($2, XKBKEYCODES, "keycodes", $1); } + keycodesinclude keycodesect +; + +/* The header of a keytypes section. */ +types: + flags "xkb_types" '{' typessect '}' ';' +| flags "xkb_types" STR '{' typessect '}' ';' +; + +/* A list of virtual modifier declarations (see vmods_def), seperated + by commas. */ +vmodslist: + IDENTIFIER { vmod_add ($1); } +| vmodslist ',' IDENTIFIER { vmod_add ($3) } +; + +/* Virtual modifiers must be declared before they can be used. */ +vmods_def: + "virtualmods" vmodslist ';' +; + +/* Return the number of the virtual modifier. */ +vmod: + IDENTIFIER { $$ = vmod_find ($1); } +; + +/* A single realmodifier. */ +rmod: + "shift" { $$ = RMOD_SHIFT } +| "lock" { $$ = RMOD_LOCK } +| "control" { $$ = RMOD_CTRL } +| "mod1" { $$ = RMOD_MOD1 } +| "mod2" { $$ = RMOD_MOD2 } +| "mod3" { $$ = RMOD_MOD3 } +| "mod4" { $$ = RMOD_MOD4 } +| "mod5" { $$ = RMOD_MOD5 } +; + +/* One of more modifiers, seperated by '+'. A modmap_t will return all real + and virtual modifiers specified. */ +mods: + mods '+' rmod { $$.rmods = $1.rmods | $3; } +| mods '+' vmod { $$.vmods = $1.vmods | $3; } + /* Use a mid-rule action to start with no modifiers. */ +| { $$.rmods = 0; $$.vmods = 0 } rmod { $$.rmods = $2; } +| { $$.rmods = 0; $$.vmods = 0 } vmod { $$.vmods = $2; } +| "all" { $$.rmods = 0xFF; $$.vmods = 0xFFFF} +| "none" { $$.rmods = 0; $$.vmods = 0 } +; + +/* The numeric level starts with 0. Level1-Level4 returns 0-3, also + numeric values can be used to describe a level. */ +level: + LEVEL { $$ = $1 - 1 } +| "any" { $$ = 0 } +| NUM { $$ = $1 - 1 } +; + +/* A single keytype. */ +type: + /* Empty */ +| type MODS '=' mods ';' + { current_keytype->modmask = $4 } +| type MAP '[' mods ']' '=' level ';' + { keytype_mapadd (current_keytype, $4, $7) } +| type "level_name" '[' level ']' '=' STR ';' +| type "preserve" '[' mods ']' '=' mods ';' + { keytype_preserve_add (current_keytype, $4, $7) } +; + +/* Process the includes on the stack. */ +typesinclude: + '{' typessect '}' { close_include () } +| typesinclude '{' typessect '}' { close_include () } +; + +/* A keytype section contains keytypes and virtual modifier declarations. */ +typessect: + /* Empty */ +| typessect vmods_def +| typessect TYPE STR { keytype_new ($3, ¤t_keytype) }'{' type '}' ';' { } +| typessect include STR + { include_sections ($3, XKBTYPES, "types", $2) } + typesinclude +; + +/* The header of a compatibility section. */ +compat: + flags "xkb_compatibility" '{' compatsect '}' ';' +| flags "xkb_compatibility" STR '{' compatsect '}' ';' +; + +/* XXX: A symbol can be more than just an identifier (hex). */ +symbol: + IDENTIFIER { $$ = (int) XStringToKeysym ( $1) ? : -1; } +| ANY { $$ = 0 } +| error { yyerror ("Invalid symbol.") } +; + +/* Which kinds of modifiers (like base, locked, etc.) can affect the + indicator. */ +whichstate: + WHICHSTATE { $$ = $1 } +| "none" { $$ = 0 } +| "any" { $$ = 0xff } /* XXX */ +; + +/* The groups that can affect a indicator. */ +groups: + groups '+' group +| groups '-' group +| group {} +| "all" { $$ = 0xff } /* XXX */ +; + +indicators: +/* empty */ +| indicators indicator +; + +/* An indicator desciption. */ +indicator: + "mods" '=' mods ';' { current_indicator->modmap = $3 } +| "groups" '=' groups ';' { current_indicator->groups = $3 } +| "controls" '=' ctrls ';' +| "whichmodstate" '=' whichstate ';' { current_indicator->which_mods = $3 } +| "whichgroupstate" '=' whichstate ';' { current_indicator->which_mods = $3 } +| allowexplicit ';' {} /* Ignored for now. */ +| driveskbd ';' {} +| "index" '=' NUM ';' {} +; + +/* Boolean for allowexplicit. */ +allowexplicit: + '~' "allowexplicit" { $$ = 0 } +| '!' "allowexplicit" { $$ = 0 } +| "allowexplicit" { $$ = 1 } +| "allowexplicit" '=' BOOLEAN { $$ = $3 } +; + +/* Boolean for driveskbd. */ +driveskbd: + '~' "driveskbd" { $$ = 0 } +| '!' "driveskbd" { $$ = 0 } +| "driveskbd" { $$ = 1 } +| "driveskbd" '=' BOOLEAN { $$ = $3 } +; + +interprets: + /* Empty */ +| interprets interpret +; + +/* A single interpretation. */ +interpret: + "usemodmap" '=' level ';' + { current_interpretation->match &= 0x7F | ($3 << 7) } /* XXX */ +| repeat ';' + { + current_interpretation->flags &= ~(KEYREPEAT | KEYNOREPEAT); + current_interpretation->flags |= $1; + } +| locking ';' {} +| "virtualmod" '=' vmod ';' { current_interpretation->vmod = $3 } +| "action" '=' action ';' + { + memcpy (¤t_interpretation->action, $3, sizeof (xkb_action_t)); + free ($3); + } +; + +/* Process the includes on the stack. */ +compatinclude: + '{' compatsect '}' { close_include () } +| compatinclude '{' compatsect '}' { close_include () } +; + +/* The body of a compatibility section. */ +compatsect: + /* Empty */ +| compatsect vmods_def +| compatsect "interpret" '.' + { current_interpretation = &default_interpretation } + interpret +| compatsect "interpret" symbol + { + if ($3 != -1) + { + interpret_new (¤t_interpretation, $3); + current_interpretation->match |= 1; + } + } + '{' interprets '}' ';' +| compatsect "interpret" symbol '+' rmod + { + if ($3 != -1) + { + interpret_new (¤t_interpretation, $3); + current_interpretation->rmods = $5; + current_interpretation->match |= 4; + } + } + '{' interprets '}' ';' +| compatsect "interpret" symbol '+' "any" + { + if ($3 != -1) + { + interpret_new (¤t_interpretation, $3); + current_interpretation->rmods = 255; + current_interpretation->match |= 2; + } + } + '{' interprets '}' ';' +| compatsect "interpret" symbol '+' INTERPMATCH '(' mods ')' + { + if ($3 != -1) + { + interpret_new (¤t_interpretation, $3); + current_interpretation->rmods = $7.rmods; + current_interpretation->match |= $5; + } + } + '{' interprets '}' ';' +| compatsect GROUP NUM '=' mods ';' +| compatsect "indicator" STR '{' indicators '}' ';' +| compatsect include STR + { include_sections ($3, XKBCOMPAT, "compat", $2) } + compatinclude +| compatsect actiondef +| compatsect "indicator" '.' indicator +; + + + /* Booleans */ +/* Boolean for clearlocks. */ +clearlocks: + '~' "clearlocks" { $$ = 0 } +| '!' "clearlocks" { $$ = 0 } +| "clearlocks" { $$ = 1 } +| "clearlocks" '=' BOOLEAN { $$ = $3 } +; + +/* Boolean for latchtolock. */ +latchtolock: + '~' "latchtolock" { $$ = 0 } +| '!' "latchtolock" { $$ = 0 } +| "latchtolock" { $$ = 1 } +| "latchtolock" '=' BOOLEAN { $$ = $3 } +; + +/* Boolean for useModMap. */ +usemodmap: + '~' "usemodmap" { $$ = 0 } +| '!' "usemodmap" { $$ = 0 } +| "usemodmap" { $$ = 1 } +| "usemodmap" '=' BOOLEAN { $$ = $3 } +; + +/* Boolean for locking. */ +locking: + '~' "locking" { $$ = 0 } +| '!' "locking" { $$ = 0 } +| "locking" { $$ = 1 } +| "locking" '=' BOOLEAN { $$ = $3 } +; + +/* Boolean for repeat. */ +repeat: + '~' "repeat" { $$ = KEYNOREPEAT } +| '!' "repeat" { $$ = KEYNOREPEAT } +| "repeat" { $$ = KEYREPEAT } +| "repeat" '=' BOOLEAN + { + if ($3) + $$ = KEYREPEAT; + else + $$ = KEYNOREPEAT; + } +; + +/* Boolean for groupswrap. */ +groupswrap: + '~' "groupswrap" { $$ = 0 } +| '!' "groupswrap" { $$ = 0 } +| "groupswrap" { $$ = 1 } +| "groupswrap" '=' BOOLEAN { $$ = $3 } +; + +/* Boolean for groupsclamp. */ +groupsclamp: + '~' "groupsclamp" { $$ = 0 } +| '!' "groupsclamp" { $$ = 0 } +| "groupsclamp" { $$ = 1 } +| "groupsclamp" '=' BOOLEAN { $$ = $3 } +; + +/* Boolean for noaccel. */ +noaccel: + '~' "accel" { $$ = 0 } +| '!' "accel" { $$ = 0 } +| "accel" { $$ = 1 } +| "accel" '=' BOOLEAN { $$ = $3 } +; + + +sameserver: + '~' "sameserver" { $$ = 0 } +| '!' "sameserver" { $$ = 0 } +| "sameserver" { $$ = 1 } +| "sameserver" '=' BOOLEAN { $$ = $3 } +; + +setmodsparams: + /* empty */ +| setmodsparam +| setmodsparams ',' setmodsparam +; + + +/* Parameter for the (Set|Lock|Latch)Mods action. */ +setmodsparam: + "mods" '=' mods + { + ((action_setmods_t *) current_action)->modmap = $3; + } +| "mods" '=' "usemodmap" + { ((action_setmods_t *) current_action)->flags |= useModMap; + } +| clearlocks + { + ((action_setmods_t *) current_action)->flags &= ~clearLocks; + ((action_setmods_t *) current_action)->flags |= $1; + } +| usemodmap + { + ((action_setmods_t *) current_action)->flags &= ~useModMap; + ((action_setmods_t *) current_action)->flags |= $1; + } +| latchtolock + { + ((action_setmods_t *) current_action)->flags &= ~latchToLock; + ((action_setmods_t *) current_action)->flags |= $1; + } +; + +setgroupparams: +/* empty */ +| setgroupparam +| setgroupparams ',' setgroupparam +; + +/* Parameter for the (Set|Lock|Latch)Group action. */ +setgroupparam: + "group" '=' NUM + { + ((action_setgroup_t *) current_action)->group = $3; + ((action_setgroup_t *) current_action)->flags |= groupAbsolute; + } +| "group" '=' '+' NUM + { + ((action_setgroup_t *) current_action)->group = $4; + } +| "group" '=' '-' NUM + { + ((action_setgroup_t *) current_action)->group = -$4; + } +| clearlocks + { + ((action_setgroup_t *) current_action)->flags |= $1; + } +| latchtolock + { + ((action_setgroup_t *) current_action)->flags |= $1; + } +; + +moveptrparams: +/* empty */ +| moveptrparam +| moveptrparams ',' moveptrparam +; + +/* Parameters for the MovePtr action. */ +moveptrparam: + IDENTIFIER '=' NUM + { + ((action_moveptr_t *) current_action)->x = $3; + ((action_setgroup_t *) current_action)->flags |= MoveAbsoluteX; + } +| IDENTIFIER '=' '+' NUM + { + ((action_moveptr_t *) current_action)->x = $4; + } +| IDENTIFIER '=' '-' NUM + { + ((action_moveptr_t *) current_action)->x = -$4; + } +| noaccel + { + ((action_moveptr_t *) current_action)->flags |= NoAcceleration; + } +; + +/* A mouse button. */ +button: + NUM { $$ = $1 } +| BUTTONNUM { $$ = $1 } +| "default" { $$ = 0 } +; + +affectbtnlock: + "lock" +| "unlock" +| "both" +| "neither" +; + +ptrbtnparams: + /* empty */ +| ptrbtnparam +| ptrbtnparams ',' ptrbtnparam +; + +/* Parameters for the (Set|Lock|Latch)PtrBtn action. */ +ptrbtnparam: + "button" '=' button + { ((action_ptrbtn_t *) current_action)->button = $3; } +| "count" '=' NUM + { ((action_ptrbtn_t *) current_action)->count = $3; } +| "affect" '=' affectbtnlock + { + // ((action_ptrbtn_t *) $$)->a = $3; + } +; + +/* XXX: This should be extended. */ +affectbtns: + "defaultbutton" +| "button" +| "all" +; + +ptrdfltparams: +/* empty */ +| ptrdfltparam +| ptrdfltparams ',' ptrdfltparam +; + +/* Parameters for the SetPtrDflt action. */ +ptrdfltparam: + "button" '=' button { } +| "button" '=' '+' button { } +| "button" '=' '-' button { } +| "affect" '=' affectbtns { } +; + +/* A list of controlflags. */ +ctrls: + ctrls '+' CONTROLFLAG// { $$ |= $3 } +| CONTROLFLAG// { $$ = $1 } +| OVERLAY +; + +/* Modified controlflags. */ +ctrlflags: + ctrls { /*$$ = $1*/ } +| "all" { $$ = 0xFFFF } +| "none" { $$ = 0 } +; + +/* The parameters of a (Set|Lock|Latch)Ctrls Action. */ +ctrlparams: + "controls" '=' ctrlflags + { /* ((action_setcontrols_t *) $$)->controls = $3; */ } +; + +isoaffect: + "mods" +| "groups" +| "controls" +| "pointers" +| "all" +| "none" +; + +isolockparams: +/* empty */ +| isolockparam +| isolockparams ',' isolockparam +; + +/* Parameters for the ISOLock action. */ +isolockparam: + "mods" '=' mods +| "mods" '=' USEMODMAP +| "group" '=' group +| "controls" '=' ctrlflags +| "affect" '=' isoaffect +; + +switchscrnparams: + switchscrnparam + | switchscrnparams ',' switchscrnparam +; + +/* Parameters for the SwitchScreen action. */ +switchscrnparam: + "screen" '=' NUM + { + ((action_switchscrn_t *) current_action)->screen = $3; + ((action_switchscrn_t *) current_action)->flags |= screenAbs; + } +| "screen" '+' '=' NUM + { + ((action_switchscrn_t *) current_action)->screen = $4; + } +| "screen" '-' '=' NUM + { + ((action_switchscrn_t *) current_action)->screen = -$4; + } +| sameserver + { + /* XXX: Implement this. */ +/* ((action_switchscrn_t *) current_action)->flags &= ~0; */ +/* ((action_switchscrn_t *) current_action)->flags |= $1; */ + } +; + +consscrollparams: + consscrollparam + | consscrollparams ',' consscrollparam +; + +/* Parameters for the ConsScroll action. */ +consscrollparam: + "screen" '+' '=' FLOAT + { + ((action_consscroll_t *) current_action)->screen = $4; + } +| "screen" '-' '=' FLOAT + { + ((action_consscroll_t *) current_action)->screen = -$4; + } +| "line" '=' NUM + { + ((action_consscroll_t *) current_action)->line = $3; + ((action_consscroll_t *) current_action)->flags |= lineAbs; + } +| "line" '+' '=' NUM + { + ((action_consscroll_t *) current_action)->line = $4; + } +| "line" '-' '=' NUM + { + ((action_consscroll_t *) current_action)->line = -$4; + } +| "percent" '=' NUM + { + ((action_consscroll_t *) current_action)->percent = $3; + ((action_consscroll_t *) current_action)->flags |= usePercentage; + } +; + +privateparams: + /* empty */ + | privateparam + | privateparams ',' privateparam +; + +privateparam: + "type" '=' HEX + { + } +| "data" '=' STR + { + } +; + +/* An action definition. */ +action: + "setmods" + { + if (set_default_action (&default_setmods, ¤t_action)) + YYABORT; + } + '(' setmodsparams ')' { $$ = current_action } +| "latchmods" + { + if (set_default_action (&default_latchmods, ¤t_action)) + YYABORT; + } + '(' setmodsparams ')' { $$ = current_action } +| "lockmods" + { + if (set_default_action (&default_lockmods, ¤t_action)) + YYABORT; + } + '(' setmodsparams ')' { $$ = current_action } +| "setgroup" + { + if (set_default_action (&default_setgroup, ¤t_action)) + YYABORT; + } + '(' setgroupparams ')' { $$ = current_action } +| "latchgroup" + { + if (set_default_action (&default_latchgroup, ¤t_action)) + YYABORT; + } + '(' setgroupparams ')' { $$ = current_action } +| "lockgroup" + { + if (set_default_action (&default_lockgroup, ¤t_action)) + YYABORT; + } + '(' setgroupparams ')' { $$ = current_action } +| "moveptr" + { + if (set_default_action (&default_moveptr, ¤t_action)) + YYABORT; + } + '(' moveptrparams ')' { $$ = current_action } +| "ptrbtn" + { + if (set_default_action (&default_ptrbtn, ¤t_action)) + YYABORT; + } + '(' ptrbtnparams ')' { $$ = current_action } +| "lockptrbtn" + { + if (set_default_action (&default_lockptrbtn, ¤t_action)) + YYABORT; + } + '(' ptrbtnparams ')' { $$ = current_action } +| "setptrdflt" + { + if (set_default_action (&default_ptrdflt, ¤t_action)) + YYABORT; + } + '(' ptrdfltparams ')' { $$ = current_action } +| "setcontrols" + { + if (set_default_action (&default_setcontrols, ¤t_action)) + YYABORT; + } + '(' ctrlparams ')' { $$ = current_action } +| "lockcontrols" + { + if (set_default_action (&default_lockcontrols, ¤t_action)) + YYABORT; + } + '(' ctrlparams ')' { $$ = current_action } +| "terminate" '(' ')' + { $$ = calloc (1, sizeof (xkb_action_t)); $$->type = SA_TerminateServer } +| "switchscreen" + { + if (set_default_action (&default_switchscrn, ¤t_action)) + YYABORT; + } +'(' switchscrnparams ')' { $$ = current_action } +| "consscroll" + { + if (set_default_action (&default_consscroll, ¤t_action)) + YYABORT; + } + '(' consscrollparams ')' { $$ = current_action } +| "isolock" + { + if (set_default_action (&default_isolock, ¤t_action)) + YYABORT; + } + '(' isolockparams ')' { $$ = current_action } +| "private" '(' privateparams ')' + { $$ = calloc (1, sizeof (xkb_action_t)); $$->type = SA_NoAction } +| "noaction" '(' ')' + { $$ = calloc (1, sizeof (xkb_action_t)); $$->type = SA_NoAction } +| error ')' { yyerror ("Invalid action\n") } +; + +/* Define values for default actions. */ +actiondef: + "setmods" '.' { current_action = &default_setmods } setmodsparam ';' +| "latchmods" '.' { current_action = &default_latchmods } setmodsparam ';' +| "lockmods" '.' { current_action = &default_lockmods } setmodsparam ';' +| "setgroup" '.' { current_action = &default_setgroup } setgroupparam ';' +| "latchgroup" '.' { current_action = &default_latchgroup } setgroupparam ';' +| "lockgroup" '.' { current_action = &default_lockgroup } setgroupparam ';' +| "moveptr" '.' { current_action = &default_moveptr } moveptrparam ';' +| "ptrbtn" '.' { current_action = &default_ptrbtn } ptrbtnparam ';' +| "lockptrbtn" '.' { current_action = &default_lockptrbtn } ptrbtnparam ';' +| "setptrdflt" '.' { current_action = &default_ptrdflt } ptrdfltparam ';' +| "setcontrols" '.' { current_action = &default_setcontrols } ctrlparams ';' +| "lockcontrols" '.' { current_action = &default_lockcontrols } ctrlparams ';' +| "isolock" '.' { current_action = &default_isolock } isolockparam ';' +| "switchscreen" '.' { current_action = &default_switchscrn } switchscrnparam ';' +; + +/* The header of a symbols section. */ +symbols: + flags "xkb_symbols" '{' symbolssect '}' ';' +| flags "xkb_symbols" STR '{' symbolssect '}' ';' +; + +/* A group. */ +group: + GROUPNUM { $$ = $1 - 1 } +| NUM { $$ = $1 - 1} +| HEX { $$ = $1 - 1} +; + +/* A list of keysyms and keycodes bound to a realmodifier. */ +key_list: + key_list ',' KEYCODE { set_rmod_keycode ($3, current_rmod) } +| key_list ',' symbolname { ksrm_add ($3, current_rmod) } +| KEYCODE { set_rmod_keycode ($1, current_rmod) } +| symbolname { ksrm_add ($1, current_rmod) } +; + +/* Process the includes on the stack. */ +symbolinclude: + '{' symbolssect '}' { close_include () } +| symbolinclude '{' symbolssect '}' { close_include () } +; + +/* A XKB symbol section. It is used to bind keysymbols, actions and + realmodifiers to keycodes. */ +symbolssect: + /* Empty */ +| symbolssect vmods_def +| symbolssect NAME '[' group ']' '=' STR ';' +| symbolssect "key" KEYCODE + { + key_new ($3); + current_group = 0; + } '{' keydescs '}' ';' +| symbolssect "replace" "key" KEYCODE + { + key_delete ($4); + key_new ($4); + current_group = 0; + } '{' keydescs '}' ';' +| symbolssect "override" "key" KEYCODE + { + key_delete ($4); + key_new ($4); + current_group = 0; + } '{' keydescs '}' ';' +| symbolssect "modifier_map" rmod { current_rmod = $3 } '{' key_list '}' ';' +| symbolssect include STR + { include_sections ($3, XKBSYMBOLS, "symbols", $2) } + symbolinclude +| symbolssect actiondef +| symbolssect "key" '.' {current_key = default_key } keydesc ';' +| symbolssect error ';' { yyerror ("Error in symbol section\n") } +; + +/* Returns a keysymbols, the numberic representation. */ +symbolname: + IDENTIFIER { $$ = XStringToKeysym ($1); } +| NUM { $$ = $1 + '0' } +; + +/* None or more keysyms, assigned to a single group of the current + key. */ +groupsyms: + /* empty */ +| groupsyms ',' symbolname + { key_set_keysym (current_key, current_group, symbolcnt++, $3) } +| { symbolcnt = 0 } symbolname + { + symbolcnt = 0; + key_set_keysym (current_key, current_group, symbolcnt++, $2); + } +; + +/* A list of actions. */ +actions: + actions ',' action + { key_set_action (current_key, current_group, actioncnt++, $3) } +| { actioncnt = 0 } action + { key_set_action ( current_key, current_group, actioncnt++, $2) } +; + +keydescs: + keydesc +| keydescs ',' keydesc +; + +/* A single key and everything assigned to it. */ +keydesc: + "type" '[' group ']' '=' STR + { + current_key->groups[$3].keytype = keytype_find ($6); + } +| "type" '[' error ']' { yyerror ("Invalid group.\n") } +| "type" '=' STR + { current_key->groups[current_group].keytype = keytype_find ($3) } +| { symbolcnt = 0 } "symbols" '[' group ']' { current_group = $4 } '=' '[' groupsyms ']' + { + current_key->numgroups = ($4 + 1) > current_key->numgroups ? + ($4 + 1) : current_key->numgroups; + } +| {actioncnt = 0 } "actions" '[' group ']' { current_group = $4 } '=' '[' actions ']' + { + current_key->numgroups = ($4 + 1) > current_key->numgroups ? + ($4 + 1) : current_key->numgroups; + } +| "virtualmods" '=' mods + { current_key->mods.vmods = $3.vmods } +| '[' groupsyms ']' + { + current_group++; + current_key->numgroups = current_group > current_key->numgroups ? + current_group : current_key->numgroups; + } +| '[' actions ']' + { + current_group++; + current_key->numgroups = current_group > current_key->numgroups ? + current_group : current_key->numgroups; + } +| locking {}/* This is not implemented - YET. */ +/* XXX: There 3 features are described in Ivan Pascals docs about XKB, + but aren't used in the standard keymaps and cannot be used because it + cannot be stored in the XKM dataformat. */ +| groupswrap {} +| groupsclamp {} +| "groupsredirect" '=' NUM +| "overlay" '=' KEYCODE /* If you _REALLY_ need overlays, mail me!!!! */ +| repeat + { + current_key->flags &= ~(KEYREPEAT | KEYNOREPEAT); + current_key->flags |= $1; + } +; + +/* The geometry map is ignored. */ + +/* The header of a geometry section. */ +geometry: + flags "xkb_geometry" '{' { skipsection () } '}' ';' +| flags "xkb_geometry" STR '{' { skipsection () } '}' ';' +; + +%% +/* Skip all tokens until a section of the type SECTIONSYMBOL with the + name SECTIONNAME is found. */ +static void +skip_to_sectionname (char *sectionname, int sectionsymbol) +{ + int symbol; + + do + { + do + { + symbol = yylex (); + } while (symbol != sectionsymbol); + symbol = yylex (); + + if (symbol != STR) + continue; + + } while (strcmp (yylval.str, sectionname)); +} + +/* Skip all tokens until the default section is found. */ +static void +skip_to_defaultsection (void) +{ + int symbol; + + /* Search the default section. */ + do + { + symbol = yylex (); + } while (symbol != DEFAULT); + + do + { + symbol = yylex (); + } while (symbol != '{'); + scanner_unput ('{'); +} + +/* Include a single file. INCL is the filename. SECTIONSYMBOL is the + token that marks the beginning of the section. DIRNAME is the name + of the directory from where the includefiles must be loaded. NEW_MM + is the mergemode that should be used. */ +static error_t +include_section (char *incl, int sectionsymbol, char *dirname, + mergemode new_mm) +{ + void include_file (FILE *, mergemode, char *); + char *filename; + char *sectionname = NULL; + FILE *includefile; + + sectionname = strchr (incl, '('); + if (sectionname) + { + int snlen; + + snlen = strlen (sectionname); + if (sectionname[snlen-1] != ')') + return 0; + sectionname[snlen-1] = '\0'; + sectionname[0] = '\0'; + sectionname++; + + if (asprintf (&filename, "%s/%s", dirname, incl) < 0) + return ENOMEM; + } + else + { + if (asprintf (&filename, "%s/%s", dirname, incl) < 0) + return ENOMEM; + } + + includefile = fopen (strdup (filename), "r"); + + if (includefile == NULL) + { + fprintf (stderr, "Couldn't open include file \"%s\"\n", filename); + exit (EXIT_FAILURE); + } + + include_file (includefile, new_mm, strdup (filename)); + + /* If there is a sectionname not the entire file should be included, + the scanner should be positioned at the required section. */ + if (sectionname) + skip_to_sectionname (sectionname, sectionsymbol); + else + skip_to_defaultsection (); + + return 0; +} + +/* Include multiple file sections, seperated by '+'. INCL is the + include string. SECTIONSYMBOL is the token that marks the beginning + of the section. DIRNAME is the name of the directory from where the + includefiles must be loaded. NEW_MM is the mergemode that should be + used. */ +static error_t +include_sections (char *incl, int sectionsymbol, char *dirname, + mergemode new_mm) +{ + char *curstr; + char *s; + + if (new_mm == defaultmm) + new_mm = merge_mode; + +/* printf ("dir: %s - include: %s: %d\n", dirname, incl, new_mm); */ + /* Cut of all includes, starting with the first. The includes are + pushed on the stack in reversed order. */ + do { + curstr = strrchr (incl, '+'); + if (curstr) + { + curstr[0] = '\0'; + curstr++; + + s = strdup (curstr); + if (s == NULL) + return ENOMEM; + + include_section (s, sectionsymbol, dirname, new_mm); + free (s); + } + } while (curstr); + + s = strdup (incl); + if (s == NULL) + return ENOMEM; + + include_section (s, sectionsymbol, dirname, new_mm); + free (s); + + return 0; +} + +/* Skip all tokens until the end of the section is reached. */ +static void +skipsection (void) +{ + /* Pathesensis counter. */ + int p = 0; + while (p >= 0) + { + int symbol = yylex (); + if (symbol == '{') + p++; + if (symbol == '}') + p--; + } + scanner_unput ('}'); +} + +/* Initialize the default action with the default DEF. */ +static error_t +set_default_action (struct xkb_action *def, + struct xkb_action **newact) +{ + struct xkb_action *newaction; + newaction = malloc (sizeof (struct xkb_action)); + if (newaction == NULL) + return ENOMEM; + memcpy (newaction, def, sizeof (struct xkb_action)); + + *newact = newaction; + + return 0; +} + +/* Remove all keysyms bound to the group GROUP or the key KEY. */ +static void +remove_symbols (struct key *key, group_t group) +{ + // printf ("rem: group: %d\n", group); + if (key->groups[group].symbols) + { + free (key->groups[group].symbols); + key->groups[group].symbols = NULL; + key->groups[group].width = 0; + } +} + +/* Set the keysym KS for key KEY on group GROUP and level LEVEL. */ +static void +key_set_keysym (struct key *key, group_t group, int level, symbol ks) +{ + symbol *keysyms = key->groups[group].symbols; + + if ((level + 1) > key->groups[group].width) + { + keysyms = realloc (keysyms, level + 1); + + if (!keys) + { + fprintf (stderr, "No mem\n"); + exit (EXIT_FAILURE); + } + + key->groups[group].symbols = keysyms; + key->groups[group].width++; + } + else + /* For NoSymbol leave the old symbol intact. */ + if (!ks) + return; + + + keysyms[level++] = ks; +} + +/* Set the action ACTION for key KEY on group GROUP and level LEVEL. */ +void +key_set_action (struct key *key, group_t group, int level, xkb_action_t *action) +{ + xkb_action_t **actions = key->groups[group].actions; + size_t width = key->groups[group].actionwidth; + + if ((size_t) (level + 1) > width) + { + actions = realloc (actions, level + 1); + /* Previous levels have no actions defined. */ + memset (&actions[level - 1], 0, level - width); + + if (!keys) + { + fprintf (stderr, "No mem\n"); + exit (EXIT_FAILURE); + } + + key->groups[group].actions = actions; + key->groups[group].actionwidth += level - width + 1; + } + + actions[level++] = action; +} + +/* Delete keycode to keysym mapping. */ +void +key_delete (char *keyname) +{ + group_t group; + keycode_t kc = keyname_find (keyname); + + current_key = &keys[kc]; + for (group = 0; group < current_key->numgroups; group++) + remove_symbols (current_key, group); + memset (current_key, 0, sizeof (struct key)); + +} + +/* Create a new keycode to keysym mapping, check if the old one should + be removed or preserved. */ +static void +key_new (char *keyname) +{ + group_t group; + + int isempty (char *mem, int size) + { + int i; + for (i = 0; i < size; i++) + if (mem[i]) + return 0; + return 1; + } + + keycode_t kc = keyname_find (keyname); + + if (merge_mode == augment) + { + if (!isempty ((char *) &keys[kc], sizeof (struct key))) + { + current_key = &dummy_key; + return; + } + else + current_key = &keys[kc]; + } + + if (merge_mode == override) + current_key = &keys[kc]; + + if (merge_mode == replace) + { + key_delete (keyname); + current_key = &keys[kc]; + } + + if (current_key->numgroups == 0 || merge_mode == replace) + { + /* Clone the default key. */ + memcpy (current_key, default_key, sizeof (struct key)); + for (group = 0; group < 3; group++) + { + current_key->groups[group].symbols = NULL; + current_key->groups[group].actions = NULL; + current_key->groups[group].actionwidth = 0; + current_key->groups[group].width = 0; + } + } +} + +/* Load the XKB configuration from the section XKBKEYMAP in the + keymapfile XKBKEYMAPFILE. Use XKBDIR as root directory for relative + pathnames. */ +error_t +parse_xkbconfig (char *xkbdir, char *xkbkeymapfile, char *xkbkeymap) +{ + error_t err; + char *cwd = getcwd (NULL, 0); + extern FILE *yyin; + extern char *filename; + + // xkbkeymap = 0; + + // xkbkeymapfile = 0; + + // xkbdir = "/etc/X11/xkb"; + // xkbdir ="/home/marco/xkb"; + // xkbkeymapfile = "keymap/hurd"; + // xkbkeymap = "hack"; + + debug_printf ("Dir: %s, file: %s sect: %s\n", xkbdir, xkbkeymapfile, xkbkeymap); + + // xkbkeymapfile = "default.xkb"; + //xkbkeymap = "us"; + // yydebug = 1; + if (xkbkeymapfile) + { + filename = xkbkeymapfile; + + if (chdir (xkbdir) == -1) + { + fprintf (stderr, "Could not set \"%s\" as the active directory\n", + xkbdir); + return errno; + } + + yyin = fopen (xkbkeymapfile, "r"); + if (yyin == NULL) + { + fprintf (stderr, "Couldn't open keymap file\n"); + return errno; + } + + if (xkbkeymap) + skip_to_sectionname (xkbkeymap, XKBKEYMAP); + } + else /* Use defaults. */ + { + extern char *default_xkb_keymap; + filename = "<<INTERNAL>>"; + + yyin = tmpfile (); + //yyin = fopen ("TEST", "w+"); + + if (yyin == NULL) + { + fprintf (stderr, "Couldn't create tmp file.\n"); + return errno; + } + /* XXX: error handling. */ + fprintf (yyin, "%s\n", default_xkb_keymap); + + rewind (yyin); + } + err = yyparse (); + fclose (yyin); + + if (err || yynerrs > 0) + return EINVAL; + + if (xkbkeymapfile) + { + if (chdir (cwd) == -1) + { + fprintf (stderr, + "Could not set \"%s\" as the active directory\n", cwd); + return errno; + } + } + + /* Apply keysym to realmodifier mappings. */ + ksrm_apply (); + + free (cwd); + return 0; +} |