From 9871f375ed66b7d1546ac860d1df230e9af921e6 Mon Sep 17 00:00:00 2001 From: Alessandro Mauri Date: Mon, 31 Aug 2020 17:53:20 +0200 Subject: [PATCH] bump to version 0.3 bug fixes, check commits for details implemented new parser, altough it adds some lines it lowers the comlexity and it should be faster especially for bigger config files --- hkd.c | 303 +++++++++++++++++++++++++++++-------------------------- makefile | 2 +- 2 files changed, 162 insertions(+), 143 deletions(-) diff --git a/hkd.c b/hkd.c index aa5378f..adf957c 100644 --- a/hkd.c +++ b/hkd.c @@ -20,6 +20,7 @@ /* Value defines */ #define FILE_NAME_MAX_LENGTH 255 #define KEY_BUFFER_SIZE 16 +#define BLOCK_SIZE 512 /* ANSI colors escape codes */ #define ANSI_COLOR_RED "\x1b[31m" @@ -224,11 +225,9 @@ void parse_config_file (void); void update_descriptors_list (int **, int *); int prepare_epoll (int *, int, int); unsigned short key_to_code (char *); -int is_empty (const char *s); /* hotkey list operations */ void hotkey_list_add (struct hotkey_list_e *, struct key_buffer *, char *, int); void hotkey_list_destroy (struct hotkey_list_e *); -void hotkey_list_append_command (struct hotkey_list_e *, char *); int main (int argc, char *argv[]) { @@ -612,24 +611,25 @@ void hotkey_list_add (struct hotkey_list_e *head, struct key_buffer *kb, char *c hotkey_list = tmp; } -void hotkey_list_append_command (struct hotkey_list_e *head, char *cmd) -{ - char *tmp; - if (!head) - return; - while (head->next) - head = head->next; - tmp = realloc(head->command, sizeof(head->command) + strlen(cmd) + 1); - if (!tmp) - die("realloc in hotkey_list_append_command()"); - head->command = tmp; - strcat(head->command, cmd); -} - void parse_config_file (void) { wordexp_t result = {0}; FILE *fd; + int remaining = 0; + char block[BLOCK_SIZE + 1] = {0}; + char *bb = NULL; + // 0: normal, 1: skip line 2: get directive 3: get keys 4: get command 5: output + int state = 0; + char *keys = NULL; + char *cmd = NULL; + int alloc_tmp = 0, alloc_size = 0; + int fuzzy = 0; + struct key_buffer kb; + + int i_tmp = 0, done = 0; + char *cp_tmp = NULL; + unsigned short us_tmp = 0; + if (ext_config_file) { switch (wordexp(ext_config_file, &result, 0)) { case 0: @@ -675,131 +675,160 @@ void parse_config_file (void) if (!fd) die("could not open any config files, check the log for more details"); } - - int iscmd = 0; - struct key_buffer kb; - for (int linenum = 1;; linenum++) { - int fuzzy = 0, tmp; - char * linebegin = NULL; - char *line = NULL, *keys = NULL, *command = NULL; - size_t linelen = 0; - - if (getline(&line, &linelen, fd) == -1) + while (!done) { + memset(block, 0, BLOCK_SIZE); + remaining = fread(block, sizeof(char), BLOCK_SIZE, fd); + if (!remaining) break; + bb = block; - linelen = strlen(line); - if (linelen < 2) - continue; - - linebegin = line; - - // Remove leading spaces - while (isspace(line[0]) && linelen > 1) { - line = &line[1]; - linelen--; - } - - // Skip comments and blank lines - if (line[0] == '#' || !line[0]) - goto parse_end_free; - - for (size_t i = 1; i < linelen; i++) { - if (line[i] == '#') - line[i] = '\0'; - } - if (!iscmd) { - if (line[0] != '-' && line[0] != '*') { - fprintf(stderr, red("Error at line %d: " - "Hotkey definitions must start with '*' or '-'\n"), linenum); - exit(EXIT_FAILURE); - } - - if (line[0] == '*') - fuzzy = 1; - line = &line[1]; - linelen--; - // Remove leading spaces - while (isspace(line[0]) && linelen > 1) { - line = &line[1]; - linelen--; - } - keys = strtok(line, ":"); - command = strtok(NULL, ":"); - if (!command || !keys) { - fprintf(stderr, red("Error at line %d: " - "No command or keys specified\n"), linenum); - exit(EXIT_FAILURE); - } - // Check if keys and command are not blank - if (is_empty(keys) || is_empty(command)) { - fprintf(stderr, red("Error at line %d: " - "command or keys not present\n"), linenum); - exit(EXIT_FAILURE); - } + while (remaining > 0) { + switch (state) { + // First state + case 0: + // remove whitespaces + while (isblank(*bb) && remaining > 0) + bb++, remaining--; + if (remaining <= 0) + break; + // get state + switch (*bb) { + case '\n': + case '#': + state = 1; + break; + case '\0': + done = 1; + break; + default: + state = 2; + break; + } + break; + // Skip line (comment) + case 1: + while (*bb != '\n' && remaining > 0) + bb++, remaining--; + bb++, remaining--; + if (remaining > 0) + state = 0; + break; + // Get compairson method + case 2: + switch (*bb) { + case '-': + fuzzy = 0; + break; + case '*': + fuzzy = 1; + break; + default: + die("invalid line") + break; + } + bb++, remaining--; + state = 3; + break; + // Get keys + case 3: + if (!keys) { + if (!(keys = malloc(alloc_size = (sizeof(char) * 64)))) + die("malloc for keys in parse_config_file()"); + memset(keys, 0, alloc_size); + alloc_tmp = 0; + } else if (alloc_tmp >= alloc_size) { + if (!(keys = realloc(keys, alloc_size *= 2))) + die("realloc for keys in parse_config_file()"); + memset(&keys[alloc_size / 2], 0, alloc_size / 2); + } - // Remove whitespaces in keys - tmp = strlen(keys); - for (int i = 0; i < tmp; i++) { - if (isspace(keys[i])) - memmove(&line[i], &line[i + 1], --tmp); - } + for (; remaining > 0 && + (bb[alloc_tmp] != ':' && bb[alloc_tmp] != '\n') && + alloc_tmp < alloc_size; + remaining--, alloc_tmp++); - // Remove leading and trailing spaces in command - tmp = strlen(command); - while (isspace(command[0]) && tmp > 1) { - command = &command[1]; - tmp--; - } - for (tmp = strlen(command) - 1; isspace(command[tmp]); tmp--) { - if (isblank(command[tmp])) - command[tmp] = '\0'; - } + if (remaining <= 0 || alloc_tmp == alloc_size) { + strncat(keys, bb, alloc_tmp); + bb += alloc_tmp; + break; + } else if (bb[alloc_tmp] == ':') { + strncat(keys, bb, alloc_tmp); + bb += alloc_tmp + 1; + remaining--; + state = 4; + break; + } else { + die("no command"); + } + break; + // Get command + case 4: + if (!cmd) { + if (!(cmd = malloc(alloc_size = (sizeof(char) * 128)))) + die("malloc for cmd in parse_config_file()"); + memset(cmd, 0, alloc_size); + alloc_tmp = 0; + } else if (alloc_tmp >= alloc_size) { + if (!(cmd = realloc(cmd, alloc_size *= 2))) + die("realloc for cmd in parse_config_file()"); + memset(&cmd[alloc_size / 2], 0, alloc_size / 2); + } - if (command[strlen(command) - 2] == '\\') { - iscmd = 1; - } else { - iscmd = 0; - tmp = strlen(command) - 1; - while (isspace(command[tmp])) - command[tmp--] = '\0'; - } + for (; remaining > 0 && + bb[alloc_tmp] != '\n' && + alloc_tmp < alloc_size; + remaining--, alloc_tmp++); - key_buffer_reset(&kb); - char *k = strtok(keys, ","); - unsigned short kc; - do { - if (!(kc = key_to_code(k))) { - fprintf(stderr, red("Error at line %d: " - "%s is not a valid key"), linenum, k); - exit(EXIT_FAILURE); + if (remaining <= 0 || alloc_tmp == alloc_size) { + strncat(cmd, bb, alloc_tmp); + bb += alloc_tmp; + break; + } else { + strncat(cmd, bb, alloc_tmp); + if (!(bb[alloc_tmp - 1] == '\\')) + state = 5; + bb += alloc_tmp + 1; + remaining--; + break; } - key_buffer_add(&kb, kc); - } while ((k = strtok(NULL, ","))); - hotkey_list_add(hotkey_list, &kb, command, fuzzy); - hotkey_size_mask |= 1 << (kb.size - 1); - key_buffer_reset(&kb); - } else { - for (tmp = strlen(line) - 1; isspace(line[tmp]); tmp--) { - if (isblank(line[tmp])) - line[tmp] = '\0'; - } - linelen = strlen(line); - - // if line is blank skip - if (is_empty(line)) - goto parse_end_free; - - if (line[linelen - 2] == '\\') { - iscmd = 1; - } else { - iscmd = 0; - while (isspace(line[linelen - 1])) - line[--linelen] = '\0'; + break; + case 5: + i_tmp = strlen(keys); + for (int i = 0; i < i_tmp; i++) { + if (isblank(keys[i])) { + memmove(&keys[i], &keys[i + 1], --i_tmp); + keys[i_tmp] = '\0'; + } + } + cp_tmp = strtok(keys, ","); + if(!cp_tmp) + die("no keys"); + do { + if (!(us_tmp = key_to_code(cp_tmp))) + die("key not valid"); + key_buffer_add(&kb, us_tmp); + } while ((cp_tmp = strtok(NULL, ","))); + + cp_tmp = cmd; + while (isblank(*cp_tmp)) + cp_tmp++; + + hotkey_list_add(hotkey_list, &kb, cp_tmp, fuzzy); + hotkey_size_mask |= 1 << (kb.size - 1); + // DO STUFF + + key_buffer_reset(&kb); + free(keys); + free(cmd); + cp_tmp = keys = cmd = NULL; + i_tmp = state = 0; + break; + default: + die("unknown state in parse_config_file"); + break; + } - hotkey_list_append_command(hotkey_list, line); } - parse_end_free: - free(linebegin); } } @@ -811,13 +840,3 @@ unsigned short key_to_code (char *key) } return 0; } - -int is_empty (const char *s) -{ - while (*s != '\0') { - if (!isspace((unsigned char)*s)) - return 0; - s++; - } - return 1; -} diff --git a/makefile b/makefile index 8627f98..0726bca 100644 --- a/makefile +++ b/makefile @@ -1,6 +1,6 @@ CC = gcc CFLAGS = -Wall -Werror -pedantic --std=c99 -O2 -VERSION = 0.2 +VERSION = 0.3 PREFIX = /usr/local MANPREFIX = ${PREFIX}/share/man