From 7e5e0f00b67c9fd8da1e645e592b85bf42375d39 Mon Sep 17 00:00:00 2001 From: "Meredith L. Patterson" <mlp@thesmartpolitenerd.com> Date: Thu, 16 Jan 2014 18:58:36 +0100 Subject: [PATCH] C++ bindings now work! --- src/allocator.h | 7 ++ src/bindings/cpp/.gitignore | 2 + src/bindings/cpp/SConscript | 2 +- src/bindings/cpp/cpp_tests.cpp | 113 +++++++++++++------ src/bindings/cpp/hammer/hammer.hpp | 140 ++++++++++++++++-------- src/bindings/cpp/hammer/hammer_test.hpp | 12 +- src/internal.h | 9 +- 7 files changed, 197 insertions(+), 88 deletions(-) create mode 100644 src/bindings/cpp/.gitignore diff --git a/src/allocator.h b/src/allocator.h index a02d97cd..803d89fe 100644 --- a/src/allocator.h +++ b/src/allocator.h @@ -19,6 +19,10 @@ #define HAMMER_ALLOCATOR__H__ #include <sys/types.h> +#ifdef __cplusplus +extern "C" { +#endif + // TODO(thequux): Turn this into an "HAllocatorVtable", and add a wrapper that also takes an environment pointer. typedef struct HAllocator_ { void* (*alloc)(struct HAllocator_* allocator, size_t size); @@ -44,5 +48,8 @@ typedef struct { void h_allocator_stats(HArena *arena, HArenaStats *stats); +#ifdef __cplusplus +} +#endif #endif // #ifndef LIB_ALLOCATOR__H__ diff --git a/src/bindings/cpp/.gitignore b/src/bindings/cpp/.gitignore new file mode 100644 index 00000000..33dac38b --- /dev/null +++ b/src/bindings/cpp/.gitignore @@ -0,0 +1,2 @@ +hammer_test +test_detail.xml diff --git a/src/bindings/cpp/SConscript b/src/bindings/cpp/SConscript index 714d3001..bd9a90ea 100644 --- a/src/bindings/cpp/SConscript +++ b/src/bindings/cpp/SConscript @@ -2,7 +2,7 @@ Import("env libhammer_shared") cppenv = env.Clone() -cppenv.Append(CPPPATH=[".", "vendor/gtest-1.7.0/fused-src"]) +cppenv.Append(CPPPATH=[".", "vendor/gtest-1.7.0/fused-src", "../.."]) cppenv.MergeFlags("-Wno-missing-field-initializers -DGTEST_HAS_PTHREAD=0") diff --git a/src/bindings/cpp/cpp_tests.cpp b/src/bindings/cpp/cpp_tests.cpp index b6bfb439..d708208b 100644 --- a/src/bindings/cpp/cpp_tests.cpp +++ b/src/bindings/cpp/cpp_tests.cpp @@ -1,7 +1,10 @@ #include <gtest/gtest.h> #include <hammer/hammer.hpp> +#include <hammer/internal.h> #include <hammer/hammer_test.hpp> +#define a_new_(arena, typ, count) ((typ*)h_arena_malloc((arena), sizeof(typ)*(count))) + namespace { using namespace ::hammer; TEST(ParserTypes, Token) { @@ -24,23 +27,23 @@ namespace { TEST(ParserTypes, Int64) { Parser p = Int64(); - EXPECT_TRUE(ParsesTo(p, "\xff\xff\xff\xfe\x00\x00\x00\x00", "s-0x200000000")); - EXPECT_TRUE(ParseFails(p, "\xff\xff\xff\xfe\x00\x00\x00")); + EXPECT_TRUE(ParsesTo(p, std::string("\xff\xff\xff\xfe\x00\x00\x00\x00", 8), "s-0x200000000")); + EXPECT_TRUE(ParseFails(p, std::string("\xff\xff\xff\xfe\x00\x00\x00", 7))); } TEST(ParserTypes, Int32) { Parser p = Int32(); - EXPECT_TRUE(ParsesTo(p, "\xff\xfe\x00\x00", "s-0x20000")); - EXPECT_TRUE(ParseFails(p, "\xff\xfe\x00")); - EXPECT_TRUE(ParsesTo(p, "\x00\x02\x00\x00","s0x20000")); - EXPECT_TRUE(ParseFails(p, "\x00\x02\x00")); + EXPECT_TRUE(ParsesTo(p, std::string("\xff\xfe\x00\x00", 4), "s-0x20000")); + EXPECT_TRUE(ParseFails(p, std::string("\xff\xfe\x00", 3))); + EXPECT_TRUE(ParsesTo(p, std::string("\x00\x02\x00\x00",4) ,"s0x20000")); + EXPECT_TRUE(ParseFails(p, std::string("\x00\x02\x00", 3))); } TEST(ParserTypes, Int16) { Parser p = Int16(); - EXPECT_TRUE(ParsesTo(p, "\xfe\x00", "s-0x200")); + EXPECT_TRUE(ParsesTo(p, std::string("\xfe\x00", 2), "s-0x200")); EXPECT_TRUE(ParseFails(p, "\xfe")); - EXPECT_TRUE(ParsesTo(p, "\x02\x00", "s0x200")); + EXPECT_TRUE(ParsesTo(p, std::string("\x02\x00", 2), "s0x200")); EXPECT_TRUE(ParseFails(p, "\x01")); } @@ -52,19 +55,19 @@ namespace { TEST(ParserTypes, Uint64) { Parser p = Uint64(); - EXPECT_TRUE(ParsesTo(p, "\x00\x00\x00\x02\x00\x00\x00\x00", "u0x200000000")); - EXPECT_TRUE(ParseFails(p, "\x00\x00\x00\x02\x00\x00\x00")); + EXPECT_TRUE(ParsesTo(p, std::string("\x00\x00\x00\x02\x00\x00\x00\x00", 8), "u0x200000000")); + EXPECT_TRUE(ParseFails(p, std::string("\x00\x00\x00\x02\x00\x00\x00", 7))); } TEST(ParserTypes, Uint32) { Parser p = Uint32(); - EXPECT_TRUE(ParsesTo(p, "\x00\x02\x00\x00", "u0x20000")); - EXPECT_TRUE(ParseFails(p, "\x00\x02\x00")); + EXPECT_TRUE(ParsesTo(p, std::string("\x00\x02\x00\x00", 4), "u0x20000")); + EXPECT_TRUE(ParseFails(p, std::string("\x00\x02\x00", 3))); } TEST(ParserTypes, Uint16) { Parser p = Uint16(); - EXPECT_TRUE(ParsesTo(p, "\x02\x00", "u0x200")); + EXPECT_TRUE(ParsesTo(p, std::string("\x02\x00", 2), "u0x200")); EXPECT_TRUE(ParseFails(p, "\x02")); } @@ -82,7 +85,7 @@ namespace { TEST(ParserTypes, Whitespace) { Parser p = Whitespace(Ch('a')); - Parser q = Whitespace(EndP()); + Parser q = Whitespace(End()); EXPECT_TRUE(ParsesTo(p, "a", "u0x61")); EXPECT_TRUE(ParsesTo(p, " a", "u0x61")); EXPECT_TRUE(ParsesTo(p, " a", "u0x61")); @@ -121,13 +124,45 @@ namespace { EXPECT_TRUE(ParseFails(p, " ab")); } - // TODO action function - +#include <ctype.h> + + HParsedToken* upcase(const HParseResult *p, void* user_data) { + switch(p->ast->token_type) { + case TT_SEQUENCE: + { + HParsedToken *ret = a_new_(p->arena, HParsedToken, 1); + HCountedArray *seq = h_carray_new_sized(p->arena, p->ast->seq->used); + ret->token_type = TT_SEQUENCE; + for (size_t i=0; i<p->ast->seq->used; ++i) { + if (TT_UINT == ((HParsedToken*)p->ast->seq->elements[i])->token_type) { + HParsedToken *tmp = a_new_(p->arena, HParsedToken, 1); + tmp->token_type = TT_UINT; + tmp->uint = toupper(((HParsedToken*)p->ast->seq->elements[i])->uint); + h_carray_append(seq, tmp); + } else { + h_carray_append(seq, p->ast->seq->elements[i]); + } + } + ret->seq = seq; + return ret; + } + case TT_UINT: + { + HParsedToken *ret = a_new_(p->arena, HParsedToken, 1); + ret->token_type = TT_UINT; + ret->uint = toupper(p->ast->uint); + return ret; + } + default: + return (HParsedToken*)p->ast; + } + } + TEST(ParserTypes, Action) { Parser p = Action(Sequence(Choice(Ch('a'), Ch('A'), NULL), Choice(Ch('b'), Ch('B'), NULL), NULL), - toupper); // this won't compile + upcase); EXPECT_TRUE(ParsesTo(p, "ab", "(u0x41 u0x42)")); EXPECT_TRUE(ParsesTo(p, "AB", "(u0x41 u0x42)")); EXPECT_TRUE(ParseFails(p, "XX")); @@ -145,14 +180,14 @@ namespace { EXPECT_TRUE(ParseFails(p, "a")); } - TEST(ParserTypes, EndP) { - Parser p = Sequence(Ch('a'), EndP(), NULL); + TEST(ParserTypes, End) { + Parser p = Sequence(Ch('a'), End(), NULL); EXPECT_TRUE(ParsesTo(p, "a", "(u0x61)")); EXPECT_TRUE(ParseFails(p, "aa")); } - TEST(ParserTypes, NothingP) { - Parser p = NothingP(); + TEST(ParserTypes, Nothing) { + Parser p = Nothing(); EXPECT_TRUE(ParseFails(p, "a")); } @@ -207,7 +242,7 @@ namespace { TEST(ParserTypes, Many1) { Parser p = Many1(Choice(Ch('a'), Ch('b'), NULL)); - EXPECT_TRUE(ParseFails(p, "", "()")); + EXPECT_TRUE(ParseFails(p, "")); EXPECT_TRUE(ParsesTo(p, "a", "(u0x61)")); EXPECT_TRUE(ParsesTo(p, "b", "(u0x62)")); EXPECT_TRUE(ParsesTo(p, "aabbaba", "(u0x61 u0x61 u0x62 u0x62 u0x61 u0x62 u0x61)")); @@ -232,7 +267,7 @@ namespace { } TEST(ParserTypes, Ignore) { - Parser p = Sequence(Ch('a'), Ignore(Ch('b'), Ch('c'), NULL)); + Parser p = Sequence(Ch('a'), Ignore(Ch('b')), Ch('c'), NULL); EXPECT_TRUE(ParsesTo(p, "abc", "(u0x61 u0x63)")); EXPECT_TRUE(ParseFails(p, "ac")); } @@ -256,15 +291,23 @@ namespace { } TEST(ParserTypes, EpsilonP) { - Parser p = Sequence(Ch('a'), EpsilonP(), Ch('b'), NULL); - Parser q = Sequence(EpsilonP(), Ch('a'), NULL); - Parser r = Sequence(Ch('a'), EpsilonP(), NULL); + Parser p = Sequence(Ch('a'), Epsilon(), Ch('b'), NULL); + Parser q = Sequence(Epsilon(), Ch('a'), NULL); + Parser r = Sequence(Ch('a'), Epsilon(), NULL); EXPECT_TRUE(ParsesTo(p, "ab", "(u0x61 u0x62)")); EXPECT_TRUE(ParsesTo(q, "a", "(u0x61)")); EXPECT_TRUE(ParsesTo(r, "a", "(u0x61)")); } - bool validate_test_ab() { return false; } + bool validate_test_ab(HParseResult *p, void* user_data) { + if (TT_SEQUENCE != p->ast->token_type) + return false; + if (TT_UINT != p->ast->seq->elements[0]->token_type) + return false; + if (TT_UINT != p->ast->seq->elements[1]->token_type) + return false; + return (p->ast->seq->elements[0]->uint == p->ast->seq->elements[1]->uint); + } TEST(ParserTypes, AttrBool) { Parser p = AttrBool(Many1(Choice(Ch('a'), Ch('b'), NULL)), @@ -293,21 +336,21 @@ namespace { Ch('b'), NULL); EXPECT_TRUE(ParsesTo(p, "a+b", "(u0x61 u0x2b u0x62)")); EXPECT_TRUE(ParseFails(p, "a++b")); - EXPECT_TRUE(ParsesTo(p, "a+b", "(u0x61 (u0x2b) u0x62)")); - EXPECT_TRUE(ParsesTo(p, "a++b", "(u0x61 <2b.2b> u0x62)")); + EXPECT_TRUE(ParsesTo(q, "a+b", "(u0x61 (u0x2b) u0x62)")); + EXPECT_TRUE(ParsesTo(q, "a++b", "(u0x61 <2b.2b> u0x62)")); } - + /* TEST(ParserTypes, Leftrec) { - IndirectParser p = Indirect(); - p.bind(Choice(Sequence(p, Ch('a'), NULL), EpsilonP(), NULL)); + Indirect p = Indirect(); + p.bind(Choice(Sequence(p, Ch('a'), NULL), Epsilon(), NULL)); EXPECT_TRUE(ParsesTo(p, "a", "(u0x61)")); EXPECT_TRUE(ParsesTo(p, "aa", "((u0x61) u0x61)")); EXPECT_TRUE(ParsesTo(p, "aaa", "(((u0x61) u0x61) u0x61)")); } - + */ TEST(ParserTypes, Rightrec) { - IndirectParser p = Indirect(); - p.bind(Choice(Sequence(Ch('a'), p, NULL), EpsilonP(), NULL)); + Indirect p = Indirect(); + p.bind(Choice(Sequence(Ch('a'), p, NULL), Epsilon(), NULL)); EXPECT_TRUE(ParsesTo(p, "a", "(u0x61)")); EXPECT_TRUE(ParsesTo(p, "aa", "(u0x61 (u0x61))")); EXPECT_TRUE(ParsesTo(p, "aaa", "(u0x61 (u0x61 (u0x61)))")); diff --git a/src/bindings/cpp/hammer/hammer.hpp b/src/bindings/cpp/hammer/hammer.hpp index 07039e40..c33814e2 100644 --- a/src/bindings/cpp/hammer/hammer.hpp +++ b/src/bindings/cpp/hammer/hammer.hpp @@ -4,6 +4,9 @@ #include <hammer/hammer.h> #include <string> #include <stdint.h> +#include <cstdarg> +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused" namespace hammer { class ParseResult; @@ -12,9 +15,9 @@ namespace hammer { const HParser *parser; Parser(const HParser* inner) : parser(inner) {} - Parser(const Parser &other) : parser(other.parser) {} - ParseResult parse(std::string string); + //static Parser nil = Parser(NULL); + ParseResult parse(const std::string &string); }; class ParsedToken { @@ -39,7 +42,7 @@ namespace hammer { void* getUser() const {return token->user;} uint64_t getUint() const {return token->uint;} int64_t getSint() const {return token->sint;} - // TODO: Sequence GetSeq() const {return Sequence(token->seq);} + // TODO: Sequence getSeq() const {return Sequence(token->seq);} std::string getBytes() const {return std::string((char*)token->bytes.token, token->bytes.len); } @@ -78,7 +81,7 @@ namespace hammer { } }; - inline ParseResult Parser::parse(std::string string) { + inline ParseResult Parser::parse(const std::string &string) { return ParseResult(h_parse(parser, (uint8_t*)string.data(), string.length())); } @@ -96,66 +99,109 @@ namespace hammer { return Parser(h_ch_range(lower,upper)); } - static inline Parser int64() { return Parser(h_int64()); } - static inline Parser int32() { return Parser(h_int32()); } - static inline Parser int16() { return Parser(h_int16()); } - static inline Parser int8 () { return Parser(h_int8 ()); } + static inline Parser Int64() { return Parser(h_int64()); } + static inline Parser Int32() { return Parser(h_int32()); } + static inline Parser Int16() { return Parser(h_int16()); } + static inline Parser Int8 () { return Parser(h_int8 ()); } - static inline Parser uint64() { return Parser(h_uint64()); } - static inline Parser uint32() { return Parser(h_uint32()); } - static inline Parser uint16() { return Parser(h_uint16()); } - static inline Parser uint8 () { return Parser(h_uint8 ()); } + static inline Parser Uint64() { return Parser(h_uint64()); } + static inline Parser Uint32() { return Parser(h_uint32()); } + static inline Parser Uint16() { return Parser(h_uint16()); } + static inline Parser Uint8 () { return Parser(h_uint8 ()); } - static inline Parser int_range(Parser p, int64_t lower, int64_t upper) { + static inline Parser IntRange(Parser p, int64_t lower, int64_t upper) { return Parser(h_int_range(p.parser, lower, upper)); } - static inline Parser bits(size_t len, bool sign) { return Parser(h_bits(len, sign)); } - static inline Parser whitespace(Parser p) { return Parser(h_whitespace(p.parser)); } - static inline Parser left(Parser p, Parser q) { return Parser(h_left(p.parser, q.parser)); } - static inline Parser right(Parser p, Parser q) { return Parser(h_right(p.parser, q.parser)); } - static inline Parser middle(Parser p, Parser q, Parser r) { + static inline Parser Bits(size_t len, bool sign) { return Parser(h_bits(len, sign)); } + static inline Parser Whitespace(Parser p) { return Parser(h_whitespace(p.parser)); } + static inline Parser Left(Parser p, Parser q) { return Parser(h_left(p.parser, q.parser)); } + static inline Parser Right(Parser p, Parser q) { return Parser(h_right(p.parser, q.parser)); } + static inline Parser Middle(Parser p, Parser q, Parser r) { return Parser(h_middle(p.parser, q.parser, r.parser)); } - // TODO: Define Action - //Parser action(Parser p, Action a); + // User is responsible for ensuring that function remains allocated. + Parser Action(Parser p, HAction action, void* user_data) { + return Parser(h_action(p.parser, action, user_data)); + } - static inline Parser in(std::string charset); - static inline Parser in(const uint8_t *charset, size_t length); - static inline Parser in(std::set<uint8_t> charset); + Parser Action(Parser p, HAction action) { + return Parser(h_action(p.parser, action, NULL)); + } - static inline Parser not_in(std::string charset); - static inline Parser not_in(const uint8_t *charset, size_t length); - static inline Parser not_in(std::set<uint8_t> charset); + Parser AttrBool(Parser p, HPredicate pred, void* user_data) { + return Parser(h_attr_bool(p.parser, pred, user_data)); + } + + Parser AttrBool(Parser p, HPredicate pred) { + return Parser(h_attr_bool(p.parser, pred, NULL)); + } - static inline Parser end() { return Parser(h_end_p()); } - static inline Parser nothing() { return Parser(h_nothing_p()); } + static inline Parser In(const std::string &charset) { + return Parser(h_in((const uint8_t*)charset.data(), charset.length())); + } + static inline Parser In(const uint8_t *charset, size_t length) { + return Parser(h_in(charset, length)); + } + /* TODO + static inline Parser In(std::set<uint8_t> charset) { + + } + */ + + static inline Parser NotIn(const std::string &charset) { + return Parser(h_not_in((const uint8_t*)charset.data(), charset.length())); + } + static inline Parser NotIn(const uint8_t *charset, size_t length) { + return Parser(h_not_in(charset, length)); + } + /* TODO + static inline Parser NotIn(std::set<uint8_t> charset) { } + */ + static inline Parser End() { return Parser(h_end_p()); } + static inline Parser Nothing() { return Parser(h_nothing_p()); } // TODO: figure out varargs - //Parser sequence(); - // - //Parser choice(); - - static inline Parser butnot(Parser p1, Parser p2) { return Parser(h_butnot(p1.parser, p2.parser)); } - static inline Parser difference(Parser p1, Parser p2) { return Parser(h_difference(p1.parser, p2.parser)); } - static inline Parser xor_(Parser p1, Parser p2) { return Parser(h_xor(p1.parser, p2.parser)); } - static inline Parser many(Parser p) { return Parser(h_many(p.parser)); } - static inline Parser many1(Parser p) { return Parser(h_many1(p.parser)); } - static inline Parser repeat_n(Parser p, size_t n) { return Parser(h_repeat_n(p.parser, n)); } - static inline Parser optional(Parser p) { return Parser(h_optional(p.parser)); } - static inline Parser ignore(Parser p) { return Parser(h_ignore(p.parser)); } - static inline Parser sepBy(Parser p, Parser sep) { return Parser(h_sepBy(p.parser, sep.parser)); } - static inline Parser sepBy1(Parser p, Parser sep) { return Parser(h_sepBy1(p.parser, sep.parser)); } - static inline Parser epsilon() { return Parser(h_epsilon_p()); } - static inline Parser length_value(Parser length, Parser value) { return Parser(h_length_value(length.parser, value.parser)); } + static inline Parser Sequence(Parser p, ...) { + va_list ap; + va_start(ap, p); + // old-skool reinterpret_cast<HParser*>(p) + HParser* ret = h_sequence__v(*(HParser**)(void*)&p, + ap); + va_end(ap); + return Parser(ret); + } + + static inline Parser Choice(Parser p, ...) { + va_list ap; + va_start(ap, p); + // old-skool reinterpret_cast<HParser*>(p) + HParser* ret = h_choice__v(*(HParser**)(void*)&p, + ap); + va_end(ap); + return Parser(ret); + } + + static inline Parser ButNot(Parser p1, Parser p2) { return Parser(h_butnot(p1.parser, p2.parser)); } + static inline Parser Difference(Parser p1, Parser p2) { return Parser(h_difference(p1.parser, p2.parser)); } + static inline Parser Xor(Parser p1, Parser p2) { return Parser(h_xor(p1.parser, p2.parser)); } + static inline Parser Many(Parser p) { return Parser(h_many(p.parser)); } + static inline Parser Many1(Parser p) { return Parser(h_many1(p.parser)); } + static inline Parser RepeatN(Parser p, size_t n) { return Parser(h_repeat_n(p.parser, n)); } + static inline Parser Optional(Parser p) { return Parser(h_optional(p.parser)); } + static inline Parser Ignore(Parser p) { return Parser(h_ignore(p.parser)); } + static inline Parser SepBy(Parser p, Parser sep) { return Parser(h_sepBy(p.parser, sep.parser)); } + static inline Parser SepBy1(Parser p, Parser sep) { return Parser(h_sepBy1(p.parser, sep.parser)); } + static inline Parser Epsilon() { return Parser(h_epsilon_p()); } + static inline Parser LengthValue(Parser length, Parser value) { return Parser(h_length_value(length.parser, value.parser)); } // Was attr_bool in the old C bindings. // TODO: Figure out closure //Parser validate(Parser p, Predicate pred); - static inline Parser and_(Parser p) { return Parser(h_and(p.parser)); } - static inline Parser not_(Parser p) { return Parser(h_not(p.parser)); } + static inline Parser And(Parser p) { return Parser(h_and(p.parser)); } + static inline Parser Not(Parser p) { return Parser(h_not(p.parser)); } class Indirect : public Parser { public: @@ -169,4 +215,6 @@ namespace hammer { // return Parser(foo); //} } + +#pragma GCC diagnostic pop #endif diff --git a/src/bindings/cpp/hammer/hammer_test.hpp b/src/bindings/cpp/hammer/hammer_test.hpp index 41e4d9e1..77e6daa3 100644 --- a/src/bindings/cpp/hammer/hammer_test.hpp +++ b/src/bindings/cpp/hammer/hammer_test.hpp @@ -7,9 +7,8 @@ #define HAMMER_DECL_UNUSED __attribute__((unused)) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused" - +static ::testing::AssertionResult ParseFails (hammer::Parser parser, + const std::string &input) HAMMER_DECL_UNUSED; static ::testing::AssertionResult ParseFails (hammer::Parser parser, const std::string &input) { hammer::ParseResult result = parser.parse(input); @@ -20,6 +19,8 @@ static ::testing::AssertionResult ParseFails (hammer::Parser parser, } } +static ::testing::AssertionResult ParsesOK(hammer::Parser parser, + const std::string &input) HAMMER_DECL_UNUSED; static ::testing::AssertionResult ParsesOK(hammer::Parser parser, const std::string &input) { hammer::ParseResult result = parser.parse(input); @@ -30,6 +31,9 @@ static ::testing::AssertionResult ParsesOK(hammer::Parser parser, } } +static ::testing::AssertionResult ParsesTo(hammer::Parser parser, + const std::string &input, + const std::string &expected_result) HAMMER_DECL_UNUSED; static ::testing::AssertionResult ParsesTo(hammer::Parser parser, const std::string &input, const std::string &expected_result) { @@ -47,6 +51,4 @@ static ::testing::AssertionResult ParsesTo(hammer::Parser parser, } } -#pragma GCC diagnostic pop - #endif // defined(HAMMER_HAMMER_TEST__HPP) diff --git a/src/internal.h b/src/internal.h index 3c639d02..056a5afc 100644 --- a/src/internal.h +++ b/src/internal.h @@ -47,8 +47,13 @@ #define h_new(type, count) ((type*)(mm__->alloc(mm__, sizeof(type)*(count)))) #define h_free(addr) (mm__->free(mm__, (addr))) +#ifndef __cplusplus #define false 0 #define true 1 +#endif +#ifdef __cplusplus +extern "C" { +#endif // This is going to be generally useful. static inline void h_generic_free(HAllocator *allocator, void* ptr) { @@ -388,5 +393,7 @@ bool h_not_regular(HRVMProg*, void*); #include <stdlib.h> #define h_arena_malloc(a, s) malloc(s) #endif - +#ifdef __cplusplus +} // extern "C" +#endif #endif // #ifndef HAMMER_INTERNAL__H -- GitLab