required C standard is C23
refactored logger function names to remove underscores added function attributes
This commit is contained in:
parent
12a522b0e6
commit
23968f7acc
|
@ -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)
|
||||
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
|
||||
#include <ast/ast.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/log.h>
|
||||
#include <assert.h>
|
||||
|
||||
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");
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/log.h>
|
||||
#include <assert.h>
|
||||
|
||||
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,
|
||||
|
|
|
@ -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_ */
|
||||
|
|
Loading…
Reference in New Issue