summaryrefslogtreecommitdiff
path: root/src/core/state.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/state.c')
-rw-r--r--src/core/state.c69
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) {