diff options
Diffstat (limited to 'src/core/state.c')
-rw-r--r-- | src/core/state.c | 69 |
1 files changed, 66 insertions, 3 deletions
diff --git a/src/core/state.c b/src/core/state.c index 91bd9e4..18448eb 100644 --- a/src/core/state.c +++ b/src/core/state.c @@ -1,9 +1,72 @@ #include "state.h" +#include "std_allocator.h" + +#include <assert.h> +#include <stdarg.h> SandState sand_create_state(SandConfig config) { - return (SandState) { - .config = config, - }; + SandState S; + + S.config = config; + S.gpa = sand_get_std_allocator(); + + return S; +} + +char *sand_vasprintf(SandAllocator *a, size_t *length_out, const char *fmt, va_list ap) { + va_list ap_clone; + + va_copy(ap_clone, ap); + int length = vsnprintf(NULL, 0, fmt, ap_clone); + va_end(ap_clone); + if (length < 0) { + goto fail; + } + + char *buffer = sand_allocate(a, length + 1); // Include NUL character. + if (buffer == NULL) { + goto fail; + } + + va_copy(ap_clone, ap); + int final_length = vsnprintf(buffer, length + 1, fmt, ap_clone); + va_end(ap_clone); + assert(final_length == length); + + if (length_out != NULL) { + *length_out = length; + } + return buffer; + +fail: + if (length_out != NULL) { + *length_out = 0; + } + return NULL; +} + +_SAND_FORMAT_ATTR(printf, 3, 4) +char *sand_asprintf(SandAllocator *a, size_t *length_out, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + char *result = sand_vasprintf(a, length_out, fmt, ap); + va_end(ap); + return result; +} + +void sand_print_diagnostic(SandState *S, const SandLocation *location, SandDiagnosticLevel level, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + size_t message_length; + char *message = sand_vasprintf(&S->gpa, &message_length, fmt, ap); + va_end(ap); + + if (message == NULL) { + return; // FIXME: What do we do here? + } + + S->config.diagnostic_handler(location ,level, message, message_length); + sand_deallocate(&S->gpa, message, message_length + 1); } void sand_destroy_state(SandState *S) { |