diff options
author | koekeishiya <aasvi93@hotmail.com> | 2018-01-06 17:00:30 +0100 |
---|---|---|
committer | koekeishiya <aasvi93@hotmail.com> | 2018-01-06 17:00:30 +0100 |
commit | 977b44fe68d8a1613313bcb8c45c3b48ec424fa9 (patch) | |
tree | 0324107228b1d121d52a56d18e991a875a44a3f8 /src | |
parent | 94c26f456f095ec8334d9c313943c2747d27c0c2 (diff) | |
parent | 8b8f85402dff702c5f85e97dee56251e948e6223 (diff) | |
download | skhd-977b44fe68d8a1613313bcb8c45c3b48ec424fa9.tar.gz skhd-977b44fe68d8a1613313bcb8c45c3b48ec424fa9.zip |
#15 fix memory leak, some error handling and merge master
Diffstat (limited to 'src')
-rw-r--r-- | src/hotkey.c | 30 | ||||
-rw-r--r-- | src/hotload.c | 48 | ||||
-rw-r--r-- | src/hotload.h | 2 | ||||
-rw-r--r-- | src/parse.c | 66 |
4 files changed, 114 insertions, 32 deletions
diff --git a/src/hotkey.c b/src/hotkey.c index fae753b..af1e410 100644 --- a/src/hotkey.c +++ b/src/hotkey.c @@ -123,17 +123,21 @@ bool find_and_exec_hotkey(struct hotkey *eventkey, struct table *mode_map, struc } internal void -free_hotkeys(struct table *hotkey_map) +free_hotkeys(struct table *hotkey_map, struct table *freed_pointers) { int count; void **hotkeys = table_reset(hotkey_map, &count); + for (int index = 0; index < count; ++index) { struct hotkey *hotkey = (struct hotkey *) hotkeys[index]; - // the same hotkey can be added for multiple modes - // we need to know if this pointer was already freed - // by a mode that was destroyed before us - // free(hotkey->command); - // free(hotkey); + if (table_find(freed_pointers, hotkey)) { + // we have already freed this pointer, do nothing! + // printf("info: %p has already been freed!\n", hotkey); + } else { + table_add(freed_pointers, hotkey, hotkey); + free(hotkey->command); + free(hotkey); + } } if (count) { @@ -141,20 +145,32 @@ free_hotkeys(struct table *hotkey_map) } } +unsigned long hash_pointer(struct hotkey *a) { return (unsigned long)a; } +bool same_pointer(struct hotkey *a, struct hotkey *b) { return a == b; } + void free_mode_map(struct table *mode_map) { int count; + struct table freed_pointers; void **modes = table_reset(mode_map, &count); + + if (count) { + table_init(&freed_pointers, 13, + (table_hash_func) hash_pointer, + (table_compare_func) same_pointer); + } + for (int index = 0; index < count; ++index) { struct mode *mode = (struct mode *) modes[index]; if (mode->command) free(mode->command); if (mode->name) free(mode->name); - free_hotkeys(&mode->hotkey_map); + free_hotkeys(&mode->hotkey_map, &freed_pointers); free(mode); } if (count) { free(modes); + table_free(&freed_pointers); } } diff --git a/src/hotload.c b/src/hotload.c index 8677cc2..ad02d21 100644 --- a/src/hotload.c +++ b/src/hotload.c @@ -1,4 +1,5 @@ #include "hotload.h" +#include <sys/stat.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -40,6 +41,31 @@ file_name(const char *file) return name; } +internal char * +resolve_symlink(char *file) +{ + struct stat buffer; + if (lstat(file, &buffer) != 0) { + return NULL; + } + + if (!S_ISLNK(buffer.st_mode)) { + return file; + } + + ssize_t size = buffer.st_size + 1; + char *result = malloc(size); + ssize_t read = readlink(file, result, size); + + if (read != -1) { + result[read] = '\0'; + return result; + } + + free(result); + return NULL; +} + internal struct watched_file * hotloader_watched_file(struct hotloader *hotloader, char *absolutepath) { @@ -78,14 +104,24 @@ internal FSEVENT_CALLBACK(hotloader_handler) } } -void hotloader_add_file(struct hotloader *hotloader, const char *file) +void hotloader_add_file(struct hotloader *hotloader, char *file) { if (!hotloader->enabled) { - struct watched_file watch_info; - watch_info.directory = file_directory(file); - watch_info.filename = file_name(file); - hotloader->watch_list[hotloader->watch_count++] = watch_info; - printf("hotload: watching file '%s' in directory '%s'\n", watch_info.filename, watch_info.directory); + char *real_path = resolve_symlink(file); + if (real_path) { + struct watched_file watch_info; + watch_info.directory = file_directory(real_path); + watch_info.filename = file_name(real_path); + + if (real_path != file) { + free(real_path); + } + + hotloader->watch_list[hotloader->watch_count++] = watch_info; + printf("hotload: watching file '%s' in directory '%s'\n", watch_info.filename, watch_info.directory); + } else { + fprintf(stderr, "hotload: could not watch file '%s'\n", file); + } } } diff --git a/src/hotload.h b/src/hotload.h index 5948a21..ad782fb 100644 --- a/src/hotload.h +++ b/src/hotload.h @@ -27,6 +27,6 @@ struct hotloader bool hotloader_begin(struct hotloader *hotloader, hotloader_callback *callback); void hotloader_end(struct hotloader *hotloader); -void hotloader_add_file(struct hotloader *hotloader, const char *file); +void hotloader_add_file(struct hotloader *hotloader, char *file); #endif diff --git a/src/parse.c b/src/parse.c index bf5a48d..e807b8a 100644 --- a/src/parse.c +++ b/src/parse.c @@ -12,6 +12,23 @@ #define internal static +internal void +init_default_mode(struct parser *parser) +{ + struct mode *default_mode = malloc(sizeof(struct mode)); + + default_mode->line = -1; + default_mode->cursor = -1; + default_mode->name = copy_string("default"); + + table_init(&default_mode->hotkey_map, 131, + (table_hash_func) hash_hotkey, + (table_compare_func) same_hotkey); + + default_mode->command = NULL; + table_add(parser->mode_map, default_mode->name, default_mode); +} + internal char * read_file(const char *file) { @@ -153,6 +170,11 @@ parse_mode(struct parser *parser, struct hotkey *hotkey) struct mode *mode = table_find(parser->mode_map, name); free(name); + if (!mode && token_equals(identifier, "default")) { + init_default_mode(parser); + mode = table_find(parser->mode_map, "default"); + } + if (!mode) { parser_report_error(parser, Error_Undeclared_Ident, "undeclared identifier"); return; @@ -178,35 +200,40 @@ parse_hotkey(struct parser *parser) memset(hotkey, 0, sizeof(struct hotkey)); bool found_modifier; - printf("(#%d) hotkey :: {\n", parser->current_token.line); + printf("hotkey :: #%d {\n", parser->current_token.line); if (parser_match(parser, Token_Identifier)) { parse_mode(parser, hotkey); if (parser->error) { - return NULL; + goto err; } } if (hotkey->mode_count > 0) { if (!parser_match(parser, Token_Insert)) { parser_report_error(parser, Error_Unexpected_Token, "expected '<'"); - return NULL; + goto err; } } else { - hotkey->mode_list[hotkey->mode_count++] = table_find(parser->mode_map, "default"); + hotkey->mode_list[hotkey->mode_count] = table_find(parser->mode_map, "default"); + if (!hotkey->mode_list[hotkey->mode_count]) { + init_default_mode(parser); + hotkey->mode_list[hotkey->mode_count] = table_find(parser->mode_map, "default"); + } + hotkey->mode_count++; } if ((found_modifier = parser_match(parser, Token_Modifier))) { hotkey->flags = parse_modifier(parser); if (parser->error) { - return NULL; + goto err; } } if (found_modifier) { if (!parser_match(parser, Token_Dash)) { parser_report_error(parser, Error_Unexpected_Token, "expected '-'"); - return NULL; + goto err; } } @@ -218,7 +245,7 @@ parse_hotkey(struct parser *parser) parse_key_literal(parser, hotkey); } else { parser_report_error(parser, Error_Unexpected_Token, "expected key-literal"); - return NULL; + goto err; } if (parser_match(parser, Token_Arrow)) { @@ -232,16 +259,20 @@ parse_hotkey(struct parser *parser) hotkey->command = parse_command(parser); if (!table_find(parser->mode_map, hotkey->command)) { parser_report_error(parser, Error_Undeclared_Ident, "undeclared identifier"); - return NULL; + goto err; } } else { parser_report_error(parser, Error_Unexpected_Token, "expected ':' followed by command or ';' followed by mode"); - return NULL; + goto err; } printf("}\n"); return hotkey; + +err: + free(hotkey); + return NULL; } internal struct mode * @@ -295,16 +326,15 @@ void parse_config(struct parser *parser) (parser_check(parser, Token_Literal)) || (parser_check(parser, Token_Key_Hex)) || (parser_check(parser, Token_Key))) { - hotkey = parse_hotkey(parser); - if (parser->error) { + if ((hotkey = parse_hotkey(parser))) { + for (int i = 0; i < hotkey->mode_count; ++i) { + mode = hotkey->mode_list[i]; + table_add(&mode->hotkey_map, hotkey, hotkey); + } + } else if (parser->error) { free_mode_map(parser->mode_map); return; } - - for (int i = 0; i < hotkey->mode_count; ++i) { - mode = hotkey->mode_list[i]; - table_add(&mode->hotkey_map, hotkey, hotkey); - } } else { parser_report_error(parser, Error_Unexpected_Token, "expected decl, modifier or key-literal"); return; @@ -362,11 +392,11 @@ void parser_report_error(struct parser *parser, enum parse_error_type error_type va_start(args, format); if (error_type == Error_Unexpected_Token) { - fprintf(stderr, "(#%d:%d) ", parser->current_token.line, parser->current_token.cursor); + fprintf(stderr, "#%d:%d: ", parser->current_token.line, parser->current_token.cursor); vfprintf(stderr, format, args); fprintf(stderr, ", but got '%.*s'\n", parser->current_token.length, parser->current_token.text); } else if (error_type == Error_Undeclared_Ident) { - fprintf(stderr, "(#%d:%d) ", parser->previous_token.line, parser->previous_token.cursor); + fprintf(stderr, "#%d:%d: ", parser->previous_token.line, parser->previous_token.cursor); vfprintf(stderr, format, args); fprintf(stderr, " '%.*s'\n", parser->previous_token.length, parser->previous_token.text); } else if (error_type == Error_Duplicate_Ident) { |