diff --git a/Makefile b/Makefile index 419dc561..f14cdb44 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,9 @@ TOPDIR=$(shell pwd) include $(TOPDIR)/common.mk # Depend on the object files of all source-files in src/*.c and on all header files -FILES=$(patsubst %.c,%.o,$(wildcard src/*.c)) +AUTOGENERATED:=src/cfgparse.tab.c src/cfgparse.yy.c +FILES:=$(filter-out $(AUTOGENERATED),$(wildcard src/*.c)) +FILES:=$(FILES:.c=.o) HEADERS=$(wildcard include/*.h) # Depend on the specific file (.c for each .o) and on all headers @@ -11,13 +13,23 @@ src/%.o: src/%.c ${HEADERS} echo "CC $<" $(CC) $(CFLAGS) -c -o $@ $< -all: ${FILES} +all: src/cfgparse.y.o src/cfgparse.yy.o ${FILES} echo "LINK i3" - $(CC) -o i3 ${FILES} $(LDFLAGS) + $(CC) -o i3 ${FILES} src/cfgparse.y.o src/cfgparse.yy.o $(LDFLAGS) echo "" echo "SUBDIR i3-msg" $(MAKE) TOPDIR=$(TOPDIR) -C i3-msg +src/cfgparse.yy.o: src/cfgparse.l + echo "LEX $<" + lex -i -o $(@:.o=.c) $< + $(CC) $(CFLAGS) -c -o $@ $(@:.o=.c) + +src/cfgparse.y.o: src/cfgparse.y + echo "YACC $<" + yacc -b $(basename $< .y) -d $< + $(CC) $(CFLAGS) -c -o $@ $(<:.y=.tab.c) + install: all echo "INSTALL" $(INSTALL) -d -m 0755 $(DESTDIR)/usr/bin @@ -46,7 +58,7 @@ dist: distclean rm -rf i3-${VERSION} clean: - rm -f src/*.o + rm -f src/*.o src/cfgparse.tab.{c,h} src/cfgparse.yy.c $(MAKE) -C docs clean $(MAKE) -C man clean $(MAKE) TOPDIR=$(TOPDIR) -C i3-msg clean diff --git a/src/cfgparse.l b/src/cfgparse.l new file mode 100644 index 00000000..af26c6ae --- /dev/null +++ b/src/cfgparse.l @@ -0,0 +1,59 @@ +%{ +#include +#include "cfgparse.tab.h" +#include + +enum { + BIND_NONE = 0, + BIND_SHIFT = XCB_MOD_MASK_SHIFT, /* (1 << 0) */ + BIND_CONTROL = XCB_MOD_MASK_CONTROL, /* (1 << 2) */ + BIND_MOD1 = XCB_MOD_MASK_1, /* (1 << 3) */ + BIND_MOD2 = XCB_MOD_MASK_2, /* (1 << 4) */ + BIND_MOD3 = XCB_MOD_MASK_3, /* (1 << 5) */ + BIND_MOD4 = XCB_MOD_MASK_4, /* (1 << 6) */ + BIND_MOD5 = XCB_MOD_MASK_5, /* (1 << 7) */ + BIND_MODE_SWITCH = (1 << 8) +}; + +%} + +%Start BIND_COND BIND_AWS_COND BIND_A2WS_COND ASSIGN_COND + +%% +[0-9]+ yylval.number = atoi(yytext); return NUMBER; +[0-9a-fA-F]+ { yylval.string = strdup(yytext); return HEX; } +bind { BEGIN(BIND_COND); return TOKBIND; } +bindsym { BEGIN(BIND_COND); return TOKBINDSYM; } +floating_modifier return TOKFLOATING_MODIFIER; +workspace return TOKWORKSPACE; +screen return TOKSCREEN; +assign { BEGIN(ASSIGN_COND); return TOKASSIGN; } +set { BEGIN(BIND_COND); return TOKSET; } +ipc-socket { BEGIN(BIND_AWS_COND); return TOKIPCSOCKET; } +exec { BEGIN(BIND_AWS_COND); return TOKEXEC; } +client.focused { /* TODO: lval pointer */ return TOKCOLOR; } +Mod1 yylval.number = BIND_MOD1; return MODIFIER; +Mod2 yylval.number = BIND_MOD2; return MODIFIER; +Mod3 yylval.number = BIND_MOD3; return MODIFIER; +Mod4 yylval.number = BIND_MOD4; return MODIFIER; +Mod5 yylval.number = BIND_MOD5; return MODIFIER; +control return TOKCONTROL; +shift return TOKSHIFT; +→ return TOKARROW; +\n /* ignore end of line */; +[ \t]+ { BEGIN(BIND_AWS_COND); return WHITESPACE; } +[ \t]+ { BEGIN(BIND_A2WS_COND); return WHITESPACE; } +[ \t]+ return WHITESPACE; +[^\n]+ { BEGIN(INITIAL); yylval.string = strdup(yytext); return STRING; } +[^ \t]+ { BEGIN(INITIAL); yylval.string = strdup(yytext); return STRING_NG; } +[a-zA-Z]+ yylval.string = strdup(yytext); return WORD; +[a-zA-Z0-9_-]+ yylval.string = strdup(yytext); return VARNAME; +\"[^\"]+\" { + /* yylval will be the string, but without quotes */ + char *copy = strdup(yytext+1); + copy[strlen(copy)-1] = '\0'; + yylval.string = copy; + return QUOTEDSTRING; + } +. return (int) yytext[0]; +%% diff --git a/src/cfgparse.y b/src/cfgparse.y new file mode 100644 index 00000000..2cf408a7 --- /dev/null +++ b/src/cfgparse.y @@ -0,0 +1,193 @@ +%{ +#include +#include +#include + +enum { + BIND_NONE = 0, + BIND_SHIFT = XCB_MOD_MASK_SHIFT, /* (1 << 0) */ + BIND_CONTROL = XCB_MOD_MASK_CONTROL, /* (1 << 2) */ + BIND_MOD1 = XCB_MOD_MASK_1, /* (1 << 3) */ + BIND_MOD2 = XCB_MOD_MASK_2, /* (1 << 4) */ + BIND_MOD3 = XCB_MOD_MASK_3, /* (1 << 5) */ + BIND_MOD4 = XCB_MOD_MASK_4, /* (1 << 6) */ + BIND_MOD5 = XCB_MOD_MASK_5, /* (1 << 7) */ + BIND_MODE_SWITCH = (1 << 8) +}; + + +int yydebug = 1; + +void yyerror(const char *str) +{ + fprintf(stderr,"error: %s\n",str); +} + +int yywrap() +{ + return 1; +} + +#if 0 +main() +{ + yyparse(); + printf("parsing done\n"); +} +#endif + +%} + +%union { + int number; + char *string; +} + +%token NUMBER +%token WORD +%token STRING +%token STRING_NG +%token VARNAME +%token HEX +%token TOKBIND +%token TOKBINDSYM +%token MODIFIER +%token TOKCONTROL +%token TOKSHIFT +%token WHITESPACE +%token TOKFLOATING_MODIFIER +%token QUOTEDSTRING +%token TOKWORKSPACE +%token TOKSCREEN +%token TOKASSIGN +%token TOKSET +%token TOKIPCSOCKET +%token TOKEXEC +%token TOKCOLOR +%token TOKARROW + +%% + +lines: /* empty */ + | lines WHITESPACE line + | lines line + ; + +line: + bind + | bindsym + | floating_modifier + | workspace + | assign + | set + | ipcsocket + | exec + | color + ; + +command: + STRING + ; + +bind: + TOKBIND WHITESPACE binding_modifiers '+' NUMBER WHITESPACE command + { + printf("\tFound binding mod%d with key %d and command %s\n", $3, $5, $7); + } + ; + +bindsym: + TOKBINDSYM WHITESPACE binding_modifiers '+' WORD WHITESPACE command + { + printf("\tFound symbolic mod%d with key %s and command %s\n", $3, $5, $7); + } + ; + +floating_modifier: + TOKFLOATING_MODIFIER WHITESPACE binding_modifiers + { + printf("\tfloating modifier %d\n", $3); + } + ; + +workspace: + TOKWORKSPACE WHITESPACE NUMBER WHITESPACE TOKSCREEN WHITESPACE screen + { + printf("\t workspace %d to screen %d\n", $3, $7); + } + | TOKWORKSPACE WHITESPACE NUMBER WHITESPACE TOKSCREEN WHITESPACE screen WHITESPACE QUOTEDSTRING + { + printf("\t quoted: %s\n", $9); + } + ; + +screen: + NUMBER + ; + + +assign: + TOKASSIGN WHITESPACE window_class WHITESPACE optional_arrow NUMBER + { + printf("assignment of %s to %d\n", $3, $6); + } + ; + +window_class: + QUOTEDSTRING + | STRING_NG + ; + +optional_arrow: + /* NULL */ + | TOKARROW WHITESPACE + ; + +set: + TOKSET WHITESPACE variable WHITESPACE STRING + { + printf("set %s to %s\n", $3, $5); + } + ; + +variable: + '$' WORD { asprintf(&$$, "$%s", $2); } + | '$' VARNAME { asprintf(&$$, "$%s", $2); } + ; + +ipcsocket: + TOKIPCSOCKET WHITESPACE STRING + { + printf("ipc %s\n", $3); + } + ; + +exec: + TOKEXEC WHITESPACE STRING + { + printf("exec %s\n", $3); + } + ; + +color: + TOKCOLOR WHITESPACE '#' HEX + { + printf("color %s\n", $4); + } + ; + + +binding_modifiers: + binding_modifier + | + binding_modifiers '+' binding_modifier + { + $$ = $1 | $3; + } + ; + +binding_modifier: + MODIFIER { $$ = $1; } + | TOKCONTROL { $$ = BIND_CONTROL; } + | TOKSHIFT { $$ = BIND_SHIFT; } + ;