#include "state.h" #include "std_allocator.h" #include #include SandState sand_create_state(SandConfig 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) { (void) S; }