diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4f6f313 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +build +.cache +*~* +*\#* diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..9993d45 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.29) + +project(moka) + +set(CMAKE_EXPORT_COMPILE_COMMANDS On) + +add_subdirectory(lib) +add_subdirectory(src) +add_subdirectory(tests) + +set_property(TARGET moka-core PROPERTY C_STANDARD 99) +set_property(TARGET moka-tests PROPERTY C_STANDARD 99) +set_property(TARGET moka PROPERTY C_STANDARD 99) diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f0e5116 --- /dev/null +++ b/Makefile @@ -0,0 +1,18 @@ +.PHONY: build check install tests + +build: + cmake -B build + cmake --build build + +tests: build + @build/tests/moka-tests \ + && echo -e "\e[32m=== All tests passed ===\e[0m" \ + || echo -e "\e[31m=== Some tests failed ===\e[0m" + +install: tests + sudo cmake --install build + +check: + @cppcheck --enable=all -q lib src tests \ + --suppress=missingIncludeSystem \ + --suppress=unusedFunction diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt new file mode 100644 index 0000000..6abfbf1 --- /dev/null +++ b/lib/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.29) + +project(moka-lib) + +add_library(moka-core + commons.c + status.c + vec.c + str.c +) + +target_compile_options(moka-core + PUBLIC -Wall -Wextra +) + +target_include_directories(moka-core + PUBLIC ${CMAKE_SOURCE_DIR}/lib +) + diff --git a/lib/commons.c b/lib/commons.c new file mode 100644 index 0000000..8d818ba --- /dev/null +++ b/lib/commons.c @@ -0,0 +1,2 @@ +#include "commons.h" + diff --git a/lib/commons.h b/lib/commons.h new file mode 100644 index 0000000..ac475e3 --- /dev/null +++ b/lib/commons.h @@ -0,0 +1,22 @@ +#ifndef MK_COMMON_H +#define MK_COMMON_H + +#include +#include +#include +#include +#include +#include + +#define MK_STRLEN 4096 +#define MK_ENUM_ENUM(X) X +#define MK_ENUM_STRING(X) #X + +#define MK_ENUM_H(PREFIX, DEF) \ +typedef enum {DEF(MK_ENUM_ENUM)} PREFIX; \ +extern char const* PREFIX ## Str [] + +#define MK_ENUM_C(PREFIX, DEF) \ +char const* PREFIX ## Str [] = {DEF(MK_ENUM_STRING)} + +#endif diff --git a/lib/status.c b/lib/status.c new file mode 100644 index 0000000..b1739a6 --- /dev/null +++ b/lib/status.c @@ -0,0 +1,83 @@ +#include "status.h" + +MK_ENUM_C(Status, STATUS_KIND); + +void message_init(struct message* self, + Status kind, + char const* what) +{ + assert(self); + assert(what); + + self->kind = kind; + self->what = strdup(what); +} + +void message_free(struct message* self) +{ + assert(self); + free(self->what); +} + +void status_init(struct status* self) +{ + assert(self); + vec_init(&self->messages); +} + +void status_free(struct status* self) +{ + assert(self); + vec_free_elements(&self->messages, (void*) message_free); + vec_free(&self->messages); +} +void status_push(struct status* self, + Status kind, + char const* format, + ...) +{ + char msg[MK_STRLEN]; + va_list lst; + va_start(lst, format); + + vsnprintf(msg, MK_STRLEN, format, lst); + + struct message* message = malloc(sizeof(struct message)); + message_init(message, kind, msg); + + vec_push(&self->messages, message); + va_end(lst); +} + +void status_dump(struct status* self) +{ + assert(self); + + for (size_t i=0; imessages.size; i++) + { + struct message const* msg = self->messages.data[i]; + + printf("%s| %s\n", + StatusStr[msg->kind] + strlen("STATUS_"), + msg->what + ); + } +} + +bool status_is_ok(struct status* self) +{ + assert(self); + + for (size_t i=0; imessages.size; i++) + { + struct message const* m = self->messages.data[i]; + + if (m->kind == STATUS_ERROR) + { + return false; + } + } + + return true; + +} diff --git a/lib/status.h b/lib/status.h new file mode 100644 index 0000000..e7de7c7 --- /dev/null +++ b/lib/status.h @@ -0,0 +1,41 @@ +#ifndef MK_STATUS_H +#define MK_STATUS_H + +#include "commons.h" +#include "vec.h" + +#define STATUS_KIND(G) \ +G(STATUS_ERROR),\ +G(STATUS_WARNING) + +MK_ENUM_H(Status, STATUS_KIND); + +struct message +{ + Status kind; + char* what; +}; + +struct status +{ + struct vec messages; +}; + +void message_init(struct message* self, + Status kind, + char const* what); +void message_free(struct message* self); + +void status_init(struct status* self); +void status_free(struct status* self); + +void status_push(struct status* self, + Status kind, + char const* format, + ...); + +void status_dump(struct status* self); + +bool status_is_ok(struct status* self); + +#endif diff --git a/lib/str.c b/lib/str.c new file mode 100644 index 0000000..c3fac4f --- /dev/null +++ b/lib/str.c @@ -0,0 +1,70 @@ +#include "str.h" + +void str_init(struct str* self) +{ + assert(self); + self->size = 0; + self->capacity = 0; + self->value = NULL; +} + +void str_free(struct str* self) +{ + assert(self); + free(self->value); + self->value = NULL; + self->size = 0; + self->capacity = 0; +} + +void str_push(struct str* self, char element) +{ + assert(self); + + if (self->capacity == 0) + { + self->capacity = 1; + self->value = calloc(self->capacity, sizeof(char)); + } + + if (self->size + 2 >= self->capacity) + { + self->capacity *= 2; + char* data = realloc(self->value, sizeof(char) * self->capacity); + assert(data); + self->value = data; + } + + self->value[self->size] = element; + self->size++; + self->value[self->size] = '\0'; +} + +void str_extend(struct str* self, char const* rhs) +{ + assert(self); + assert(rhs); + + size_t sz = strlen(rhs); + + for (size_t i=0; icapacity = 0; + self->size = 0; + self->data = NULL; +} + +void vec_free_elements(struct vec* self, void (*func)(void*)) +{ + assert(self); + + for (size_t i=0; isize; i++) + { + if (func != NULL) + { + func(self->data[i]); + } + + free(self->data[i]); + } +} + +void vec_free(struct vec* self) +{ + assert(self); + free(self->data); + self->data = NULL; + self->size = 0; + self->capacity = 0; +} + +void vec_push(struct vec* self, void* element) +{ + assert(self); + assert(element); + + if (self->capacity == 0) + { + self->capacity = 1; + self->data = calloc(self->capacity, sizeof(void*)); + } + else if (self->size + 1 >= self->capacity) + { + self->capacity *= 2; + void** data = realloc( + self->data, + self->capacity * sizeof(void*) + ); + assert(data); + self->data = data; + } + + self->data[self->size] = element; + self->size++; +} + +void* vec_pop(struct vec* self) +{ + assert(self); + assert(self->size > 0); + void* element = self->data[self->size - 1]; + self->size--; + return element; +} diff --git a/lib/vec.h b/lib/vec.h new file mode 100644 index 0000000..64ceaec --- /dev/null +++ b/lib/vec.h @@ -0,0 +1,20 @@ +#ifndef MK_VEC_H +#define MK_VEC_H + +#include "commons.h" + +struct vec +{ + size_t capacity; + size_t size; + void** data; +}; + +void vec_init(struct vec* self); +void vec_free_elements(struct vec* self, void (*func)(void*)); +void vec_free(struct vec* self); + +void vec_push(struct vec* self, void* element); +void* vec_pop(struct vec* self); + +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..e4122ae --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.29) + +project(moka-bin) + +add_executable(moka + main.c +) + +install(TARGETS moka) + +add_dependencies(moka moka-core) + +target_link_libraries(moka + moka-core +) diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..905869d --- /dev/null +++ b/src/main.c @@ -0,0 +1,4 @@ +int main() +{ + return 0; +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..3cc51e0 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.29) + +project(moka-tests) + + +add_executable(moka-tests + main.c +) + +find_package(PkgConfig REQUIRED) +pkg_check_modules(CHECK check REQUIRED IMPORTED_TARGET) + +add_dependencies(moka-tests moka-core) + +target_link_libraries(moka-tests + moka-core + PkgConfig::CHECK +) diff --git a/tests/main.c b/tests/main.c new file mode 100644 index 0000000..b7e2071 --- /dev/null +++ b/tests/main.c @@ -0,0 +1,16 @@ +#include +#include + + +int main() +{ + Suite* s = suite_create("Moka Frontend"); + + + SRunner* runner = srunner_create(s); + srunner_run_all(runner, CK_VERBOSE); + int failed = srunner_ntests_failed(runner); + srunner_free(runner); + + return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +}