X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcfgparse.y;h=99367adbd0126d081e5d25fce8042cea0a54a5f0;hb=93600ce0fdad72f4820c673498e4cc4d3dc330f2;hp=4b7224b51ae1a8fc31e4a3c2edc17854314520da;hpb=b1ebbde1537bfc20a23ffae8ebe9014aa314e5f2;p=i3%2Fi3 diff --git a/src/cfgparse.y b/src/cfgparse.y index 4b7224b5..99367adb 100644 --- a/src/cfgparse.y +++ b/src/cfgparse.y @@ -1,28 +1,42 @@ %{ -#include -#include -#include +/* + * vim:ts=8:expandtab + * + */ #include #include #include #include -#include -#include -#include "data.h" -#include "config.h" -#include "i3.h" -#include "util.h" -#include "queue.h" -#include "table.h" +#include "all.h" -extern int yylex(void); +typedef struct yy_buffer_state *YY_BUFFER_STATE; +extern int yylex(struct context *context); +extern int yyparse(void); extern FILE *yyin; - -int yydebug = 1; - -void yyerror(const char *str) { - fprintf(stderr,"error: %s\n",str); +YY_BUFFER_STATE yy_scan_string(const char *); + +static struct bindings_head *current_bindings; +static struct context *context; + +/* We don’t need yydebug for now, as we got decent error messages using + * yyerror(). Should you ever want to extend the parser, it might be handy + * to just comment it in again, so it stays here. */ +//int yydebug = 1; + +void yyerror(const char *error_message) { + ELOG("\n"); + ELOG("CONFIG: %s\n", error_message); + ELOG("CONFIG: in file \"%s\", line %d:\n", + context->filename, context->line_number); + ELOG("CONFIG: %s\n", context->line_copy); + ELOG("CONFIG: "); + for (int c = 1; c <= context->last_column; c++) + if (c >= context->first_column) + printf("^"); + else printf(" "); + printf("\n"); + ELOG("\n"); } int yywrap() { @@ -43,7 +57,7 @@ void parse_file(const char *f) { if (fstat(fd, &stbuf) == -1) die("Could not fstat file: %s\n", strerror(errno)); - buf = smalloc(stbuf.st_size * sizeof(char)); + buf = scalloc((stbuf.st_size + 1) * sizeof(char)); while (read_bytes < stbuf.st_size) { if ((ret = read(fd, buf + read_bytes, (stbuf.st_size - read_bytes))) < 0) die("Could not read(): %s\n", strerror(errno)); @@ -83,7 +97,7 @@ void parse_file(const char *f) { new->key = sstrdup(v_key); new->value = sstrdup(v_value); SLIST_INSERT_HEAD(&variables, new, variables); - LOG("Got new variable %s = %s\n", v_key, v_value); + DLOG("Got new variable %s = %s\n", v_key, v_value); continue; } } @@ -104,7 +118,7 @@ void parse_file(const char *f) { /* Then, allocate a new buffer and copy the file over to the new one, * but replace occurences of our variables */ char *walk = buf, *destwalk; - char *new = smalloc((stbuf.st_size + extra_bytes) * sizeof(char)); + char *new = smalloc((stbuf.st_size + extra_bytes + 1) * sizeof(char)); destwalk = new; while (walk < (buf + stbuf.st_size)) { /* Find the next variable */ @@ -137,60 +151,91 @@ void parse_file(const char *f) { yy_scan_string(new); + context = scalloc(sizeof(struct context)); + context->filename = f; + if (yyparse() != 0) { fprintf(stderr, "Could not parse configfile\n"); exit(1); } + FREE(context->line_copy); + free(context); free(new); free(buf); + + while (!SLIST_EMPTY(&variables)) { + current = SLIST_FIRST(&variables); + FREE(current->key); + FREE(current->value); + SLIST_REMOVE_HEAD(&variables, variables); + FREE(current); + } } %} +%expect 1 +%error-verbose +%lex-param { struct context *context } + %union { int number; char *string; struct Colortriple *color; - struct Assignment *assignment; + struct Assignment *assignment; + struct Binding *binding; } -%token NUMBER -%token WORD -%token STR -%token STR_NG -%token HEX +%token NUMBER "" +%token WORD "" +%token STR "" +%token STR_NG "" +%token HEX "" +%token OUTPUT "" %token TOKBIND %token TOKTERMINAL -%token TOKCOMMENT -%token TOKFONT -%token TOKBINDSYM -%token MODIFIER -%token TOKCONTROL -%token TOKSHIFT -%token WHITESPACE -%token TOKFLOATING_MODIFIER -%token QUOTEDSTRING -%token TOKWORKSPACE -%token TOKSCREEN -%token TOKASSIGN +%token TOKCOMMENT "" +%token TOKFONT "font" +%token TOKBINDSYM "bindsym" +%token MODIFIER "" +%token TOKCONTROL "control" +%token TOKSHIFT "shift" +%token WHITESPACE "" +%token TOKFLOATING_MODIFIER "floating_modifier" +%token QUOTEDSTRING "" +%token TOKWORKSPACE "workspace" +%token TOKOUTPUT "output" +%token TOKASSIGN "assign" %token TOKSET -%token TOKIPCSOCKET -%token TOKEXEC +%token TOKIPCSOCKET "ipc_socket" +%token TOKEXEC "exec" %token TOKCOLOR -%token TOKARROW +%token TOKARROW "→" +%token TOKMODE "mode" +%token TOKNEWCONTAINER "new_container" +%token TOKNEWWINDOW "new_window" +%token TOKFOCUSFOLLOWSMOUSE "focus_follows_mouse" +%token TOKWORKSPACEBAR "workspace_bar" +%token TOKCONTAINERMODE "default/stacking/tabbed" +%token TOKSTACKLIMIT "stack-limit" %% lines: /* empty */ | lines WHITESPACE line + | lines error | lines line ; line: - bind - | bindsym + bindline + | mode | floating_modifier + | new_container + | new_window + | focus_follows_mouse + | workspace_bar | workspace | assign | ipcsocket @@ -209,102 +254,278 @@ command: STR ; +bindline: + binding + { + TAILQ_INSERT_TAIL(bindings, $1, bindings); + } + ; + +binding: + TOKBIND WHITESPACE bind { $$ = $3; } + | TOKBINDSYM WHITESPACE bindsym { $$ = $3; } + ; + bind: - TOKBIND WHITESPACE binding_modifiers NUMBER WHITESPACE command + binding_modifiers NUMBER WHITESPACE command { - printf("\tFound binding mod%d with key %d and command %s\n", $3, $4, $6); + printf("\tFound binding mod%d with key %d and command %s\n", $1, $2, $4); Binding *new = scalloc(sizeof(Binding)); - new->keycode = $4; - new->mods = $3; - new->command = sstrdup($6); + new->keycode = $2; + new->mods = $1; + new->command = $4; - TAILQ_INSERT_TAIL(&bindings, new, bindings); + $$ = new; } ; bindsym: - TOKBINDSYM WHITESPACE binding_modifiers WORD WHITESPACE command + binding_modifiers word_or_number WHITESPACE command { - printf("\tFound symbolic mod%d with key %s and command %s\n", $3, $4, $6); + printf("\tFound symbolic mod%d with key %s and command %s\n", $1, $2, $4); Binding *new = scalloc(sizeof(Binding)); - new->symbol = sstrdup($4); - new->mods = $3; - new->command = sstrdup($6); + new->symbol = $2; + new->mods = $1; + new->command = $4; + + $$ = new; + } + ; + +word_or_number: + WORD + | NUMBER + { + asprintf(&$$, "%d", $1); + } + ; + +mode: + TOKMODE WHITESPACE QUOTEDSTRING WHITESPACE '{' modelines '}' + { + if (strcasecmp($3, "default") == 0) { + printf("You cannot use the name \"default\" for your mode\n"); + exit(1); + } + printf("\t now in mode %s\n", $3); + printf("\t current bindings = %p\n", current_bindings); + Binding *binding; + TAILQ_FOREACH(binding, current_bindings, bindings) { + printf("got binding on mods %d, keycode %d, symbol %s, command %s\n", + binding->mods, binding->keycode, binding->symbol, binding->command); + } + + struct Mode *mode = scalloc(sizeof(struct Mode)); + mode->name = $3; + mode->bindings = current_bindings; + current_bindings = NULL; + SLIST_INSERT_HEAD(&modes, mode, modes); + } + ; + + +modelines: + /* empty */ + | modelines modeline + ; + +modeline: + WHITESPACE + | comment + | binding + { + if (current_bindings == NULL) { + current_bindings = scalloc(sizeof(struct bindings_head)); + TAILQ_INIT(current_bindings); + } - TAILQ_INSERT_TAIL(&bindings, new, bindings); + TAILQ_INSERT_TAIL(current_bindings, $1, bindings); } ; floating_modifier: TOKFLOATING_MODIFIER WHITESPACE binding_modifiers { - LOG("floating modifier = %d\n", $3); + DLOG("floating modifier = %d\n", $3); config.floating_modifier = $3; } ; +new_container: + TOKNEWCONTAINER WHITESPACE TOKCONTAINERMODE + { + DLOG("new containers will be in mode %d\n", $3); + config.container_mode = $3; + +#if 0 + /* We also need to change the layout of the already existing + * workspaces here. Workspaces may exist at this point because + * of the other directives which are modifying workspaces + * (setting the preferred screen or name). While the workspace + * objects are already created, they have never been used. + * Thus, the user very likely awaits the default container mode + * to trigger in this case, regardless of where it is inside + * his configuration file. */ + Workspace *ws; + TAILQ_FOREACH(ws, workspaces, workspaces) { + if (ws->table == NULL) + continue; + switch_layout_mode(global_conn, + ws->table[0][0], + config.container_mode); + } +#endif + } + | TOKNEWCONTAINER WHITESPACE TOKSTACKLIMIT WHITESPACE TOKSTACKLIMIT WHITESPACE NUMBER + { + DLOG("stack-limit %d with val %d\n", $5, $7); + config.container_stack_limit = $5; + config.container_stack_limit_value = $7; + +#if 0 + /* See the comment above */ + Workspace *ws; + TAILQ_FOREACH(ws, workspaces, workspaces) { + if (ws->table == NULL) + continue; + Container *con = ws->table[0][0]; + con->stack_limit = config.container_stack_limit; + con->stack_limit_value = config.container_stack_limit_value; + } +#endif + } + ; + +new_window: + TOKNEWWINDOW WHITESPACE WORD + { + DLOG("new windows should start in mode %s\n", $3); + config.default_border = sstrdup($3); + } + ; + +bool: + NUMBER + { + $$ = ($1 == 1); + } + | WORD + { + DLOG("checking word \"%s\"\n", $1); + $$ = (strcasecmp($1, "yes") == 0 || + strcasecmp($1, "true") == 0 || + strcasecmp($1, "on") == 0 || + strcasecmp($1, "enable") == 0 || + strcasecmp($1, "active") == 0); + } + ; + +focus_follows_mouse: + TOKFOCUSFOLLOWSMOUSE WHITESPACE bool + { + DLOG("focus follows mouse = %d\n", $3); + config.disable_focus_follows_mouse = !($3); + } + ; + +workspace_bar: + TOKWORKSPACEBAR WHITESPACE bool + { + DLOG("workspace bar = %d\n", $3); + config.disable_workspace_bar = !($3); + } + ; + workspace: - TOKWORKSPACE WHITESPACE NUMBER WHITESPACE TOKSCREEN WHITESPACE screen workspace_name + TOKWORKSPACE WHITESPACE NUMBER WHITESPACE TOKOUTPUT WHITESPACE OUTPUT optional_workspace_name + { + int ws_num = $3; + if (ws_num < 1) { + DLOG("Invalid workspace assignment, workspace number %d out of range\n", ws_num); + } else { +#if 0 + Workspace *ws = workspace_get(ws_num - 1); + ws->preferred_output = $7; + if ($8 != NULL) { + workspace_set_name(ws, $8); + free($8); + } +#endif + } + } + | TOKWORKSPACE WHITESPACE NUMBER WHITESPACE workspace_name { int ws_num = $3; - if (ws_num < 1 || ws_num > 10) { - LOG("Invalid workspace assignment, workspace number %d out of range\n", ws_num); + if (ws_num < 1) { + DLOG("Invalid workspace assignment, workspace number %d out of range\n", ws_num); } else { - workspaces[ws_num - 1].preferred_screen = sstrdup($7); - if ($8 != NULL) - workspace_set_name(&(workspaces[ws_num - 1]), $8); + DLOG("workspace name to: %s\n", $5); +#if 0 + if ($5 != NULL) { + workspace_set_name(workspace_get(ws_num - 1), $5); + free($5); + } +#endif } } ; -workspace_name: - /* NULL */ { $$ = NULL; } - | WHITESPACE QUOTEDSTRING { $$ = $2; } - | WHITESPACE STR { $$ = $2; } +optional_workspace_name: + /* empty */ { $$ = NULL; } + | WHITESPACE workspace_name { $$ = $2; } ; -screen: - NUMBER { asprintf(&$$, "%d", $1); } - | NUMBER 'x' { asprintf(&$$, "%d", $1); } - | NUMBER 'x' NUMBER { asprintf(&$$, "%dx%d", $1, $3); } - | 'x' NUMBER { asprintf(&$$, "x%d", $2); } +workspace_name: + QUOTEDSTRING { $$ = $1; } + | STR { $$ = $1; } + | WORD { $$ = $1; } ; assign: TOKASSIGN WHITESPACE window_class WHITESPACE optional_arrow assign_target { - printf("assignment of %s to %d\n", $3, $6); - - struct Assignment *new = $6; - new->windowclass_title = strdup($3); - TAILQ_INSERT_TAIL(&assignments, new, assignments); +#if 0 + printf("assignment of %s\n", $3); + + struct Assignment *new = $6; + printf(" to %d\n", new->workspace); + printf(" floating = %d\n", new->floating); + new->windowclass_title = $3; + TAILQ_INSERT_TAIL(&assignments, new, assignments); +#endif } ; assign_target: - NUMBER - { - struct Assignment *new = scalloc(sizeof(struct Assignment)); - new->workspace = $1; - new->floating = ASSIGN_FLOATING_NO; - $$ = new; - } - | '~' - { - struct Assignment *new = scalloc(sizeof(struct Assignment)); - new->floating = ASSIGN_FLOATING_ONLY; - $$ = new; - } - | '~' NUMBER - { - struct Assignment *new = scalloc(sizeof(struct Assignment)); - new->workspace = $2; - new->floating = ASSIGN_FLOATING; - $$ = new; - } - ; + NUMBER + { +#if 0 + struct Assignment *new = scalloc(sizeof(struct Assignment)); + new->workspace = $1; + new->floating = ASSIGN_FLOATING_NO; + $$ = new; +#endif + } + | '~' + { +#if 0 + struct Assignment *new = scalloc(sizeof(struct Assignment)); + new->floating = ASSIGN_FLOATING_ONLY; + $$ = new; +#endif + } + | '~' NUMBER + { +#if 0 + struct Assignment *new = scalloc(sizeof(struct Assignment)); + new->workspace = $2; + new->floating = ASSIGN_FLOATING; + $$ = new; +#endif + } + ; window_class: QUOTEDSTRING @@ -319,7 +540,7 @@ optional_arrow: ipcsocket: TOKIPCSOCKET WHITESPACE STR { - config.ipc_socket_path = sstrdup($3); + config.ipc_socket_path = $3; } ; @@ -327,7 +548,7 @@ exec: TOKEXEC WHITESPACE STR { struct Autostart *new = smalloc(sizeof(struct Autostart)); - new->command = sstrdup($3); + new->command = $3; TAILQ_INSERT_TAIL(&autostarts, new, autostarts); } ; @@ -335,15 +556,15 @@ exec: terminal: TOKTERMINAL WHITESPACE STR { - config.terminal = sstrdup($3); - printf("terminal %s\n", config.terminal); + ELOG("The terminal option is DEPRECATED and has no effect. " + "Please remove it from your configuration file.\n"); } ; font: TOKFONT WHITESPACE STR { - config.font = sstrdup($3); + config.font = $3; printf("font %s\n", config.font); } ; @@ -361,7 +582,14 @@ color: ; colorpixel: - '#' HEX { $$ = get_colorpixel(global_conn, $2); } + '#' HEX + { + char *hex; + if (asprintf(&hex, "#%s", $2) == -1) + die("asprintf()"); + $$ = get_colorpixel(hex); + free(hex); + } ;