diff --git a/config.c b/config.c new file mode 100644 index 0000000..35086f3 --- /dev/null +++ b/config.c @@ -0,0 +1,104 @@ +#include "config.h" +#include "util.h" +#include +#include +#include +#include +#include +#include + +void parsing_error(size_t line) { + fprintf(stderr, "error: failed parsing config at line %zu", line); + exit(EXIT_FAILURE); +} + +Config parse_config(FILE *config_file) { + size_t len = 0; + ssize_t read; + char *line = NULL; + size_t line_index = 0; + bool in_config = false; + + char current_path[MAX_MODULE_NAME_LENGTH]; + Module current_module = { + .path = NULL, + .config = NULL, + }; + size_t config_index = 0; + size_t config_multiplier = 1; + + Config config = { + .modules = malloc(MAX_MODULES * sizeof(Module)), + .module_count = 0, + }; + + // TODO handle errors of all the function inside the while + errno = 0; + + // TODO rewrite this to read the config char by char + while ((read = getline(&line, &len, config_file)) != -1) { + if (read <= 1) + continue; + + // if config is passed to this module + if (line[read - 2u] == '{') { + if (in_config) { + fclose(config_file); + parsing_error(line_index); + } + in_config = true; + // get rid of the '{' + strncpy(current_path, line, (size_t)read - 2); + current_path[read - 2] = '\0'; + + current_module.path = process_str(current_path); + current_module.config = malloc(INITIAL_CONFIG_SIZE * sizeof(char*)); + continue; + } + + // end of config for current module + if (line[read - 2u] == '}') { + if (!in_config) { + fclose(config_file); + parsing_error(line_index); + } + in_config = false; + + if (config_index >= INITIAL_CONFIG_SIZE * config_multiplier) { + config_multiplier *= 2; + current_module.config = realloc(current_module.config, INITIAL_CONFIG_SIZE * config_multiplier); + } + current_module.config[config_index] = NULL; + config.modules[config.module_count] = current_module; + config.module_count += 1; + config_index = 0; + continue; + } + + if (in_config) { + if (config_index >= INITIAL_CONFIG_SIZE * config_multiplier) { + config_multiplier *= 2; + current_module.config = realloc(current_module.config, INITIAL_CONFIG_SIZE * config_multiplier); + } + current_module.config[config_index] = process_str(line); + config_index += 1; + continue; + } + + // no config passed to this module + current_module.path = process_str(line); + + current_module.config = malloc(sizeof(void*)); + current_module.config[0] = NULL; + + config.modules[config.module_count] = current_module; + config.module_count += 1; + + free(line); + } + if (read == -1 && errno != 0) + free(line); + + return config; +} + diff --git a/config.h b/config.h new file mode 100644 index 0000000..1e50a34 --- /dev/null +++ b/config.h @@ -0,0 +1,24 @@ +#ifndef _MODFETCH_CONFIG_H +#define _MODFETCH_CONFIG_H + +#include +#include + +typedef struct { + // path to the binary of this module + char *path; + // name=value strings for each value in config + char **config; +} Module; + +typedef struct { + size_t module_count; + Module *modules; +} Config; + + +void parsing_error(size_t line); + +Config parse_config(FILE *config_file); + +#endif // _MODFETCH_CONFIG_H diff --git a/modfetch.c b/modfetch.c index 497b3bf..c280054 100644 --- a/modfetch.c +++ b/modfetch.c @@ -1,5 +1,8 @@ +#include "config.h" #include "mod.h" #include "semver.h" +#include "util.h" + #include #include #include @@ -19,195 +22,6 @@ static const semver VERSION = { .patch = 0, }; -static const uint8_t MAX_MODULE_NAME_LENGTH = 128; -static const uint8_t MAX_MODULES = 128; - -static const uint8_t INITIAL_CONFIG_SIZE = 8; - -static const uint16_t MAX_PATH_LENGTH = 4096; - -typedef struct { - // path to the binary of this module - char *path; - // name=value strings for each value in config - char **config; -} Module; - -typedef struct { - size_t module_count; - Module *modules; -} Config; - -void parsing_error(size_t line) { - fprintf(stderr, "error: failed parsing config at line %zu", line); - exit(EXIT_FAILURE); -} - -char *remove_whitespaces(const char *str) { - char tmp[strlen(str)]; - size_t i = 0; - size_t j = 0; - while (str[i] != '\0') { - if (isspace(str[i])) { - i += 1; - continue; - } - tmp[j] = str[i]; - i += 1; - j += 1; - } - - char *ret = malloc(j * sizeof(char)); - strncpy(ret, tmp, j); - ret[j] = '\0'; - - return ret; -} - -char *resolve_env_vars(const char *str) { - size_t len = strlen(str); - char *ret = malloc(MAX_PATH_LENGTH * sizeof(char)); - size_t ret_offset = 0; - bool in_env_var = false; - char env_var[MAX_PATH_LENGTH]; - memset(env_var, 0, sizeof(env_var)); - size_t env_var_offset = 0; - - for (size_t i = 0; i < len; ++i) { - if (str[i] == '~') { - char *home = getenv("HOME"); - strcat(ret, home); - ret_offset += strlen(home); - continue; - } - - if (str[i] == '$') { - in_env_var = true; - continue; - } - - // end of current env var - if (in_env_var && !(isalpha(str[i]) || isdigit(str[i]) || str[i] == '_')) { - in_env_var = false; - - char *env = getenv(env_var); - strcat(ret, env); - ret_offset += strlen(env); - memset(env_var, 0, sizeof(env_var)); - env_var_offset = 0; - } - - if (in_env_var) { - env_var[env_var_offset] = str[i]; - env_var_offset += 1; - continue; - } - - ret[ret_offset] = str[i]; - ret_offset += 1; - } - ret[ret_offset] = '\0'; - - return ret; -} - -char *process_str(const char *str) { - char *whitespaceless = remove_whitespaces(str); - char *ret = resolve_env_vars(whitespaceless); - free(whitespaceless); - return ret; -} - -Config parse_config(FILE *config_file) { - size_t len = 0; - ssize_t read; - char *line = NULL; - size_t line_index = 0; - bool in_config = false; - - char current_path[MAX_MODULE_NAME_LENGTH]; - Module current_module = { - .path = NULL, - .config = NULL, - }; - size_t config_index = 0; - size_t config_multiplier = 1; - - Config config = { - .modules = malloc(MAX_MODULES * sizeof(Module)), - .module_count = 0, - }; - - // TODO handle errors of all the function inside the while - errno = 0; - - // TODO rewrite this to read the config char by char - while ((read = getline(&line, &len, config_file)) != -1) { - if (read <= 1) - continue; - - // if config is passed to this module - if (line[read - 2u] == '{') { - if (in_config) { - fclose(config_file); - parsing_error(line_index); - } - in_config = true; - // get rid of the '{' - strncpy(current_path, line, (size_t)read - 2); - current_path[read - 2] = '\0'; - - current_module.path = process_str(current_path); - current_module.config = malloc(INITIAL_CONFIG_SIZE * sizeof(char*)); - continue; - } - - // end of config for current module - if (line[read - 2u] == '}') { - if (!in_config) { - fclose(config_file); - parsing_error(line_index); - } - in_config = false; - - if (config_index >= INITIAL_CONFIG_SIZE * config_multiplier) { - config_multiplier *= 2; - current_module.config = realloc(current_module.config, INITIAL_CONFIG_SIZE * config_multiplier); - } - current_module.config[config_index] = NULL; - config.modules[config.module_count] = current_module; - config.module_count += 1; - config_index = 0; - continue; - } - - if (in_config) { - if (config_index >= INITIAL_CONFIG_SIZE * config_multiplier) { - config_multiplier *= 2; - current_module.config = realloc(current_module.config, INITIAL_CONFIG_SIZE * config_multiplier); - } - current_module.config[config_index] = process_str(line); - config_index += 1; - continue; - } - - // no config passed to this module - current_module.path = process_str(line); - - current_module.config = malloc(sizeof(void*)); - current_module.config[0] = NULL; - - config.modules[config.module_count] = current_module; - config.module_count += 1; - - free(line); - } - if (read == -1 && errno != 0) - free(line); - - return config; -} - int main(int argc, char *argv[]) { char *config_path; diff --git a/util.c b/util.c new file mode 100644 index 0000000..2ff20b6 --- /dev/null +++ b/util.c @@ -0,0 +1,80 @@ +#include "util.h" +#include +#include +#include +#include + +char *remove_whitespaces(const char *str) { + char tmp[strlen(str)]; + size_t i = 0; + size_t j = 0; + while (str[i] != '\0') { + if (isspace(str[i])) { + i += 1; + continue; + } + tmp[j] = str[i]; + i += 1; + j += 1; + } + + char *ret = malloc(j * sizeof(char)); + strncpy(ret, tmp, j); + ret[j] = '\0'; + + return ret; +} + +char *resolve_env_vars(const char *str) { + size_t len = strlen(str); + char *ret = malloc(MAX_PATH_LENGTH * sizeof(char)); + size_t ret_offset = 0; + bool in_env_var = false; + char env_var[MAX_PATH_LENGTH]; + memset(env_var, 0, sizeof(env_var)); + size_t env_var_offset = 0; + + for (size_t i = 0; i < len; ++i) { + if (str[i] == '~') { + char *home = getenv("HOME"); + strcat(ret, home); + ret_offset += strlen(home); + continue; + } + + if (str[i] == '$') { + in_env_var = true; + continue; + } + + // end of current env var + if (in_env_var && !(isalpha(str[i]) || isdigit(str[i]) || str[i] == '_')) { + in_env_var = false; + + char *env = getenv(env_var); + strcat(ret, env); + ret_offset += strlen(env); + memset(env_var, 0, sizeof(env_var)); + env_var_offset = 0; + } + + if (in_env_var) { + env_var[env_var_offset] = str[i]; + env_var_offset += 1; + continue; + } + + ret[ret_offset] = str[i]; + ret_offset += 1; + } + ret[ret_offset] = '\0'; + + return ret; +} + +char *process_str(const char *str) { + char *whitespaceless = remove_whitespaces(str); + char *ret = resolve_env_vars(whitespaceless); + free(whitespaceless); + return ret; +} diff --git a/util.h b/util.h new file mode 100644 index 0000000..63b3e34 --- /dev/null +++ b/util.h @@ -0,0 +1,20 @@ +#ifndef _MODFETCH_UTIL_H +#define _MODFETCH_UTIL_H + +#include + +static const uint8_t MAX_MODULE_NAME_LENGTH = 128; +static const uint8_t MAX_MODULES = 128; + +static const uint8_t INITIAL_CONFIG_SIZE = 8; + +static const uint16_t MAX_PATH_LENGTH = 4096; + + +char *remove_whitespaces(const char *str); + +char *resolve_env_vars(const char *str); + +char *process_str(const char *str); + +#endif // _MODFETCH_UTIL_H