3 * vim:ts=4:sw=4:expandtab
16 #include <X11/XKBlib.h>
28 /* These are the same as in YYLTYPE */
35 typedef struct yy_buffer_state *YY_BUFFER_STATE;
36 extern int yylex(struct context *context);
37 extern int yyparse(void);
39 YY_BUFFER_STATE yy_scan_string(const char *);
41 static struct context *context;
43 /* We don’t need yydebug for now, as we got decent error messages using
44 * yyerror(). Should you ever want to extend the parser, it might be handy
45 * to just comment it in again, so it stays here. */
48 void yyerror(const char *error_message) {
49 fprintf(stderr, "\n");
50 fprintf(stderr, "CONFIG: %s\n", error_message);
51 fprintf(stderr, "CONFIG: line %d:\n",
52 context->line_number);
53 fprintf(stderr, "CONFIG: %s\n", context->line_copy);
54 fprintf(stderr, "CONFIG: ");
55 for (int c = 1; c <= context->last_column; c++)
56 if (c >= context->first_column)
58 else fprintf(stderr, " ");
59 fprintf(stderr, "\n");
60 fprintf(stderr, "\n");
67 char *rewrite_binding(const char *bindingline) {
70 context = calloc(sizeof(struct context), 1);
72 yy_scan_string(bindingline);
75 fprintf(stderr, "Could not parse configfile\n");
79 result = context->result;
81 if (context->line_copy)
82 free(context->line_copy);
88 /* XXX: does not work for combinations of modifiers yet */
89 static char *modifier_to_string(int modifiers) {
90 //printf("should convert %d to string\n", modifiers);
91 if (modifiers == (1 << 3))
92 return strdup("$mod+");
93 else if (modifiers == ((1 << 3) | (1 << 0)))
94 return strdup("$mod+Shift+");
95 else if (modifiers == (1 << 9))
96 return strdup("$mod+");
97 else if (modifiers == ((1 << 9) | (1 << 0)))
98 return strdup("$mod+Shift+");
99 else if (modifiers == (1 << 0))
100 return strdup("Shift+");
101 else return strdup("");
107 %lex-param { struct context *context }
114 %token <number>NUMBER "<number>"
115 %token <string>STR "<string>"
117 %token TOKMODVAR "$mod"
118 %token MODIFIER "<modifier>"
119 %token TOKCONTROL "control"
120 %token TOKSHIFT "shift"
121 %token WHITESPACE "<whitespace>"
126 | lines WHITESPACE bindcode
132 TOKBINDCODE WHITESPACE binding_modifiers NUMBER WHITESPACE STR
134 //printf("\tFound keycode binding mod%d with key %d and command %s\n", $<number>3, $4, $<string>6);
136 if (($<number>3 & (1 << 0))) {
137 /* When shift is included, we really need to use the second-level
138 * symbol (upper-case). The lower-case symbol could be on a
139 * different key than the upper-case one (unlikely for letters, but
140 * more likely for special characters). */
143 KeySym sym = XkbKeycodeToKeysym(dpy, $4, 0, level);
144 char *str = XKeysymToString(sym);
145 char *modifiers = modifier_to_string($<number>3);
146 // TODO: modifier to string
147 sasprintf(&(context->result), "bindsym %s%s %s\n", modifiers, str, $<string>6);
153 /* NULL */ { $<number>$ = 0; }
155 | binding_modifiers '+' binding_modifier { $<number>$ = $<number>1 | $<number>3; }
156 | binding_modifiers '+' { $<number>$ = $<number>1; }
160 MODIFIER { $<number>$ = $<number>1; }
161 | TOKMODVAR { $<number>$ = $<number>1; }
162 | TOKCONTROL { $<number>$ = (1 << 2); }
163 | TOKSHIFT { $<number>$ = (1 << 0); }