refactor shit out of modfetch.c
This commit is contained in:
parent
d6961a75f3
commit
8081a8d302
5 changed files with 231 additions and 189 deletions
104
config.c
Normal file
104
config.c
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
#include "config.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
24
config.h
Normal file
24
config.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef _MODFETCH_CONFIG_H
|
||||||
|
#define _MODFETCH_CONFIG_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
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
|
192
modfetch.c
192
modfetch.c
|
@ -1,5 +1,8 @@
|
||||||
|
#include "config.h"
|
||||||
#include "mod.h"
|
#include "mod.h"
|
||||||
#include "semver.h"
|
#include "semver.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
@ -19,195 +22,6 @@ static const semver VERSION = {
|
||||||
.patch = 0,
|
.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[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
char *config_path;
|
char *config_path;
|
||||||
|
|
80
util.c
Normal file
80
util.c
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
#include "util.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
20
util.h
Normal file
20
util.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef _MODFETCH_UTIL_H
|
||||||
|
#define _MODFETCH_UTIL_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
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
|
Loading…
Reference in a new issue