summaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/util')
-rw-r--r--src/util/membuf.c31
-rw-r--r--src/util/membuf.h14
-rw-r--r--src/util/ragel/ragel.h30
-rw-r--r--src/util/ragel/ragel.rl92
4 files changed, 167 insertions, 0 deletions
diff --git a/src/util/membuf.c b/src/util/membuf.c
new file mode 100644
index 0000000..0602679
--- /dev/null
+++ b/src/util/membuf.c
@@ -0,0 +1,31 @@
+#include "membuf.h"
+
+#include <stdlib.h>
+#include <assert.h>
+#include <memory.h>
+#include <err.h>
+
+static void
+membuf_bounds_check(const struct membuf *buf, const size_t nmemb)
+{
+ assert(buf);
+
+ if (buf->mem.len < nmemb || buf->written > buf->mem.len - nmemb)
+ errx(EXIT_FAILURE, "%s: %zu bytes exceeds the maximum storage size of %zu bytes", __func__, buf->written + nmemb, buf->mem.len);
+}
+
+void
+membuf_terminate(struct membuf *buf, const void *data, const size_t data_sz)
+{
+ assert(data || !data_sz);
+ membuf_bounds_check(buf, data_sz);
+ memcpy((char*)buf->mem.data + buf->written, data, data_sz);
+}
+
+void
+membuf_append(struct membuf *buf, const void *data, const size_t data_sz)
+{
+ membuf_terminate(buf, data, data_sz);
+ buf->written += data_sz;
+ assert(buf->written <= buf->mem.len);
+}
diff --git a/src/util/membuf.h b/src/util/membuf.h
new file mode 100644
index 0000000..86d8dde
--- /dev/null
+++ b/src/util/membuf.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <fspec/memory.h>
+
+struct membuf {
+ struct fspec_mem mem;
+ size_t written;
+};
+
+void
+membuf_terminate(struct membuf *buf, const void *data, const size_t data_sz);
+
+void
+membuf_append(struct membuf *buf, const void *data, const size_t data_sz);
diff --git a/src/util/ragel/ragel.h b/src/util/ragel/ragel.h
new file mode 100644
index 0000000..b2c7572
--- /dev/null
+++ b/src/util/ragel/ragel.h
@@ -0,0 +1,30 @@
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+struct ragel_mem {
+ const char *data, *end;
+ bool binary; // binary input bit
+};
+
+struct ragel {
+ struct ragel_mem input; // block of input data
+ uint64_t lineno; // current line
+ const char *p, *pe, *eof; // see ragel doc
+ const char *cl; // current line start
+ const char *name; // may be current file name for example
+ bool error; // error thrown bit
+};
+
+__attribute__((format(printf, 2, 3))) void
+ragel_throw_error(struct ragel *ragel, const char *fmt, ...);
+
+void
+ragel_set_name(struct ragel *ragel, const char *name);
+
+void
+ragel_advance_line(struct ragel *ragel);
+
+void
+ragel_feed_input(struct ragel *ragel, const bool eof, const struct ragel_mem *input);
diff --git a/src/util/ragel/ragel.rl b/src/util/ragel/ragel.rl
new file mode 100644
index 0000000..c52f27b
--- /dev/null
+++ b/src/util/ragel/ragel.rl
@@ -0,0 +1,92 @@
+#include "ragel.h"
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+
+%%{
+ machine ragel;
+ write data noerror nofinal;
+
+ action red { fputs("\x1b[31m", stderr); }
+ action reset { fputs("\x1b[0m", stderr); }
+ action end { fputs("\x1b[0m\n", stderr); }
+ action mark { fputc((fpc == *error ? '^' : '~'), stderr); }
+ action lead { fputc(' ', stderr); }
+ action char { fputc(fc, stderr); }
+
+ valid = ^cntrl - space - punct;
+ mark_token = (space valid | punct) ${ *error = fpc; };
+ search_err := ((any | mark_token) when { fpc != ragel->pe && fpc <= ragel->p })*;
+
+ word = print | valid*;
+ until_err = (any when { fpc != *error })*;
+ print_err := (until_err <: (word - '\n') >red %reset <: (print - '\n')*) $char >*lead %!end %/end;
+ print_mark := (until_err $lead <: (any | word) >red $mark) >*lead %!end %/end;
+}%%
+
+static void
+ragel_exec_error(const struct ragel *ragel, const int start_cs, const char **error)
+{
+ (void)ragel_start;
+ assert(ragel && ragel->cl && error);
+ int cs = start_cs;
+ const char *p = ragel->cl, *pe = ragel->pe, *eof = ragel->eof;
+ assert(p <= pe);
+ %% write exec;
+}
+
+void
+ragel_throw_error(struct ragel *ragel, const char *fmt, ...)
+{
+ assert(ragel && fmt);
+ ragel->error = true;
+
+ const char *error = ragel->p;
+
+ if (!ragel->input.binary)
+ ragel_exec_error(ragel, ragel_en_search_err, &error);
+
+ const char *name = (ragel->name ? ragel->name : "");
+ assert(error >= ragel->cl);
+ uint64_t column = (error - ragel->cl);
+ fprintf(stderr, "\x1b[37m%s:%" PRIu64 ":%" PRIu64 " \x1b[31merror: \x1b[0m", name, ragel->lineno, column);
+
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ fputc('\n', stderr);
+
+ if (!ragel->input.binary) {
+ ragel_exec_error(ragel, ragel_en_print_err, &error);
+ ragel_exec_error(ragel, ragel_en_print_mark, &error);
+ }
+}
+
+void
+ragel_set_name(struct ragel *ragel, const char *name)
+{
+ assert(ragel);
+ ragel->name = name;
+}
+
+void
+ragel_advance_line(struct ragel *ragel)
+{
+ assert(ragel);
+ ++ragel->lineno;
+ ragel->cl = ragel->p;
+}
+
+void
+ragel_feed_input(struct ragel *ragel, const bool eof, const struct ragel_mem *input)
+{
+ assert(ragel);
+ ragel->input = *input;
+ ragel->cl = ragel->p = ragel->input.data;
+ ragel->pe = ragel->input.end;
+ ragel->eof = (eof ? ragel->pe : NULL);
+ assert(ragel->p <= ragel->pe);
+}