diff options
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/membuf.c | 31 | ||||
-rw-r--r-- | src/util/membuf.h | 14 | ||||
-rw-r--r-- | src/util/ragel/ragel.h | 30 | ||||
-rw-r--r-- | src/util/ragel/ragel.rl | 92 |
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); +} |