diff --git a/HACKING b/HACKING new file mode 100644 index 0000000000000000000000000000000000000000..869c327574673b97402e235c576bc756740fa1dd --- /dev/null +++ b/HACKING @@ -0,0 +1,12 @@ +Privileged arguments +==================== + +As a matter of convenience, there are several identifiers that +internal macros use. Chances are that if you use these names for other +things, you're gonna have a bad time. + +In particular, these names, and the macros that use them, are: +- state: + Used by a_new and company. Should be an HParseState* +- mm__: + Used by h_new and h_free. Should be an HAllocator* diff --git a/src/Makefile b/src/Makefile index faae8a7d4bedad4b1900b930abe2cafd05f9ab92..e4d70d127b2dd07093cb21bdd566d74a0e18129f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -32,6 +32,8 @@ OUTPUTS := bitreader.o \ pprint.o \ allocator.o \ datastructures.o \ + system_allocator.o \ + test_suite.o \ test_suite \ $(PARSERS:%=parsers/%.o) @@ -45,7 +47,7 @@ all: libhammer.a test_suite test_suite: test_suite.o libhammer.a $(call hush, "Linking $@") $(CC) -o $@ $^ $(LDFLAGS) -libhammer.a: bitreader.o hammer.o pprint.o allocator.o datastructures.o bitwriter.o \ +libhammer.a: bitreader.o hammer.o pprint.o allocator.o datastructures.o bitwriter.o system_allocator.o \ $(PARSERS:%=parsers/%.o) bitreader.o: test_suite.h diff --git a/src/allocator.c b/src/allocator.c index 59c6e5097f67443b933c168f58e791ab2684301b..e345c875317716da362e5b8ca9ed35298dc32e59 100644 --- a/src/allocator.c +++ b/src/allocator.c @@ -15,11 +15,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include <glib.h> +#include <string.h> #include <stdint.h> #include <sys/types.h> -#include "allocator.h" +#include "hammer.h" +#include "internal.h" + struct arena_link { // TODO: @@ -36,22 +38,25 @@ struct arena_link { struct HArena_ { struct arena_link *head; + struct HAllocator_ *mm__; size_t block_size; size_t used; size_t wasted; }; -HArena *h_new_arena(size_t block_size) { +HArena *h_new_arena(HAllocator* mm__, size_t block_size) { if (block_size == 0) block_size = 4096; - struct HArena_ *ret = g_new(struct HArena_, 1); - struct arena_link *link = (struct arena_link*)g_malloc0(sizeof(struct arena_link) + block_size); + struct HArena_ *ret = h_new(struct HArena_, 1); + struct arena_link *link = (struct arena_link*)mm__->alloc(mm__, sizeof(struct arena_link) + block_size); + memset(link, 0, sizeof(struct arena_link) + block_size); link->free = block_size; link->used = 0; link->next = NULL; ret->head = link; ret->block_size = block_size; ret->used = 0; + ret->mm__ = mm__; ret->wasted = sizeof(struct arena_link) + sizeof(struct HArena_) + block_size; return ret; } @@ -70,13 +75,15 @@ void* h_arena_malloc(HArena *arena, size_t size) { // This involves some annoying casting... arena->used += size; arena->wasted += sizeof(struct arena_link*); - void* link = g_malloc(size + sizeof(struct arena_link*)); + void* link = arena->mm__->alloc(arena->mm__, size + sizeof(struct arena_link*)); + memset(link, 0, size + sizeof(struct arena_link*)); *(struct arena_link**)link = arena->head->next; arena->head->next = (struct arena_link*)link; return (void*)(((uint8_t*)link) + sizeof(struct arena_link*)); } else { // we just need to allocate an ordinary new block. - struct arena_link *link = (struct arena_link*)g_malloc0(sizeof(struct arena_link) + arena->block_size); + struct arena_link *link = (struct arena_link*)arena->mm__->alloc(arena->mm__, sizeof(struct arena_link) + arena->block_size); + memset(link, 0, sizeof(struct arena_link) + arena->block_size); link->free = arena->block_size - size; link->used = size; link->next = arena->head; @@ -92,16 +99,17 @@ void h_arena_free(HArena *arena, void* ptr) { } void h_delete_arena(HArena *arena) { + HAllocator *mm__ = arena->mm__; struct arena_link *link = arena->head; while (link) { struct arena_link *next = link->next; // Even in the case of a special block, without the full arena // header, this is correct, because the next pointer is the first // in the structure. - g_free(link); + h_free(link); link = next; } - g_free(arena); + h_free(arena); } void h_allocator_stats(HArena *arena, HArenaStats *stats) { diff --git a/src/allocator.h b/src/allocator.h index 3af22d04ed19c2e6043d5b1af3d73c7685f9d8d4..e83cae7cbfecebc58dd810671385b1d63f72d9fb 100644 --- a/src/allocator.h +++ b/src/allocator.h @@ -19,9 +19,15 @@ #define HAMMER_ALLOCATOR__H__ #include <sys/types.h> +typedef struct HAllocator_ { + void* (*alloc)(struct HAllocator_* allocator, size_t size); + void* (*realloc)(struct HAllocator_* allocator, void* ptr, size_t size); + void (*free)(struct HAllocator_* allocator, void* ptr); +} HAllocator; + typedef struct HArena_ HArena ; // hidden implementation -HArena *h_new_arena(size_t block_size); // pass 0 for default... +HArena *h_new_arena(HAllocator* allocator, size_t block_size); // pass 0 for default... void* h_arena_malloc(HArena *arena, size_t count) __attribute__(( malloc, alloc_size(2) )); void h_arena_free(HArena *arena, void* ptr); // For future expansion, with alternate memory managers. void h_delete_arena(HArena *arena); diff --git a/src/bitwriter.c b/src/bitwriter.c index 9a72e22459c8ecedc066ba5ed4327db3f81ade39..e716f0946d6c5ebc60d5182bccaf6234d1222c3d 100644 --- a/src/bitwriter.c +++ b/src/bitwriter.c @@ -7,6 +7,7 @@ // This file provides the logical inverse of bitreader.c struct HBitWriter_ { uint8_t* buf; + HAllocator *mm__; size_t index; size_t capacity; char bit_offset; // unlike in bit_reader, this is always the number @@ -16,10 +17,12 @@ struct HBitWriter_ { }; // h_bit_writer_ -HBitWriter *h_bit_writer_new() { - HBitWriter *writer = g_new0(HBitWriter, 1); - writer->buf = g_malloc0(writer->capacity = 8); - +HBitWriter *h_bit_writer_new(HAllocator* mm__) { + HBitWriter *writer = h_new(HBitWriter, 1); + memset(writer, 0, sizeof(*writer)); + writer->buf = mm__->alloc(mm__, writer->capacity = 8); + memset(writer->buf, 0, writer->capacity); + writer->mm__ = mm__; writer->flags = BYTE_BIG_ENDIAN | BIT_BIG_ENDIAN; return writer; @@ -41,7 +44,7 @@ static void h_bit_writer_reserve(HBitWriter* w, size_t nbits) { int nbytes = (nbits + 7) / 8 + ((w->bit_offset != 0) ? 1 : 0); size_t old_capacity = w->capacity; while (w->index + nbytes >= w->capacity) { - w->buf = g_realloc(w->buf, w->capacity *= 2); + w->buf = w->mm__->realloc(w->mm__, w->buf, w->capacity *= 2); } if (old_capacity != w->capacity) @@ -100,8 +103,9 @@ const uint8_t *h_bit_writer_get_buffer(HBitWriter* w, size_t *len) { } void h_bit_writer_free(HBitWriter* w) { - g_free(w->buf); - g_free(w); + HAllocator *mm__ = w->mm__; + h_free(w->buf); + h_free(w); } #ifdef INCLUDE_TESTS @@ -114,7 +118,7 @@ typedef struct { void run_bitwriter_test(bitwriter_test_elem data[], char flags) { size_t len; const uint8_t *buf; - HBitWriter *w = h_bit_writer_new(); + HBitWriter *w = h_bit_writer_new(&system_allocator); int i; w->flags = flags; for (i = 0; data[i].nbits; i++) { diff --git a/src/hammer.c b/src/hammer.c index 3eab2d722266f8ce52a7e219c3dddb77d19c2d30..52881ec653609ddf6957670fba8654908a96d3ae 100644 --- a/src/hammer.c +++ b/src/hammer.c @@ -238,9 +238,12 @@ static gboolean cache_key_equal(gconstpointer key1, gconstpointer key2) { } -HParseResult* h_parse(const HParser* parser, const uint8_t* input, size_t length) { +HParseResult* h_parse(const HParser* parser, const uint8_t* input, size_t length) { + return h_parse__m(&system_allocator, parser, input, length); +} +HParseResult* h_parse__m(HAllocator* mm__, const HParser* parser, const uint8_t* input, size_t length) { // Set up a parse state... - HArena * arena = h_new_arena(0); + HArena * arena = h_new_arena(mm__, 0); HParseState *parse_state = a_new_(arena, HParseState, 1); parse_state->cache = h_hashtable_new(arena, cache_key_equal, // key_equal_func cache_key_hash); // hash_func diff --git a/src/hammer.h b/src/hammer.h index a219dfe2024d4b112a1cac9b20cc2a2a611a3765..2c5a5cf2d0a4a26c55222d93fa2b3131ff020b5e 100644 --- a/src/hammer.h +++ b/src/hammer.h @@ -113,18 +113,47 @@ typedef struct HParser_ { void *env; } HParser; +// {{{ Preprocessor definitions +#define HAMMER_FN_DECL_NOARG(rtype_t, name) \ + rtype_t name(void); \ + rtype_t name##__m(HAllocator* mm__) + +#define HAMMER_FN_DECL(rtype_t, name, ...) \ + rtype_t name(__VA_ARGS__); \ + rtype_t name##__m(HAllocator* mm__, __VA_ARGS__) + +#define HAMMER_FN_DECL_ATTR(attr, rtype_t, name, ...) \ + rtype_t name(__VA_ARGS__) attr; \ + rtype_t name##__m(HAllocator* mm__, __VA_ARGS__) attr + +#define HAMMER_FN_DECL_VARARGS(rtype_t, name, ...) \ + rtype_t name(__VA_ARGS__, ...); \ + rtype_t name##__m(HAllocator* mm__, __VA_ARGS__, ...); \ + rtype_t name##__mv(HAllocator* mm__, __VA_ARGS__, va_list ap); \ + rtype_t name##__v(__VA_ARGS__, va_list ap) + +// Note: this drops the attributes on the floor for the __v versions +#define HAMMER_FN_DECL_VARARGS_ATTR(attr, rtype_t, name, ...) \ + rtype_t name(__VA_ARGS__, ...) attr; \ + rtype_t name##__m(HAllocator* mm__, __VA_ARGS__, ...) attr; \ + rtype_t name##__mv(HAllocator* mm__, __VA_ARGS__, va_list ap); \ + rtype_t name##__v(__VA_ARGS__, va_list ap) + +// }}} + + /** * Top-level function to call a parser that has been built over some * piece of input (of known size). */ -HParseResult* h_parse(const HParser* parser, const uint8_t* input, size_t length); +HAMMER_FN_DECL(HParseResult*, h_parse, const HParser* parser, const uint8_t* input, size_t length); /** * Given a string, returns a parser that parses that string value. * * Result token type: TT_BYTES */ -const HParser* h_token(const uint8_t *str, const size_t len); +HAMMER_FN_DECL(const HParser*, h_token, const uint8_t *str, const size_t len); /** * Given a single character, returns a parser that parses that @@ -132,7 +161,7 @@ const HParser* h_token(const uint8_t *str, const size_t len); * * Result token type: TT_UINT */ -const HParser* h_ch(const uint8_t c); +HAMMER_FN_DECL(const HParser*, h_ch, const uint8_t c); /** * Given two single-character bounds, lower and upper, returns a parser @@ -141,14 +170,14 @@ const HParser* h_ch(const uint8_t c); * * Result token type: TT_UINT */ -const HParser* h_ch_range(const uint8_t lower, const uint8_t upper); +HAMMER_FN_DECL(const HParser*, h_ch_range, const uint8_t lower, const uint8_t upper); /** * Given an integer parser, p, and two integer bounds, lower and upper, * returns a parser that parses an integral value within the range * [lower, upper] (inclusive). */ -const HParser* h_int_range(const HParser *p, const int64_t lower, const int64_t upper); +HAMMER_FN_DECL(const HParser*, h_int_range, const HParser *p, const int64_t lower, const int64_t upper); /** * Returns a parser that parses the specified number of bits. sign == @@ -156,63 +185,63 @@ const HParser* h_int_range(const HParser *p, const int64_t lower, const int64_t * * Result token type: TT_SINT if sign == true, TT_UINT if sign == false */ -const HParser* h_bits(size_t len, bool sign); +HAMMER_FN_DECL(const HParser*, h_bits, size_t len, bool sign); /** * Returns a parser that parses a signed 8-byte integer value. * * Result token type: TT_SINT */ -const HParser* h_int64(); +HAMMER_FN_DECL_NOARG(const HParser*, h_int64); /** * Returns a parser that parses a signed 4-byte integer value. * * Result token type: TT_SINT */ -const HParser* h_int32(); +HAMMER_FN_DECL_NOARG(const HParser*, h_int32); /** * Returns a parser that parses a signed 2-byte integer value. * * Result token type: TT_SINT */ -const HParser* h_int16(); +HAMMER_FN_DECL_NOARG(const HParser*, h_int16); /** * Returns a parser that parses a signed 1-byte integer value. * * Result token type: TT_SINT */ -const HParser* h_int8(); +HAMMER_FN_DECL_NOARG(const HParser*, h_int8); /** * Returns a parser that parses an unsigned 8-byte integer value. * * Result token type: TT_UINT */ -const HParser* h_uint64(); +HAMMER_FN_DECL_NOARG(const HParser*, h_uint64); /** * Returns a parser that parses an unsigned 4-byte integer value. * * Result token type: TT_UINT */ -const HParser* h_uint32(); +HAMMER_FN_DECL_NOARG(const HParser*, h_uint32); /** * Returns a parser that parses an unsigned 2-byte integer value. * * Result token type: TT_UINT */ -const HParser* h_uint16(); +HAMMER_FN_DECL_NOARG(const HParser*, h_uint16); /** * Returns a parser that parses an unsigned 1-byte integer value. * * Result token type: TT_UINT */ -const HParser* h_uint8(); +HAMMER_FN_DECL_NOARG(const HParser*, h_uint8); /** * Given another parser, p, returns a parser that skips any whitespace @@ -220,7 +249,7 @@ const HParser* h_uint8(); * * Result token type: p's result type */ -const HParser* h_whitespace(const HParser* p); +HAMMER_FN_DECL(const HParser*, h_whitespace, const HParser* p); /** * Given two parsers, p and q, returns a parser that parses them in @@ -228,7 +257,7 @@ const HParser* h_whitespace(const HParser* p); * * Result token type: p's result type */ -const HParser* h_left(const HParser* p, const HParser* q); +HAMMER_FN_DECL(const HParser*, h_left, const HParser* p, const HParser* q); /** * Given two parsers, p and q, returns a parser that parses them in @@ -236,7 +265,7 @@ const HParser* h_left(const HParser* p, const HParser* q); * * Result token type: q's result type */ -const HParser* h_right(const HParser* p, const HParser* q); +HAMMER_FN_DECL(const HParser*, h_right, const HParser* p, const HParser* q); /** * Given three parsers, p, x, and q, returns a parser that parses them in @@ -244,7 +273,7 @@ const HParser* h_right(const HParser* p, const HParser* q); * * Result token type: x's result type */ -const HParser* h_middle(const HParser* p, const HParser* x, const HParser* q); +HAMMER_FN_DECL(const HParser*, h_middle, const HParser* p, const HParser* x, const HParser* q); /** * Given another parser, p, and a function f, returns a parser that @@ -252,21 +281,21 @@ const HParser* h_middle(const HParser* p, const HParser* x, const HParser* q); * * Result token type: any */ -const HParser* h_action(const HParser* p, const HAction a); +HAMMER_FN_DECL(const HParser*, h_action, const HParser* p, const HAction a); /** * Parse a single character in the given charset. * * Result token type: TT_UINT */ -const HParser* h_in(const uint8_t *charset, size_t length); +HAMMER_FN_DECL(const HParser*, h_in, const uint8_t *charset, size_t length); /** * Parse a single character *NOT* in the given charset. * * Result token type: TT_UINT */ -const HParser* h_not_in(const uint8_t *charset, size_t length); +HAMMER_FN_DECL(const HParser*, h_not_in, const uint8_t *charset, size_t length); /** * A no-argument parser that succeeds if there is no more input to @@ -274,14 +303,14 @@ const HParser* h_not_in(const uint8_t *charset, size_t length); * * Result token type: None. The HParseResult exists but its AST is NULL. */ -const HParser* h_end_p(); +HAMMER_FN_DECL_NOARG(const HParser*, h_end_p); /** * This parser always fails. * * Result token type: NULL. Always. */ -const HParser* h_nothing_p(); +HAMMER_FN_DECL_NOARG(const HParser*, h_nothing_p); /** * Given a null-terminated list of parsers, apply each parser in order. @@ -289,7 +318,7 @@ const HParser* h_nothing_p(); * * Result token type: TT_SEQUENCE */ -const HParser* h_sequence(const HParser* p, ...) __attribute__((sentinel)); +HAMMER_FN_DECL_VARARGS_ATTR(__attribute__((sentinel)), const HParser*, h_sequence, const HParser* p); /** * Given an array of parsers, p_array, apply each parser in order. The @@ -298,7 +327,7 @@ const HParser* h_sequence(const HParser* p, ...) __attribute__((sentinel)); * * Result token type: The type of the first successful parser's result. */ -const HParser* h_choice(const HParser* p, ...) __attribute__((sentinel)); +HAMMER_FN_DECL_VARARGS_ATTR(__attribute__((sentinel)), const HParser*, h_choice, const HParser* p); /** * Given two parsers, p1 and p2, this parser succeeds in the following @@ -308,7 +337,7 @@ const HParser* h_choice(const HParser* p, ...) __attribute__((sentinel)); * * Result token type: p1's result type. */ -const HParser* h_butnot(const HParser* p1, const HParser* p2); +HAMMER_FN_DECL(const HParser*, h_butnot, const HParser* p1, const HParser* p2); /** * Given two parsers, p1 and p2, this parser succeeds in the following @@ -318,7 +347,7 @@ const HParser* h_butnot(const HParser* p1, const HParser* p2); * * Result token type: p1's result type. */ -const HParser* h_difference(const HParser* p1, const HParser* p2); +HAMMER_FN_DECL(const HParser*, h_difference, const HParser* p1, const HParser* p2); /** * Given two parsers, p1 and p2, this parser succeeds if *either* p1 or @@ -326,7 +355,7 @@ const HParser* h_difference(const HParser* p1, const HParser* p2); * * Result token type: The type of the result of whichever parser succeeded. */ -const HParser* h_xor(const HParser* p1, const HParser* p2); +HAMMER_FN_DECL(const HParser*, h_xor, const HParser* p1, const HParser* p2); /** * Given a parser, p, this parser succeeds for zero or more repetitions @@ -334,7 +363,7 @@ const HParser* h_xor(const HParser* p1, const HParser* p2); * * Result token type: TT_SEQUENCE */ -const HParser* h_many(const HParser* p); +HAMMER_FN_DECL(const HParser*, h_many, const HParser* p); /** * Given a parser, p, this parser succeeds for one or more repetitions @@ -342,7 +371,7 @@ const HParser* h_many(const HParser* p); * * Result token type: TT_SEQUENCE */ -const HParser* h_many1(const HParser* p); +HAMMER_FN_DECL(const HParser*, h_many1, const HParser* p); /** * Given a parser, p, this parser succeeds for exactly N repetitions @@ -350,7 +379,7 @@ const HParser* h_many1(const HParser* p); * * Result token type: TT_SEQUENCE */ -const HParser* h_repeat_n(const HParser* p, const size_t n); +HAMMER_FN_DECL(const HParser*, h_repeat_n, const HParser* p, const size_t n); /** * Given a parser, p, this parser succeeds with the value p parsed or @@ -358,7 +387,7 @@ const HParser* h_repeat_n(const HParser* p, const size_t n); * * Result token type: If p succeeded, the type of its result; if not, TT_NONE. */ -const HParser* h_optional(const HParser* p); +HAMMER_FN_DECL(const HParser*, h_optional, const HParser* p); /** * Given a parser, p, this parser succeeds if p succeeds, but doesn't @@ -366,7 +395,7 @@ const HParser* h_optional(const HParser* p); * * Result token type: None. The HParseResult exists but its AST is NULL. */ -const HParser* h_ignore(const HParser* p); +HAMMER_FN_DECL(const HParser*, h_ignore, const HParser* p); /** * Given a parser, p, and a parser for a separator, sep, this parser @@ -377,7 +406,7 @@ const HParser* h_ignore(const HParser* p); * * Result token type: TT_SEQUENCE */ -const HParser* h_sepBy(const HParser* p, const HParser* sep); +HAMMER_FN_DECL(const HParser*, h_sepBy, const HParser* p, const HParser* sep); /** * Given a parser, p, and a parser for a separator, sep, this parser matches a list of things that p can parse, separated by sep. Unlike sepBy, this ensures that the result has at least one element. @@ -385,14 +414,14 @@ const HParser* h_sepBy(const HParser* p, const HParser* sep); * * Result token type: TT_SEQUENCE */ -const HParser* h_sepBy1(const HParser* p, const HParser* sep); +HAMMER_FN_DECL(const HParser*, h_sepBy1, const HParser* p, const HParser* sep); /** * This parser always returns a zero length match, i.e., empty string. * * Result token type: None. The HParseResult exists but its AST is NULL. */ -const HParser* h_epsilon_p(); +HAMMER_FN_DECL_NOARG(const HParser*, h_epsilon_p); /** * This parser applies its first argument to read an unsigned integer @@ -403,7 +432,7 @@ const HParser* h_epsilon_p(); * * Result token type: TT_SEQUENCE */ -const HParser* h_length_value(const HParser* length, const HParser* value); +HAMMER_FN_DECL(const HParser*, h_length_value, const HParser* length, const HParser* value); /** * This parser attaches a predicate function, which returns true or @@ -418,7 +447,7 @@ const HParser* h_length_value(const HParser* length, const HParser* value); * * Result token type: p's result type if pred succeeded, NULL otherwise. */ -const HParser* h_attr_bool(const HParser* p, HPredicate pred); +HAMMER_FN_DECL(const HParser*, h_attr_bool, const HParser* p, HPredicate pred); /** * The 'and' parser asserts that a conditional syntax is satisfied, @@ -435,7 +464,7 @@ const HParser* h_attr_bool(const HParser* p, HPredicate pred); * * Result token type: None. The HParseResult exists but its AST is NULL. */ -const HParser* h_and(const HParser* p); +HAMMER_FN_DECL(const HParser*, h_and, const HParser* p); /** * The 'not' parser asserts that a conditional syntax is *not* @@ -455,7 +484,7 @@ const HParser* h_and(const HParser* p); * * Result token type: None. The HParseResult exists but its AST is NULL. */ -const HParser* h_not(const HParser* p); +HAMMER_FN_DECL(const HParser*, h_not, const HParser* p); /** * Create a parser that just calls out to another, as yet unknown, @@ -466,35 +495,35 @@ const HParser* h_not(const HParser* p); * Result token type: the type of whatever parser is bound to it with * bind_indirect(). */ -HParser *h_indirect(); +HAMMER_FN_DECL_NOARG(HParser*, h_indirect); /** * Set the inner parser of an indirect. See comments on indirect for * details. */ -void h_bind_indirect(HParser* indirect, const HParser* inner); +HAMMER_FN_DECL(void, h_bind_indirect, HParser* indirect, const HParser* inner); /** * Free the memory allocated to an HParseResult when it is no longer needed. */ -void h_parse_result_free(HParseResult *result); +HAMMER_FN_DECL(void, h_parse_result_free, HParseResult *result); // Some debugging aids /** * Format token into a compact unambiguous form. Useful for parser test cases. * Caller is responsible for freeing the result. */ -char* h_write_result_unamb(const HParsedToken* tok); +HAMMER_FN_DECL(char*, h_write_result_unamb, const HParsedToken* tok); /** * Format token to the given output stream. Indent starting at * [indent] spaces, with [delta] spaces between levels. */ -void h_pprint(FILE* stream, const HParsedToken* tok, int indent, int delta); +HAMMER_FN_DECL(void, h_pprint, FILE* stream, const HParsedToken* tok, int indent, int delta); /** * TODO: Document me */ -HBitWriter *h_bit_writer_new(void); +HBitWriter *h_bit_writer_new(HAllocator* mm__); /** * TODO: Document me @@ -506,7 +535,7 @@ void h_bit_writer_put(HBitWriter* w, unsigned long long data, size_t nbits); * Must not free [w] until you're done with the result. * [len] is in bytes. */ -const uint8_t *h_bit_writer_get_buffer(HBitWriter* w, size_t *len); +const uint8_t* h_bit_writer_get_buffer(HBitWriter* w, size_t *len); /** * TODO: Document me diff --git a/src/internal.h b/src/internal.h index e8a3f9147a9c213f10acccc66ca5a927f66ef168..b7f56b6004c16cd7b52a4dd62198f016b55945ef 100644 --- a/src/internal.h +++ b/src/internal.h @@ -29,9 +29,28 @@ errx(1, "Assertion failed (programmer error): %s", message); \ } while(0) #endif + +#define HAMMER_FN_IMPL_NOARGS(rtype_t, name) \ + rtype_t name(void) { \ + return name##__m(system_allocator); \ + } \ + rtype_t name##__m(HAllocator* mm__) +// Functions with arguments are difficult to forward cleanly. Alas, we will need to forward them manually. + +#define h_new(type, count) ((type*)(mm__->alloc(mm__, sizeof(type)*(count)))) +#define h_free(addr) (mm__->free(mm__, (addr))) + #define false 0 #define true 1 +// This is going to be generally useful. +static inline void h_generic_free(HAllocator *allocator, void* ptr) { + allocator->free(allocator, ptr); +} + +HAllocator system_allocator; + + typedef struct HInputStream_ { // This should be considered to be a really big value type. const uint8_t *input; @@ -155,24 +174,6 @@ typedef struct HParserCacheValue_t { }; } HParserCacheValue; -typedef unsigned int *HCharset; - -static inline HCharset new_charset() { - HCharset cs = g_new0(unsigned int, 256 / sizeof(unsigned int)); - return cs; -} - -static inline int charset_isset(HCharset cs, uint8_t pos) { - return !!(cs[pos / sizeof(*cs)] & (1 << (pos % sizeof(*cs)))); -} - -static inline void charset_set(HCharset cs, uint8_t pos, int val) { - cs[pos / sizeof(*cs)] = - val - ? cs[pos / sizeof(*cs)] | (1 << (pos % sizeof(*cs))) - : cs[pos / sizeof(*cs)] & ~(1 << (pos % sizeof(*cs))); -} - // TODO(thequux): Set symbol visibility for these functions so that they aren't exported. long long h_read_bits(HInputStream* state, int count, char signed_p); @@ -198,7 +199,6 @@ int h_hashtable_present(HHashTable* ht, void* key); void h_hashtable_del(HHashTable* ht, void* key); void h_hashtable_free(HHashTable* ht); - #if 0 #include <malloc.h> #define h_arena_malloc(a, s) malloc(s) diff --git a/src/parsers/action.c b/src/parsers/action.c index 479a840cd8382db524762241ade0d2605ec2416f..0f1686f22245d91e9147ffa0054b512ecfc89fd4 100644 --- a/src/parsers/action.c +++ b/src/parsers/action.c @@ -23,10 +23,14 @@ static const HParserVtable action_vt = { .parse = parse_action, }; -const HParser* h_action(const HParser* p, const HAction a) { - HParser *res = g_new(HParser, 1); +const HParser* h_action(const HParser* p, const HAction a) { + return h_action__m(&system_allocator, p, a); +} + +const HParser* h_action__m(HAllocator* mm__, const HParser* p, const HAction a) { + HParser *res = h_new(HParser, 1); res->vtable = &action_vt; - HParseAction *env = g_new(HParseAction, 1); + HParseAction *env = h_new(HParseAction, 1); env->p = p; env->action = a; res->env = (void*)env; diff --git a/src/parsers/and.c b/src/parsers/and.c index fb117fb153a482794d9c4c04bdb0c5caab182af8..532cbbaf7c249f2fb06c4af47495325614550807 100644 --- a/src/parsers/and.c +++ b/src/parsers/and.c @@ -13,9 +13,13 @@ static const HParserVtable and_vt = { .parse = parse_and, }; + const HParser* h_and(const HParser* p) { + return h_and__m(&system_allocator, p); +} +const HParser* h_and__m(HAllocator* mm__, const HParser* p) { // zero-width postive lookahead - HParser *res = g_new(HParser, 1); + HParser *res = h_new(HParser, 1); res->env = (void*)p; res->vtable = &and_vt; return res; diff --git a/src/parsers/attr_bool.c b/src/parsers/attr_bool.c index bf9e6dcffa34ba8eb251b10bae0a60b8ae444e88..6fa36f844d94725369d1079e583723b2e0e90356 100644 --- a/src/parsers/attr_bool.c +++ b/src/parsers/attr_bool.c @@ -21,10 +21,14 @@ static const HParserVtable attr_bool_vt = { .parse = parse_attr_bool, }; -const HParser* h_attr_bool(const HParser* p, HPredicate pred) { - HParser *res = g_new(HParser, 1); + +const HParser* h_attr_bool(const HParser* p, HPredicate pred) { + return h_attr_bool__m(&system_allocator, p, pred); +} +const HParser* h_attr_bool__m(HAllocator* mm__, const HParser* p, HPredicate pred) { + HParser *res = h_new(HParser, 1); res->vtable = &attr_bool_vt; - HAttrBool *env = g_new(HAttrBool, 1); + HAttrBool *env = h_new(HAttrBool, 1); env->p = p; env->pred = pred; res->env = (void*)env; diff --git a/src/parsers/bits.c b/src/parsers/bits.c index 32b7a552b8bfb236d44ced877f2bd88cd4dd8401..196e33bba25d6eab243d18570ac2188acad060a0 100644 --- a/src/parsers/bits.c +++ b/src/parsers/bits.c @@ -20,18 +20,24 @@ static const HParserVtable bits_vt = { .parse = parse_bits, }; const HParser* h_bits(size_t len, bool sign) { - struct bits_env *env = g_new(struct bits_env, 1); + return h_bits__m(&system_allocator, len, sign); +} +const HParser* h_bits__m(HAllocator* mm__, size_t len, bool sign) { + struct bits_env *env = h_new(struct bits_env, 1); env->length = len; env->signedp = sign; - HParser *res = g_new(HParser, 1); + HParser *res = h_new(HParser, 1); res->vtable = &bits_vt; res->env = env; return res; } #define SIZED_BITS(name_pre, len, signedp) \ - const HParser* h_##name_pre##len () { \ - return h_bits(len, signedp); \ + const HParser* h_##name_pre##len () { \ + return h_bits__m(&system_allocator, len, signedp); \ + } \ + const HParser* h_##name_pre##len##__m(HAllocator* mm__) { \ + return h_bits__m(mm__, len, signedp); \ } SIZED_BITS(int, 8, true) SIZED_BITS(int, 16, true) diff --git a/src/parsers/butnot.c b/src/parsers/butnot.c index 5026d79d0df540530b6879db8947acb8bbb11e9d..422e0e1fd64309e57b46b9d17918282aea4a5193 100644 --- a/src/parsers/butnot.c +++ b/src/parsers/butnot.c @@ -39,10 +39,13 @@ static const HParserVtable butnot_vt = { .parse = parse_butnot, }; -const HParser* h_butnot(const HParser* p1, const HParser* p2) { - HTwoParsers *env = g_new(HTwoParsers, 1); +const HParser* h_butnot(const HParser* p1, const HParser* p2) { + return h_butnot__m(&system_allocator, p1, p2); +} +const HParser* h_butnot__m(HAllocator* mm__, const HParser* p1, const HParser* p2) { + HTwoParsers *env = h_new(HTwoParsers, 1); env->p1 = p1; env->p2 = p2; - HParser *ret = g_new(HParser, 1); + HParser *ret = h_new(HParser, 1); ret->vtable = &butnot_vt; ret->env = (void*)env; return ret; } diff --git a/src/parsers/ch.c b/src/parsers/ch.c index fbfa57edaabdc4b45edf2e19b0a4643fe4ac30ed..bb3073f0e80db93fe95332d6850df9be263f0387 100644 --- a/src/parsers/ch.c +++ b/src/parsers/ch.c @@ -15,8 +15,12 @@ static HParseResult* parse_ch(void* env, HParseState *state) { static const HParserVtable ch_vt = { .parse = parse_ch, }; -const HParser* h_ch(const uint8_t c) { - HParser *ret = g_new(HParser, 1); + +const HParser* h_ch(const uint8_t c) { + return h_ch__m(&system_allocator, c); +} +const HParser* h_ch__m(HAllocator* mm__, const uint8_t c) { + HParser *ret = h_new(HParser, 1); ret->vtable = &ch_vt; ret->env = GUINT_TO_POINTER(c); return (const HParser*)ret; diff --git a/src/parsers/charset.c b/src/parsers/charset.c index b9642fccd0aef2394f64de70fed56e911a918ad9..f11715ff1ac1670d229ab4c1906c92da59fffc20 100644 --- a/src/parsers/charset.c +++ b/src/parsers/charset.c @@ -1,5 +1,24 @@ +#include <string.h> #include "parser_internal.h" +typedef unsigned int *HCharset; + +static inline HCharset new_charset(HAllocator* mm__) { + HCharset cs = h_new(unsigned int, 256 / sizeof(unsigned int)); + memset(cs, 0, 256); + return cs; +} + +static inline int charset_isset(HCharset cs, uint8_t pos) { + return !!(cs[pos / sizeof(*cs)] & (1 << (pos % sizeof(*cs)))); +} + +static inline void charset_set(HCharset cs, uint8_t pos, int val) { + cs[pos / sizeof(*cs)] = + val + ? cs[pos / sizeof(*cs)] | (1 << (pos % sizeof(*cs))) + : cs[pos / sizeof(*cs)] & ~(1 << (pos % sizeof(*cs))); +} static HParseResult* parse_charset(void *env, HParseState *state) { uint8_t in = h_read_bits(&state->input_stream, 8, false); @@ -18,8 +37,11 @@ static const HParserVtable charset_vt = { }; const HParser* h_ch_range(const uint8_t lower, const uint8_t upper) { - HParser *ret = g_new(HParser, 1); - HCharset cs = new_charset(); + return h_ch_range__m(&system_allocator, lower, upper); +} +const HParser* h_ch_range__m(HAllocator* mm__, const uint8_t lower, const uint8_t upper) { + HParser *ret = h_new(HParser, 1); + HCharset cs = new_charset(mm__); for (int i = 0; i < 256; i++) charset_set(cs, i, (lower <= i) && (i <= upper)); ret->vtable = &charset_vt; @@ -28,9 +50,9 @@ const HParser* h_ch_range(const uint8_t lower, const uint8_t upper) { } -const HParser* h_in_or_not(const uint8_t *options, size_t count, int val) { - HParser *ret = g_new(HParser, 1); - HCharset cs = new_charset(); +static const HParser* h_in_or_not__m(HAllocator* mm__, const uint8_t *options, size_t count, int val) { + HParser *ret = h_new(HParser, 1); + HCharset cs = new_charset(mm__); for (size_t i = 0; i < 256; i++) charset_set(cs, i, 1-val); for (size_t i = 0; i < count; i++) @@ -42,10 +64,18 @@ const HParser* h_in_or_not(const uint8_t *options, size_t count, int val) { } const HParser* h_in(const uint8_t *options, size_t count) { - return h_in_or_not(options, count, 1); + return h_in_or_not__m(&system_allocator, options, count, 1); +} + +const HParser* h_in__m(HAllocator* mm__, const uint8_t *options, size_t count) { + return h_in_or_not__m(mm__, options, count, 1); } const HParser* h_not_in(const uint8_t *options, size_t count) { - return h_in_or_not(options, count, 0); + return h_in_or_not__m(&system_allocator, options, count, 0); +} + +const HParser* h_not_in__m(HAllocator* mm__, const uint8_t *options, size_t count) { + return h_in_or_not__m(mm__, options, count, 0); } diff --git a/src/parsers/choice.c b/src/parsers/choice.c index 082a2e10f343b1b97ddc09ef4958193b6e6adc65..2430352236b56bb63e4eca2d4dd3fd5430ea7cdf 100644 --- a/src/parsers/choice.c +++ b/src/parsers/choice.c @@ -25,20 +25,40 @@ static const HParserVtable choice_vt = { }; const HParser* h_choice(const HParser* p, ...) { + va_list ap; + va_start(ap, p); + const HParser* ret = h_choice__mv(&system_allocator, p, ap); + va_end(ap); + return ret; +} + +const HParser* h_choice__m(HAllocator* mm__, const HParser* p, ...) { + va_list ap; + va_start(ap, p); + const HParser* ret = h_choice__mv(mm__, p, ap); + va_end(ap); + return ret; +} + +const HParser* h_choice__v(const HParser* p, va_list ap) { + return h_choice__mv(&system_allocator, p, ap); +} + +const HParser* h_choice__mv(HAllocator* mm__, const HParser* p, va_list ap_) { va_list ap; size_t len = 0; - HSequence *s = g_new(HSequence, 1); + HSequence *s = h_new(HSequence, 1); const HParser *arg; - va_start(ap, p); + va_copy(ap, ap_); do { len++; arg = va_arg(ap, const HParser *); } while (arg); va_end(ap); - s->p_array = g_new(const HParser *, len); + s->p_array = h_new(const HParser *, len); - va_start(ap, p); + va_copy(ap, ap_); s->p_array[0] = p; for (size_t i = 1; i < len; i++) { s->p_array[i] = va_arg(ap, const HParser *); @@ -46,7 +66,7 @@ const HParser* h_choice(const HParser* p, ...) { va_end(ap); s->len = len; - HParser *ret = g_new(HParser, 1); + HParser *ret = h_new(HParser, 1); ret->vtable = &choice_vt; ret->env = (void*)s; return ret; } diff --git a/src/parsers/difference.c b/src/parsers/difference.c index 7f167a003fc3edd69d9ffdadaf97466a5a5bc97a..c6cc69cef86bfba3537b3c98c8a2777447c4f598 100644 --- a/src/parsers/difference.c +++ b/src/parsers/difference.c @@ -38,10 +38,13 @@ static HParserVtable difference_vt = { .parse = parse_difference, }; -const HParser* h_difference(const HParser* p1, const HParser* p2) { - HTwoParsers *env = g_new(HTwoParsers, 1); +const HParser* h_difference(const HParser* p1, const HParser* p2) { + return h_difference__m(&system_allocator, p1, p2); +} +const HParser* h_difference__m(HAllocator* mm__, const HParser* p1, const HParser* p2) { + HTwoParsers *env = h_new(HTwoParsers, 1); env->p1 = p1; env->p2 = p2; - HParser *ret = g_new(HParser, 1); + HParser *ret = h_new(HParser, 1); ret->vtable = &difference_vt; ret->env = (void*)env; return ret; } diff --git a/src/parsers/end.c b/src/parsers/end.c index 8e427bd50eb238b2ed5960693c5b72aa30a306c6..0f0d1c7d6c66375256f540f2a00b849ff82170fa 100644 --- a/src/parsers/end.c +++ b/src/parsers/end.c @@ -14,8 +14,13 @@ static const HParserVtable end_vt = { .parse = parse_end, }; -const HParser* h_end_p() { - HParser *ret = g_new(HParser, 1); - ret->vtable = &end_vt; ret->env = NULL; +const HParser* h_end_p() { + return h_end_p__m(&system_allocator); +} + +const HParser* h_end_p__m(HAllocator* mm__) { + HParser *ret = h_new(HParser, 1); + ret->vtable = &end_vt; + ret->env = NULL; return (const HParser*)ret; } diff --git a/src/parsers/epsilon.c b/src/parsers/epsilon.c index dc6d7a6db8b294dfab3b636ee72af5d7b4e7e646..ae959cd5455d55cb31446316001ade32904a63c4 100644 --- a/src/parsers/epsilon.c +++ b/src/parsers/epsilon.c @@ -20,3 +20,6 @@ static const HParser epsilon_p = { const HParser* h_epsilon_p() { return &epsilon_p; } +const HParser* h_epsilon_p__m(HAllocator* mm__) { + return &epsilon_p; +} diff --git a/src/parsers/ignore.c b/src/parsers/ignore.c index 5972548360cb3bbbc341484d5caa17dd6df89dfc..03cdc107102841e16449aa7483171a8f3e42b33f 100644 --- a/src/parsers/ignore.c +++ b/src/parsers/ignore.c @@ -15,7 +15,10 @@ static const HParserVtable ignore_vt = { }; const HParser* h_ignore(const HParser* p) { - HParser* ret = g_new(HParser, 1); + return h_ignore__m(&system_allocator, p); +} +const HParser* h_ignore__m(HAllocator* mm__, const HParser* p) { + HParser* ret = h_new(HParser, 1); ret->vtable = &ignore_vt; ret->env = (void*)p; return ret; diff --git a/src/parsers/ignoreseq.c b/src/parsers/ignoreseq.c index 8aac2c82c5f09658c9962860f7f625bff70523f2..228f63575febe5021b272c65a69b701089e7e081 100644 --- a/src/parsers/ignoreseq.c +++ b/src/parsers/ignoreseq.c @@ -35,38 +35,48 @@ static const HParserVtable ignoreseq_vt = { // API frontends // -static const HParser* h_leftright(const HParser* p, const HParser* q, size_t which) { - HIgnoreSeq *seq = g_new(HIgnoreSeq, 1); - seq->parsers = g_new(const HParser*, 2); +static const HParser* h_leftright__m(HAllocator* mm__, const HParser* p, const HParser* q, size_t which) { + HIgnoreSeq *seq = h_new(HIgnoreSeq, 1); + seq->parsers = h_new(const HParser*, 2); seq->parsers[0] = p; seq->parsers[1] = q; seq->count = 2; seq->which = which; - HParser *ret = g_new(HParser, 1); + HParser *ret = h_new(HParser, 1); ret->vtable = &ignoreseq_vt; ret->env = (void*)seq; return ret; } const HParser* h_left(const HParser* p, const HParser* q) { - return h_leftright(p, q, 0); + return h_leftright__m(&system_allocator, p, q, 0); +} +const HParser* h_left__m(HAllocator* mm__, const HParser* p, const HParser* q) { + return h_leftright__m(mm__, p, q, 0); } const HParser* h_right(const HParser* p, const HParser* q) { - return h_leftright(p, q, 1); + return h_leftright__m(&system_allocator, p, q, 1); +} +const HParser* h_right__m(HAllocator* mm__, const HParser* p, const HParser* q) { + return h_leftright__m(mm__, p, q, 1); } + const HParser* h_middle(const HParser* p, const HParser* x, const HParser* q) { - HIgnoreSeq *seq = g_new(HIgnoreSeq, 1); - seq->parsers = g_new(const HParser*, 3); + return h_middle__m(&system_allocator, p, x, q); +} +const HParser* h_middle__m(HAllocator* mm__, const HParser* p, const HParser* x, const HParser* q) { + HIgnoreSeq *seq = h_new(HIgnoreSeq, 1); + seq->parsers = h_new(const HParser*, 3); seq->parsers[0] = p; seq->parsers[1] = x; seq->parsers[2] = q; seq->count = 3; seq->which = 1; - HParser *ret = g_new(HParser, 1); + HParser *ret = h_new(HParser, 1); ret->vtable = &ignoreseq_vt; ret->env = (void*)seq; return ret; diff --git a/src/parsers/indirect.c b/src/parsers/indirect.c index 758116de640ef9a179b934051d7b6421ce4e33cf..96e2a65d4c32f6cb2ea8b3cb05e4e230ab91c4d4 100644 --- a/src/parsers/indirect.c +++ b/src/parsers/indirect.c @@ -13,7 +13,10 @@ void h_bind_indirect(HParser* indirect, const HParser* inner) { } HParser* h_indirect() { - HParser *res = g_new(HParser, 1); + return h_indirect__m(&system_allocator); +} +HParser* h_indirect__m(HAllocator* mm__) { + HParser *res = h_new(HParser, 1); res->vtable = &indirect_vt; res->env = NULL; return res; diff --git a/src/parsers/int_range.c b/src/parsers/int_range.c index 9fb1c7edbe5d69e23a5a07d8ba10942e89fc69da..2a1db63ca3c3c6bc103e8b941ed0e7119ba91d17 100644 --- a/src/parsers/int_range.c +++ b/src/parsers/int_range.c @@ -33,6 +33,9 @@ static const HParserVtable int_range_vt = { }; const HParser* h_int_range(const HParser *p, const int64_t lower, const int64_t upper) { + return h_int_range__m(&system_allocator, p, lower, upper); +} +const HParser* h_int_range__m(HAllocator* mm__, const HParser *p, const int64_t lower, const int64_t upper) { // p must be an integer parser, which means it's using parse_bits // TODO: re-add this check //assert_message(p->vtable == &bits_vt, "int_range requires an integer parser"); @@ -40,11 +43,11 @@ const HParser* h_int_range(const HParser *p, const int64_t lower, const int64_t // and regardless, the bounds need to fit in the parser in question // TODO: check this as well. - HRange *r_env = g_new(HRange, 1); + HRange *r_env = h_new(HRange, 1); r_env->p = p; r_env->lower = lower; r_env->upper = upper; - HParser *ret = g_new(HParser, 1); + HParser *ret = h_new(HParser, 1); ret->vtable = &int_range_vt; ret->env = (void*)r_env; return ret; diff --git a/src/parsers/many.c b/src/parsers/many.c index f18be26a0f9c0a0b82fa0586940bcc62fa8531de..6cb818bcbe8c6ea9be45ead32b76711eab32968b 100644 --- a/src/parsers/many.c +++ b/src/parsers/many.c @@ -49,10 +49,13 @@ static const HParserVtable many_vt = { }; const HParser* h_many(const HParser* p) { - HParser *res = g_new(HParser, 1); - HRepeat *env = g_new(HRepeat, 1); + return h_many__m(&system_allocator, p); +} +const HParser* h_many__m(HAllocator* mm__, const HParser* p) { + HParser *res = h_new(HParser, 1); + HRepeat *env = h_new(HRepeat, 1); env->p = p; - env->sep = h_epsilon_p(); + env->sep = h_epsilon_p__m(mm__); env->count = 0; env->min_p = true; res->vtable = &many_vt; @@ -61,10 +64,13 @@ const HParser* h_many(const HParser* p) { } const HParser* h_many1(const HParser* p) { - HParser *res = g_new(HParser, 1); - HRepeat *env = g_new(HRepeat, 1); + return h_many1__m(&system_allocator, p); +} +const HParser* h_many1__m(HAllocator* mm__, const HParser* p) { + HParser *res = h_new(HParser, 1); + HRepeat *env = h_new(HRepeat, 1); env->p = p; - env->sep = h_epsilon_p(); + env->sep = h_epsilon_p__m(mm__); env->count = 1; env->min_p = true; res->vtable = &many_vt; @@ -73,10 +79,13 @@ const HParser* h_many1(const HParser* p) { } const HParser* h_repeat_n(const HParser* p, const size_t n) { - HParser *res = g_new(HParser, 1); - HRepeat *env = g_new(HRepeat, 1); + return h_repeat_n__m(&system_allocator, p, n); +} +const HParser* h_repeat_n__m(HAllocator* mm__, const HParser* p, const size_t n) { + HParser *res = h_new(HParser, 1); + HRepeat *env = h_new(HRepeat, 1); env->p = p; - env->sep = h_epsilon_p(); + env->sep = h_epsilon_p__m(mm__); env->count = n; env->min_p = false; res->vtable = &many_vt; @@ -85,8 +94,11 @@ const HParser* h_repeat_n(const HParser* p, const size_t n) { } const HParser* h_sepBy(const HParser* p, const HParser* sep) { - HParser *res = g_new(HParser, 1); - HRepeat *env = g_new(HRepeat, 1); + return h_sepBy__m(&system_allocator, p, sep); +} +const HParser* h_sepBy__m(HAllocator* mm__, const HParser* p, const HParser* sep) { + HParser *res = h_new(HParser, 1); + HRepeat *env = h_new(HRepeat, 1); env->p = p; env->sep = sep; env->count = 0; @@ -97,8 +109,11 @@ const HParser* h_sepBy(const HParser* p, const HParser* sep) { } const HParser* h_sepBy1(const HParser* p, const HParser* sep) { - HParser *res = g_new(HParser, 1); - HRepeat *env = g_new(HRepeat, 1); + return h_sepBy1__m(&system_allocator, p, sep); +} +const HParser* h_sepBy1__m(HAllocator* mm__, const HParser* p, const HParser* sep) { + HParser *res = h_new(HParser, 1); + HRepeat *env = h_new(HRepeat, 1); env->p = p; env->sep = sep; env->count = 1; @@ -135,9 +150,12 @@ static const HParserVtable length_value_vt = { }; const HParser* h_length_value(const HParser* length, const HParser* value) { - HParser *res = g_new(HParser, 1); + return h_length_value__m(&system_allocator, length, value); +} +const HParser* h_length_value__m(HAllocator* mm__, const HParser* length, const HParser* value) { + HParser *res = h_new(HParser, 1); res->vtable = &length_value_vt; - HLenVal *env = g_new(HLenVal, 1); + HLenVal *env = h_new(HLenVal, 1); env->length = length; env->value = value; res->env = (void*)env; diff --git a/src/parsers/not.c b/src/parsers/not.c index 1c46b6dc394f186977d04eef0062b4fbaa5c1ce9..73cf1295fc695d082058798b5a3f88522d34d891 100644 --- a/src/parsers/not.c +++ b/src/parsers/not.c @@ -15,7 +15,10 @@ static const HParserVtable not_vt = { }; const HParser* h_not(const HParser* p) { - HParser *res = g_new(HParser, 1); + return h_not__m(&system_allocator, p); +} +const HParser* h_not__m(HAllocator* mm__, const HParser* p) { + HParser *res = h_new(HParser, 1); res->vtable = ¬_vt; res->env = (void*)p; return res; diff --git a/src/parsers/nothing.c b/src/parsers/nothing.c index 9f81c02841ad298a6d714206961dfcc8edde0ab5..120c8ef305498bc8d4fe15baa8935196f00b9caa 100644 --- a/src/parsers/nothing.c +++ b/src/parsers/nothing.c @@ -10,8 +10,11 @@ static const HParserVtable nothing_vt = { .parse = parse_nothing, }; -const HParser* h_nothing_p() { - HParser *ret = g_new(HParser, 1); +const HParser* h_nothing_p() { + return h_nothing_p__m(&system_allocator); +} +const HParser* h_nothing_p__m(HAllocator* mm__) { + HParser *ret = h_new(HParser, 1); ret->vtable = ¬hing_vt; ret->env = NULL; return (const HParser*)ret; } diff --git a/src/parsers/optional.c b/src/parsers/optional.c index c0845765e5206283a2b465d0f668695a5acf9fae..9625fa0f5cf2c40011e1317222f312006eb33b27 100644 --- a/src/parsers/optional.c +++ b/src/parsers/optional.c @@ -16,9 +16,12 @@ static const HParserVtable optional_vt = { }; const HParser* h_optional(const HParser* p) { + return h_optional__m(&system_allocator, p); +} +const HParser* h_optional__m(HAllocator* mm__, const HParser* p) { // TODO: re-add this //assert_message(p->vtable != &ignore_vt, "Thou shalt ignore an option, rather than the other way 'round."); - HParser *ret = g_new(HParser, 1); + HParser *ret = h_new(HParser, 1); ret->vtable = &optional_vt; ret->env = (void*)p; return ret; diff --git a/src/parsers/sequence.c b/src/parsers/sequence.c index 54196da103aa9ac288c8aad70ebda8c590d1bb6f..dece4f0eab99386c05bc266bb0d366dc7487f2b6 100644 --- a/src/parsers/sequence.c +++ b/src/parsers/sequence.c @@ -27,20 +27,40 @@ static const HParserVtable sequence_vt = { .parse = parse_sequence, }; -const HParser* h_sequence(const HParser *p, ...) { +const HParser* h_sequence(const HParser* p, ...) { + va_list ap; + va_start(ap, p); + const HParser* ret = h_sequence__mv(&system_allocator, p, ap); + va_end(ap); + return ret; +} + +const HParser* h_sequence__m(HAllocator* mm__, const HParser* p, ...) { + va_list ap; + va_start(ap, p); + const HParser* ret = h_sequence__mv(mm__, p, ap); + va_end(ap); + return ret; +} + +const HParser* h_sequence__v(const HParser* p, va_list ap) { + return h_sequence__mv(&system_allocator, p, ap); +} + +const HParser* h_sequence__mv(HAllocator* mm__, const HParser *p, va_list ap_) { va_list ap; size_t len = 0; const HParser *arg; - va_start(ap, p); + va_copy(ap, ap_); do { len++; arg = va_arg(ap, const HParser *); } while (arg); va_end(ap); - HSequence *s = g_new(HSequence, 1); - s->p_array = g_new(const HParser *, len); + HSequence *s = h_new(HSequence, 1); + s->p_array = h_new(const HParser *, len); - va_start(ap, p); + va_copy(ap, ap_); s->p_array[0] = p; for (size_t i = 1; i < len; i++) { s->p_array[i] = va_arg(ap, const HParser *); @@ -48,7 +68,7 @@ const HParser* h_sequence(const HParser *p, ...) { va_end(ap); s->len = len; - HParser *ret = g_new(HParser, 1); + HParser *ret = h_new(HParser, 1); ret->vtable = &sequence_vt; ret->env = (void*)s; return ret; } diff --git a/src/parsers/token.c b/src/parsers/token.c index b3be207c3a1bea8b81bba908b0fc31780ef5232b..e57c71d2ac61c207139e683945d72cf92087696d 100644 --- a/src/parsers/token.c +++ b/src/parsers/token.c @@ -24,10 +24,13 @@ const const HParserVtable token_vt = { .parse = parse_token, }; -const HParser* h_token(const uint8_t *str, const size_t len) { - HToken *t = g_new(HToken, 1); +const HParser* h_token(const uint8_t *str, const size_t len) { + return h_token__m(&system_allocator, str, len); +} +const HParser* h_token__m(HAllocator* mm__, const uint8_t *str, const size_t len) { + HToken *t = h_new(HToken, 1); t->str = (uint8_t*)str, t->len = len; - HParser *ret = g_new(HParser, 1); + HParser *ret = h_new(HParser, 1); ret->vtable = &token_vt; ret->env = t; return (const HParser*)ret; diff --git a/src/parsers/unimplemented.c b/src/parsers/unimplemented.c index 99d153b715b92ea4664e8475bcc4cc95cbc044b0..35ee391c228246698f13da7b68b4524f732d228e 100644 --- a/src/parsers/unimplemented.c +++ b/src/parsers/unimplemented.c @@ -24,3 +24,6 @@ static HParser unimplemented = { const HParser* h_unimplemented() { return &unimplemented; } +const HParser* h_unimplemented__m(HAllocator* mm__) { + return &unimplemented; +} diff --git a/src/parsers/whitespace.c b/src/parsers/whitespace.c index 4d2ec179f15bc368a4d02c79b5c21c695434ffe6..8e009a43df268bc73257a98d6b790dfc3b1ec928 100644 --- a/src/parsers/whitespace.c +++ b/src/parsers/whitespace.c @@ -19,7 +19,10 @@ static const HParserVtable whitespace_vt = { }; const HParser* h_whitespace(const HParser* p) { - HParser *ret = g_new(HParser, 1); + return h_whitespace__m(&system_allocator, p); +} +const HParser* h_whitespace__m(HAllocator* mm__, const HParser* p) { + HParser *ret = h_new(HParser, 1); ret->vtable = &whitespace_vt; ret->env = (void*)p; return ret; diff --git a/src/parsers/xor.c b/src/parsers/xor.c index 9ffd51ef12fe081bbde8d5d0b4f5d9f68e2ca7a7..a11ad4aeae80d8589569729fd3e429e6eeb0c5a6 100644 --- a/src/parsers/xor.c +++ b/src/parsers/xor.c @@ -35,10 +35,13 @@ static const HParserVtable xor_vt = { .parse = parse_xor, }; -const HParser* h_xor(const HParser* p1, const HParser* p2) { - HTwoParsers *env = g_new(HTwoParsers, 1); +const HParser* h_xor(const HParser* p1, const HParser* p2) { + return h_xor__m(&system_allocator, p1, p2); +} +const HParser* h_xor__m(HAllocator* mm__, const HParser* p1, const HParser* p2) { + HTwoParsers *env = h_new(HTwoParsers, 1); env->p1 = p1; env->p2 = p2; - HParser *ret = g_new(HParser, 1); + HParser *ret = h_new(HParser, 1); ret->vtable = &xor_vt; ret->env = (void*)env; return ret; } diff --git a/src/system_allocator.c b/src/system_allocator.c new file mode 100644 index 0000000000000000000000000000000000000000..26e2273606bda27e7311a32c49973924d4716502 --- /dev/null +++ b/src/system_allocator.c @@ -0,0 +1,20 @@ +#include <malloc.h> +#include "internal.h" + +static void* system_alloc(HAllocator *allocator, size_t size) { + return malloc(size); +} + +static void* system_realloc(HAllocator *allocator, void* ptr, size_t size) { + return realloc(ptr, size); +} + +static void system_free(HAllocator *allocator, void* ptr) { + free(ptr); +} + +HAllocator system_allocator = { + .alloc = system_alloc, + .realloc = system_realloc, + .free = system_free, +};