From 23968f7acca68e86ef3cc32f521fc0f00ae90f56 Mon Sep 17 00:00:00 2001 From: servostar Date: Fri, 10 May 2024 15:09:52 +0200 Subject: [PATCH] required C standard is C23 refactored logger function names to remove underscores added function attributes --- CMakeLists.txt | 3 ++ src/ast/ast.c | 79 ++++++++++++++++++++++++++++++++++---------------- src/ast/ast.h | 24 +++++++++++++-- src/sys/log.c | 13 +++++---- src/sys/log.h | 24 +++++++++------ 5 files changed, 102 insertions(+), 41 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 079fc47..f4dd41f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,9 @@ project(gemstone DESCRIPTION "programming language compiler" LANGUAGES C) +set(CMAKE_C_STANDARD 23) +set(CMAKE_C_STANDARD_REQUIRED TRUE) + set(GEMSTONE_TEST_DIR ${PROJECT_SOURCE_DIR}/tests) set(GEMSTONE_BINARY_DIR ${PROJECT_SOURCE_DIR}/bin) diff --git a/src/ast/ast.c b/src/ast/ast.c index ef7ce47..233e8da 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -1,12 +1,13 @@ #include #include -#include #include #include +#include struct AST_Node_t *AST_new_node(enum AST_SyntaxElement_t kind, const char* value) { DEBUG("creating new AST node: %d \"%s\"", kind, value); + assert(kind < AST_ELEMENT_COUNT); struct AST_Node_t *node = malloc(sizeof(struct AST_Node_t)); @@ -14,6 +15,8 @@ struct AST_Node_t *AST_new_node(enum AST_SyntaxElement_t kind, const char* value PANIC("failed to allocate AST node"); } + assert(node != NULL); + // init to discrete state node->parent = NULL; node->children = NULL; @@ -71,10 +74,11 @@ void AST_init() { lookup_table[AST_Condition] = "condition"; } -const char* AST_node_to_string(struct AST_Node_t* node) { +const char* AST_node_to_string(const struct AST_Node_t* node) { DEBUG("converting AST node to string: %p", node); + assert(node != NULL); - const char* string = "unknown"; + const char* string; switch(node->kind) { case AST_Int: @@ -90,11 +94,15 @@ const char* AST_node_to_string(struct AST_Node_t* node) { string = lookup_table[node->kind]; } + assert(string != NULL); + return string; } void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child) { DEBUG("Adding new node %p to %p", child, owner); + assert(owner != NULL); + assert(child != NULL); // if there are no children for now if (owner->child_count == 0) { @@ -111,15 +119,16 @@ void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child) { PANIC("failed to allocate children array of AST node"); } + assert(owner->children != NULL); + owner->children[owner->child_count++] = child; } -struct AST_Node_t *AST_get_node(struct AST_Node_t *owner, size_t idx) { +struct AST_Node_t *AST_get_node(struct AST_Node_t *owner, const size_t idx) { DEBUG("retrvieng node %d from %p", idx, owner); - - if (owner == NULL) { - PANIC("AST owner node is NULL"); - } + assert(owner != NULL); + assert(owner->children != NULL); + assert(idx < owner->child_count); if (owner->children == NULL) { PANIC("AST owner node has no children"); @@ -135,6 +144,9 @@ struct AST_Node_t *AST_get_node(struct AST_Node_t *owner, size_t idx) { } struct AST_Node_t* AST_remove_child(struct AST_Node_t* owner, const size_t idx) { + assert(owner != NULL); + assert(owner->children != NULL); + assert(idx < owner->child_count); struct AST_Node_t* child = owner->children[idx]; @@ -151,6 +163,10 @@ struct AST_Node_t* AST_remove_child(struct AST_Node_t* owner, const size_t idx) } struct AST_Node_t* AST_detach_child(struct AST_Node_t* owner, const struct AST_Node_t* child) { + assert(owner != NULL); + assert(child != NULL); + assert(owner->children != NULL); + for (size_t i = 0; i < owner->child_count; i++) { if (owner->children[i] == child) { return AST_remove_child(owner, i); @@ -158,22 +174,20 @@ struct AST_Node_t* AST_detach_child(struct AST_Node_t* owner, const struct AST_N } PANIC("Child to detach not a child of parent"); - return NULL; } void AST_delete_node(struct AST_Node_t *node) { - DEBUG("Deleting AST node: %p", node); + assert(node != NULL); - if (node == NULL) { - PANIC("Node to free is NULL"); - } + DEBUG("Deleting AST node: %p", node); if (node->children == NULL) { return; } if (node->parent != NULL) { - AST_detach_child(node->parent, node); + const struct AST_Node_t* child = AST_detach_child(node->parent, node); + assert(child == node); } for (size_t i = 0; i < node->child_count; i++) { @@ -186,16 +200,18 @@ void AST_delete_node(struct AST_Node_t *node) { free(node); } -static void __AST_visit_nodes_recurse2(struct AST_Node_t *root, +static void AST_visit_nodes_recurse2(struct AST_Node_t *root, void (*for_each)(struct AST_Node_t *node, size_t depth), - size_t depth) { + const size_t depth) { DEBUG("Recursive visit of %p at %d with %p", root, depth, for_each); + assert(root != NULL); + (for_each)(root, depth); for (size_t i = 0; i < root->child_count; i++) { - __AST_visit_nodes_recurse2(root->children[i], for_each, depth + 1); + AST_visit_nodes_recurse2(root->children[i], for_each, depth + 1); } } @@ -203,12 +219,19 @@ void AST_visit_nodes_recurse(struct AST_Node_t *root, void (*for_each)(struct AST_Node_t *node, size_t depth)) { DEBUG("Starting recursive visit of %p with %p", root, for_each); - __AST_visit_nodes_recurse2(root, for_each, 0); + + assert(root != NULL); + assert(for_each != NULL); + + AST_visit_nodes_recurse2(root, for_each, 0); } -static void __AST_fprint_graphviz_node_definition(FILE* stream, struct AST_Node_t* node) { +static void AST_fprint_graphviz_node_definition(FILE* stream, const struct AST_Node_t* node) { DEBUG("Printing graphviz definition of %p", node); + assert(stream != NULL); + assert(node != NULL); + fprintf(stream, "\tnode%p [label=\"%s\"]\n", (void*) node, AST_node_to_string(node)); if (node->children == NULL) { @@ -216,30 +239,36 @@ static void __AST_fprint_graphviz_node_definition(FILE* stream, struct AST_Node_ } for (size_t i = 0; i < node->child_count; i++) { - __AST_fprint_graphviz_node_definition(stream, node->children[i]); + AST_fprint_graphviz_node_definition(stream, node->children[i]); } } -static void __AST_fprint_graphviz_node_connection(FILE* stream, struct AST_Node_t* node) { +static void AST_fprint_graphviz_node_connection(FILE* stream, const struct AST_Node_t* node) { DEBUG("Printing graphviz connection of %p", node); + assert(stream != NULL); + assert(node != NULL); + if (node->children == NULL) { return; } for (size_t i = 0; i < node->child_count; i++) { fprintf(stream, "\tnode%p -- node%p\n", (void*) node, (void*) node->children[i]); - __AST_fprint_graphviz_node_connection(stream, node->children[i]); + AST_fprint_graphviz_node_connection(stream, node->children[i]); } } -void AST_fprint_graphviz(FILE* stream, struct AST_Node_t* root) { +void AST_fprint_graphviz(FILE* stream, const struct AST_Node_t* root) { DEBUG("Starting print of graphviz graph of %p", root); + assert(stream != NULL); + assert(root != NULL); + fprintf(stream, "graph {\n"); - __AST_fprint_graphviz_node_definition(stream, root); - __AST_fprint_graphviz_node_connection(stream, root); + AST_fprint_graphviz_node_definition(stream, root); + AST_fprint_graphviz_node_connection(stream, root); fprintf(stream, "}\n"); } diff --git a/src/ast/ast.h b/src/ast/ast.h index 40c9af2..5129765 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -102,7 +102,9 @@ void AST_init(void); * @param node to return string representation of * @return string represenation of the node */ -const char* AST_node_to_string(struct AST_Node_t* node); +[[maybe_unused]] +[[gnu::nonnull(1)]] +const char* AST_node_to_string(const struct AST_Node_t* node); /** * @brief Create a new node struct on the system heap. Initializes the struct with the given values. @@ -112,6 +114,9 @@ const char* AST_node_to_string(struct AST_Node_t* node); * @param value an optional value for this node * @return */ +[[maybe_unused]] +[[nodiscard("pointer must be freed")]] +[[gnu::returns_nonnull]] struct AST_Node_t *AST_new_node(enum AST_SyntaxElement_t kind, const char* value); /** @@ -120,6 +125,8 @@ struct AST_Node_t *AST_new_node(enum AST_SyntaxElement_t kind, const char* value * Use of the supplied node after this call is undefined behavior * @param node The node to deallocate */ +[[maybe_unused]] +[[gnu::nonnull(1)]] void AST_delete_node(struct AST_Node_t * node); /** @@ -128,6 +135,8 @@ void AST_delete_node(struct AST_Node_t * node); * @param owner node to add a child to * @param child node to be added as a child */ +[[maybe_unused]] +[[gnu::nonnull(1), gnu::nonnull(2)]] void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child); /** @@ -138,6 +147,9 @@ void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child); * @param idx the index of the child to remove * @return a pointer to the child which was removed */ +[[maybe_unused]] +[[nodiscard("pointer must be freed")]] +[[gnu::nonnull(1)]] struct AST_Node_t* AST_remove_child(struct AST_Node_t* owner, size_t idx); /** @@ -148,6 +160,8 @@ struct AST_Node_t* AST_remove_child(struct AST_Node_t* owner, size_t idx); * @param child the child to detach * @return a pointer to child detached */ +[[nodiscard("pointer must be freed")]] +[[gnu::nonnull(1), gnu::nonnull(1)]] struct AST_Node_t* AST_detach_child(struct AST_Node_t* owner, const struct AST_Node_t* child); /** @@ -159,6 +173,8 @@ struct AST_Node_t* AST_detach_child(struct AST_Node_t* owner, const struct AST_N * @param idx the index of the child to get a pointer to * @return a pointer to the n-th child of the owner node */ +[[maybe_unused]] +[[gnu::nonnull(1)]] struct AST_Node_t *AST_get_node(struct AST_Node_t *owner, size_t idx); /** @@ -166,6 +182,8 @@ struct AST_Node_t *AST_get_node(struct AST_Node_t *owner, size_t idx); * @param root the root to recursively execute a function for * @param for_each the function to execute */ +[[maybe_unused]] +[[gnu::nonnull(1), gnu::nonnull(2)]] void AST_visit_nodes_recurse(struct AST_Node_t *root, void (*for_each)(struct AST_Node_t *node, size_t depth)); @@ -175,6 +193,8 @@ void AST_visit_nodes_recurse(struct AST_Node_t *root, * @param stream The stream to print to. Can be a file, stdout, ... * @param node the topmost ancestor */ -void AST_fprint_graphviz(FILE* stream, struct AST_Node_t* node); +[[maybe_unused]] +[[gnu::nonnull(1), gnu::nonnull(2)]] +void AST_fprint_graphviz(FILE* stream, const struct AST_Node_t* node); #endif diff --git a/src/sys/log.c b/src/sys/log.c index e3a7cd6..0aeab5f 100644 --- a/src/sys/log.c +++ b/src/sys/log.c @@ -3,6 +3,7 @@ #include #include #include +#include static struct Logger_t { FILE** streams; @@ -11,13 +12,15 @@ static struct Logger_t { void log_init(void) { + assert(LOG_DEFAULT_STREAM != NULL); log_register_stream(LOG_DEFAULT_STREAM); } void log_register_stream(FILE* restrict stream) { - if (stream == NULL) - PANIC("stream to register is NULL"); + // replace runtime check with assertion + // only to be used in debug target + assert(stream != NULL); if (GlobalLogger.stream_count == 0) { @@ -57,7 +60,7 @@ static void vflogf( vfprintf(stream, format, args); } -void __logf( +void syslog_logf( const char* restrict level, const char* restrict file, const unsigned long line, @@ -78,7 +81,7 @@ void __logf( va_end(args); } -void __panicf( +void syslog_panicf( const char* restrict file, const unsigned long line, const char* restrict func, @@ -95,7 +98,7 @@ void __panicf( exit(EXIT_FAILURE); } -void __fatalf( +void syslog_fatalf( const char* restrict file, const unsigned long line, const char* restrict func, diff --git a/src/sys/log.h b/src/sys/log.h index 64e8d44..6b8991d 100644 --- a/src/sys/log.h +++ b/src/sys/log.h @@ -34,14 +34,14 @@ * This macro will print debug information to stderr and call abort() to * performa a ungracefull exit. No clean up possible. */ -#define PANIC(format, ...) __panicf(__FILE_NAME__, __LINE__, __func__, format"\n", ##__VA_ARGS__) +#define PANIC(format, ...) syslog_panicf(__FILE_NAME__, __LINE__, __func__, format"\n", ##__VA_ARGS__) /** * @brief Panic is used in cases where the process is in an invalid or undefined state. * This macro will print debug information to stderr and call exit() to * initiate a gracefull exit, giving the process the opportunity to clean up. */ -#define FATAL(format, ...) __fatalf(__FILE_NAME__, __LINE__, __func__, format"\n", ##__VA_ARGS__) +#define FATAL(format, ...) syslog_fatalf(__FILE_NAME__, __LINE__, __func__, format"\n", ##__VA_ARGS__) /* Standard log macros. These will not terminate the application. @@ -56,7 +56,7 @@ will not print. #define __LOG(level, priority, format, ...) \ do { \ if (LOG_LEVEL <= priority) \ - __logf(level, __FILE_NAME__, __LINE__, __func__, format, ##__VA_ARGS__); \ + syslog_logf(level, __FILE_NAME__, __LINE__, __func__, format, ##__VA_ARGS__); \ } while(0) /** @@ -69,10 +69,11 @@ will not print. * @param format the format to print following args in * @param ... */ -void __logf( +[[gnu::nonnull(1), gnu::nonnull(2), gnu::nonnull(4)]] +void syslog_logf( const char* restrict level, const char* restrict file, - const unsigned long line, + unsigned long line, const char* restrict func, const char* restrict format, ...); @@ -86,9 +87,11 @@ void __logf( * @param format the format to print following args in * @param ... */ -void __panicf( +[[noreturn]] +[[gnu::nonnull(1), gnu::nonnull(3), gnu::nonnull(4)]] +void syslog_panicf( const char* restrict file, - const unsigned long line, + unsigned long line, const char* restrict func, const char* restrict format, ...); @@ -102,9 +105,11 @@ void __panicf( * @param format the format to print following args in * @param ... */ -void __fatalf( +[[noreturn]] +[[gnu::nonnull(1), gnu::nonnull(3), gnu::nonnull(4)]] +void syslog_fatalf( const char* restrict file, - const unsigned long line, + unsigned long line, const char* restrict func, const char* restrict format, ...); @@ -120,6 +125,7 @@ void log_init(void); * * @param stream */ +[[gnu::nonnull(1)]] void log_register_stream(FILE* restrict stream); #endif /* _SYS_ERR_H_ */