Adds lexer and parser.
This commit is contained in:
parent
afb32776ef
commit
9c751437c6
@ -9,3 +9,25 @@ set(CMAKE_C_STANDARD "11")
|
|||||||
add_compile_options(
|
add_compile_options(
|
||||||
-Wall -Wextra -pedantic -Werror -Wno-missing-field-initializers
|
-Wall -Wextra -pedantic -Werror -Wno-missing-field-initializers
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(BINER_GENRATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
|
||||||
|
|
||||||
|
find_package(BISON REQUIRED)
|
||||||
|
find_package(FLEX REQUIRED)
|
||||||
|
|
||||||
|
file(MAKE_DIRECTORY ${BINER_GENRATED_DIR})
|
||||||
|
bison_target(biner-parser biner.y ${BINER_GENRATED_DIR}/biner.y.c)
|
||||||
|
flex_target(biner-scanner biner.l ${BINER_GENRATED_DIR}/biner.l.c)
|
||||||
|
add_flex_bison_dependency(biner-scanner biner-parser)
|
||||||
|
|
||||||
|
add_executable(biner)
|
||||||
|
target_sources(biner
|
||||||
|
PRIVATE
|
||||||
|
main.c
|
||||||
|
tree.c
|
||||||
|
${BISON_biner-parser_OUTPUTS}
|
||||||
|
${FLEX_biner-scanner_OUTPUTS}
|
||||||
|
PUBLIC
|
||||||
|
zone.h
|
||||||
|
)
|
||||||
|
target_include_directories(biner PRIVATE . ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
8
TODO.TXT
Normal file
8
TODO.TXT
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
X parser
|
||||||
|
error handling (compiler message)
|
||||||
|
expression resolving
|
||||||
|
enum support
|
||||||
|
union support
|
||||||
|
constant support
|
||||||
|
transpiler for C
|
||||||
|
release 1.0.0
|
52
biner.l
Normal file
52
biner.l
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
%option noinput nounput noyywrap
|
||||||
|
|
||||||
|
%{
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "./tree.h"
|
||||||
|
#include "./zone.h"
|
||||||
|
|
||||||
|
#include "generated/biner.y.h"
|
||||||
|
|
||||||
|
#define ctx (biner_tree_parse_context_)
|
||||||
|
|
||||||
|
static inline uintptr_t strnew_(const char* str) {
|
||||||
|
return biner_zone_strnew(&ctx.zone, str);
|
||||||
|
}
|
||||||
|
static inline intmax_t parse_int_(int base) {
|
||||||
|
char* end = NULL;
|
||||||
|
const intmax_t v = strtoimax(yytext, &end, base);
|
||||||
|
|
||||||
|
/* TODO: replace asserts with throwing error */
|
||||||
|
assert((v != INTMAX_MIN && v != INTMAX_MAX) || errno != ERANGE);
|
||||||
|
assert(INT64_MIN <= v && v <= INT64_MAX);
|
||||||
|
assert(end != NULL && *end == 0);
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
D [0-9]
|
||||||
|
I [A-Za-z_]
|
||||||
|
H [0-9A-Fa-f]
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
"//".* ;
|
||||||
|
[/][*][^*]*[*]+([^*/][^*]*[*]+)*[/] ; /* TODO: detect unterminated comment */
|
||||||
|
|
||||||
|
"struct" return STRUCT;
|
||||||
|
|
||||||
|
{I}({I}|{D})* { yylval.ptr = strnew_(yytext); return IDENT; }
|
||||||
|
|
||||||
|
{D}+ { yylval.i = parse_int_(10); return INTEGER; }
|
||||||
|
0[xX]{H}+ { yylval.i = parse_int_(16); return INTEGER; }
|
||||||
|
|
||||||
|
[\+\-\*\/\.\(\)[\]\{\}\;] return yytext[0];
|
||||||
|
|
||||||
|
(.|\n) ;
|
||||||
|
|
||||||
|
%%
|
213
biner.y
Normal file
213
biner.y
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
%{
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "./tree.h"
|
||||||
|
#include "./zone.h"
|
||||||
|
|
||||||
|
#define ctx (biner_tree_parse_context_)
|
||||||
|
|
||||||
|
#define alloc_(T) (biner_zone_alloc(&ctx.zone, sizeof(T)))
|
||||||
|
#define ref(T, p) ((T*) (ctx.zone.ptr+p))
|
||||||
|
|
||||||
|
extern int yylex(void);
|
||||||
|
extern void yyerror(const char*);
|
||||||
|
|
||||||
|
static inline biner_zone_ptr(biner_tree_struct_member_t)
|
||||||
|
find_struct_member_(
|
||||||
|
biner_zone_ptr(biner_tree_struct_member_t) itr,
|
||||||
|
biner_zone_ptr(char) name) {
|
||||||
|
while (itr) {
|
||||||
|
const biner_tree_struct_member_t* m = ref(biner_tree_struct_member_t, itr);
|
||||||
|
if (strcmp(ref(char, m->name), ref(char, name)) == 0) {
|
||||||
|
return itr;
|
||||||
|
}
|
||||||
|
itr = m->prev;
|
||||||
|
}
|
||||||
|
yyerror("unknown member");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
%union {
|
||||||
|
int64_t i;
|
||||||
|
uintptr_t ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
%token STRUCT
|
||||||
|
%token <ptr> IDENT
|
||||||
|
%token <i> INTEGER;
|
||||||
|
|
||||||
|
%type <ptr> decl_list decl
|
||||||
|
%type <ptr> struct_body struct_member struct_member_type struct_member_reference
|
||||||
|
%type <ptr> expr add_expr mul_expr operand
|
||||||
|
|
||||||
|
%start decl_list
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
decl_list
|
||||||
|
: decl {
|
||||||
|
*ref(biner_tree_root_t, ctx.root) = (biner_tree_root_t) {
|
||||||
|
.decls = $1,
|
||||||
|
};
|
||||||
|
$$ = ctx.root;
|
||||||
|
}
|
||||||
|
| decl_list decl {
|
||||||
|
ref(biner_tree_decl_t, $2)->prev = ref(biner_tree_root_t, $1)->decls;
|
||||||
|
ref(biner_tree_root_t, $1)->decls = $2;
|
||||||
|
$$ = $1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
decl
|
||||||
|
: STRUCT IDENT '{' struct_body '}' ';' {
|
||||||
|
$$ = alloc_(biner_tree_decl_t);
|
||||||
|
*ref(biner_tree_decl_t, $$) = (biner_tree_decl_t) {
|
||||||
|
.name = $2,
|
||||||
|
.member = $4,
|
||||||
|
};
|
||||||
|
ctx.last_decl = $$;
|
||||||
|
ctx.last_member = 0;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
struct_body
|
||||||
|
: struct_member {
|
||||||
|
$$ = ctx.last_member = $1;
|
||||||
|
}
|
||||||
|
| struct_body struct_member {
|
||||||
|
ref(biner_tree_struct_member_t, $2)->prev = $1;
|
||||||
|
$$ = ctx.last_member = $2;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
struct_member
|
||||||
|
: struct_member_type IDENT ';' {
|
||||||
|
$$ = alloc_(biner_tree_struct_member_t);
|
||||||
|
*ref(biner_tree_struct_member_t, $$) =
|
||||||
|
(biner_tree_struct_member_t) {
|
||||||
|
.type = $1,
|
||||||
|
.name = $2,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
struct_member_type
|
||||||
|
: IDENT {
|
||||||
|
/* TODO: upgrade generic type to user-defined type. */
|
||||||
|
$$ = alloc_(biner_tree_struct_member_type_t);
|
||||||
|
*ref(biner_tree_struct_member_type_t, $$) =
|
||||||
|
(biner_tree_struct_member_type_t) {
|
||||||
|
.kind = BINER_TREE_STRUCT_MEMBER_TYPE_KIND_GENERIC,
|
||||||
|
.generic = $1,
|
||||||
|
.qualifier = BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_NONE,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
| IDENT '[' expr ']' {
|
||||||
|
$$ = alloc_(biner_tree_struct_member_type_t);
|
||||||
|
*ref(biner_tree_struct_member_type_t, $$) =
|
||||||
|
(biner_tree_struct_member_type_t) {
|
||||||
|
.kind = BINER_TREE_STRUCT_MEMBER_TYPE_KIND_GENERIC,
|
||||||
|
.generic = $1,
|
||||||
|
.qualifier = BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_DYNAMIC_ARRAY,
|
||||||
|
.expr = $3,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
expr
|
||||||
|
: add_expr { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
add_expr
|
||||||
|
: mul_expr
|
||||||
|
| add_expr '+' mul_expr {
|
||||||
|
$$ = alloc_(biner_tree_expr_t);
|
||||||
|
*ref(biner_tree_expr_t, $$) = (biner_tree_expr_t) {
|
||||||
|
.type = BINER_TREE_EXPR_TYPE_OPERATOR_ADD,
|
||||||
|
.operands = {$1, $3},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
| add_expr '-' mul_expr {
|
||||||
|
$$ = alloc_(biner_tree_expr_t);
|
||||||
|
*ref(biner_tree_expr_t, $$) = (biner_tree_expr_t) {
|
||||||
|
.type = BINER_TREE_EXPR_TYPE_OPERATOR_SUB,
|
||||||
|
.operands = {$1, $3},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
mul_expr
|
||||||
|
: operand
|
||||||
|
| mul_expr '*' operand {
|
||||||
|
$$ = alloc_(biner_tree_expr_t);
|
||||||
|
*ref(biner_tree_expr_t, $$) = (biner_tree_expr_t) {
|
||||||
|
.type = BINER_TREE_EXPR_TYPE_OPERATOR_MUL,
|
||||||
|
.operands = {$1, $3},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
| mul_expr '/' operand {
|
||||||
|
$$ = alloc_(biner_tree_expr_t);
|
||||||
|
*ref(biner_tree_expr_t, $$) = (biner_tree_expr_t) {
|
||||||
|
.type = BINER_TREE_EXPR_TYPE_OPERATOR_DIV,
|
||||||
|
.operands = {$1, $3},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
operand
|
||||||
|
: INTEGER {
|
||||||
|
$$ = alloc_(biner_tree_expr_t);
|
||||||
|
*ref(biner_tree_expr_t, $$) = (biner_tree_expr_t) {
|
||||||
|
.type = BINER_TREE_EXPR_TYPE_OPERAND_INTEGER,
|
||||||
|
.i = $1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
| struct_member_reference {
|
||||||
|
$$ = alloc_(biner_tree_expr_t);
|
||||||
|
*ref(biner_tree_expr_t, $$) = (biner_tree_expr_t) {
|
||||||
|
.type = BINER_TREE_EXPR_TYPE_OPERAND_REFER,
|
||||||
|
.r = $1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
| '(' expr ')' { $$ = $2; }
|
||||||
|
;
|
||||||
|
|
||||||
|
struct_member_reference
|
||||||
|
: IDENT {
|
||||||
|
$$ = alloc_(biner_tree_struct_member_reference_t);
|
||||||
|
*ref(biner_tree_struct_member_reference_t, $$) =
|
||||||
|
(biner_tree_struct_member_reference_t) {
|
||||||
|
.member = find_struct_member_(ctx.last_member, $1),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
| struct_member_reference '.' IDENT {
|
||||||
|
const biner_tree_struct_member_t* p =
|
||||||
|
ref(biner_tree_struct_member_t, $1);
|
||||||
|
|
||||||
|
const biner_tree_struct_member_type_t* t =
|
||||||
|
ref(biner_tree_struct_member_type_t, p->type);
|
||||||
|
if (t->kind != BINER_TREE_STRUCT_MEMBER_TYPE_KIND_USER_DEFINED) {
|
||||||
|
yyerror("not user-defined data");
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
const biner_tree_decl_t* d = ref(biner_tree_decl_t, t->decl);
|
||||||
|
if (d->type != BINER_TREE_DECL_TYPE_STRUCT) {
|
||||||
|
yyerror("not struct");
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
|
$$ = alloc_(biner_tree_struct_member_reference_t);
|
||||||
|
*ref(biner_tree_struct_member_reference_t, $$) =
|
||||||
|
(biner_tree_struct_member_reference_t) {
|
||||||
|
.member = find_struct_member_(d->member, $3),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
%%
|
27
main.c
Normal file
27
main.c
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "./tree.h"
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
const uint8_t* zone = biner_tree_parse(stdin);
|
||||||
|
if (zone == NULL) return EXIT_FAILURE;
|
||||||
|
|
||||||
|
const biner_tree_root_t* root = (const biner_tree_root_t*) zone;
|
||||||
|
|
||||||
|
const biner_tree_decl_t* decl =
|
||||||
|
(const biner_tree_decl_t*) (zone + root->decls);
|
||||||
|
while ((uintptr_t) decl != (uintptr_t) zone) {
|
||||||
|
printf("%s:\n", zone + decl->name);
|
||||||
|
|
||||||
|
const biner_tree_struct_member_t* member =
|
||||||
|
(const biner_tree_struct_member_t*) (zone + decl->member);
|
||||||
|
while ((uintptr_t) member != (uintptr_t) zone) {
|
||||||
|
printf(" %s\n", zone + member->name);
|
||||||
|
member = (const biner_tree_struct_member_t*) (zone + member->prev);
|
||||||
|
}
|
||||||
|
decl = (const biner_tree_decl_t*) (zone + decl->prev);
|
||||||
|
}
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
36
tree.c
Normal file
36
tree.c
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include "./tree.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "./zone.h"
|
||||||
|
|
||||||
|
#include "generated/biner.y.h"
|
||||||
|
|
||||||
|
biner_tree_parse_context_t biner_tree_parse_context_ = {0};
|
||||||
|
|
||||||
|
int yyerror(char* str) {
|
||||||
|
extern char* yytext;
|
||||||
|
fprintf(stderr, "error: %s: %s\n", str, yytext);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t* biner_tree_parse(FILE* fp) {
|
||||||
|
if (atomic_flag_test_and_set(&biner_tree_parse_context_.dirty)) {
|
||||||
|
fprintf(stderr, "parsing context is dirty now\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern FILE* yyin;
|
||||||
|
yyin = fp;
|
||||||
|
|
||||||
|
biner_tree_parse_context_.root = biner_zone_alloc(
|
||||||
|
&biner_tree_parse_context_.zone, sizeof(biner_tree_root_t));
|
||||||
|
assert(biner_tree_parse_context_.root == 0);
|
||||||
|
return yyparse()? NULL: biner_tree_parse_context_.zone.ptr;
|
||||||
|
}
|
107
tree.h
Normal file
107
tree.h
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdatomic.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "./zone.h"
|
||||||
|
|
||||||
|
typedef struct biner_tree_expr_t biner_tree_expr_t;
|
||||||
|
typedef struct biner_tree_struct_member_t biner_tree_struct_member_t;
|
||||||
|
typedef struct biner_tree_struct_member_reference_t biner_tree_struct_member_reference_t;
|
||||||
|
typedef struct biner_tree_struct_t biner_tree_struct_t;
|
||||||
|
typedef struct biner_tree_decl_t biner_tree_decl_t;
|
||||||
|
|
||||||
|
typedef enum biner_tree_expr_type_t {
|
||||||
|
BINER_TREE_EXPR_TYPE_OPERAND_INTEGER,
|
||||||
|
BINER_TREE_EXPR_TYPE_OPERAND_REFER,
|
||||||
|
BINER_TREE_EXPR_TYPE_OPERATOR_ADD,
|
||||||
|
BINER_TREE_EXPR_TYPE_OPERATOR_SUB,
|
||||||
|
BINER_TREE_EXPR_TYPE_OPERATOR_MUL,
|
||||||
|
BINER_TREE_EXPR_TYPE_OPERATOR_DIV,
|
||||||
|
} biner_tree_expr_type_t;
|
||||||
|
|
||||||
|
typedef struct biner_tree_expr_t {
|
||||||
|
biner_tree_expr_type_t type;
|
||||||
|
union {
|
||||||
|
int64_t i;
|
||||||
|
biner_zone_ptr(biner_tree_struct_member_reference_t) r;
|
||||||
|
struct {
|
||||||
|
biner_zone_ptr(biner_tree_expr_t) l;
|
||||||
|
biner_zone_ptr(biner_tree_expr_t) r;
|
||||||
|
} operands;
|
||||||
|
};
|
||||||
|
} biner_tree_expr_t;
|
||||||
|
|
||||||
|
typedef enum biner_tree_struct_member_type_kind_t {
|
||||||
|
BINER_TREE_STRUCT_MEMBER_TYPE_KIND_GENERIC,
|
||||||
|
BINER_TREE_STRUCT_MEMBER_TYPE_KIND_USER_DEFINED,
|
||||||
|
} biner_tree_struct_member_type_kind_t;
|
||||||
|
|
||||||
|
typedef enum biner_tree_struct_member_type_qualifier_t {
|
||||||
|
BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_NONE,
|
||||||
|
BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_STATIC_ARRAY,
|
||||||
|
BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_DYNAMIC_ARRAY,
|
||||||
|
} biner_tree_struct_member_type_qualifier_t;
|
||||||
|
|
||||||
|
typedef struct biner_tree_struct_member_type_t {
|
||||||
|
biner_tree_struct_member_type_kind_t kind;
|
||||||
|
union {
|
||||||
|
biner_zone_ptr(char) generic;
|
||||||
|
biner_zone_ptr(biner_tree_decl_t) decl;
|
||||||
|
};
|
||||||
|
|
||||||
|
biner_tree_struct_member_type_qualifier_t qualifier;
|
||||||
|
union {
|
||||||
|
size_t i;
|
||||||
|
biner_zone_ptr(biner_tree_expr_t) expr;
|
||||||
|
};
|
||||||
|
} biner_tree_struct_member_type_t;
|
||||||
|
|
||||||
|
typedef struct biner_tree_struct_member_t {
|
||||||
|
biner_zone_ptr(char) name;
|
||||||
|
biner_zone_ptr(biner_tree_struct_t) owner;
|
||||||
|
biner_zone_ptr(biner_tree_struct_member_type_t) type;
|
||||||
|
|
||||||
|
biner_zone_ptr(biner_tree_struct_member_t) prev;
|
||||||
|
} biner_tree_struct_member_t;
|
||||||
|
|
||||||
|
typedef struct biner_tree_struct_member_reference_t {
|
||||||
|
biner_zone_ptr(biner_tree_struct_member_t) member;
|
||||||
|
biner_zone_ptr(biner_tree_expr_t) index;
|
||||||
|
biner_zone_ptr(biner_tree_struct_member_reference_t) prev;
|
||||||
|
} biner_tree_struct_member_reference_t;
|
||||||
|
|
||||||
|
typedef enum biner_tree_decl_type_t {
|
||||||
|
BINER_TREE_DECL_TYPE_STRUCT,
|
||||||
|
} biner_tree_decl_type_t;
|
||||||
|
|
||||||
|
typedef struct biner_tree_decl_t {
|
||||||
|
biner_zone_ptr(char) name;
|
||||||
|
biner_tree_decl_type_t type;
|
||||||
|
union {
|
||||||
|
biner_zone_ptr(biner_tree_struct_member_t) member;
|
||||||
|
};
|
||||||
|
biner_zone_ptr(biner_tree_decl_t) prev;
|
||||||
|
} biner_tree_decl_t;
|
||||||
|
|
||||||
|
typedef struct biner_tree_root_t {
|
||||||
|
biner_zone_ptr(biner_tree_decl_t) decls;
|
||||||
|
} biner_tree_root_t;
|
||||||
|
|
||||||
|
typedef struct biner_tree_parse_context_t {
|
||||||
|
atomic_flag dirty;
|
||||||
|
biner_zone_t zone;
|
||||||
|
|
||||||
|
biner_zone_ptr(biner_tree_root_t) root;
|
||||||
|
biner_zone_ptr(biner_tree_decl_t) last_decl;
|
||||||
|
biner_zone_ptr(biner_tree_struct_member_t) last_member;
|
||||||
|
} biner_tree_parse_context_t;
|
||||||
|
|
||||||
|
extern biner_tree_parse_context_t biner_tree_parse_context_;
|
||||||
|
|
||||||
|
const uint8_t*
|
||||||
|
biner_tree_parse(
|
||||||
|
FILE* fp
|
||||||
|
);
|
52
zone.h
Normal file
52
zone.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define biner_zone_ptr(T) uintptr_t
|
||||||
|
|
||||||
|
typedef struct biner_zone_t {
|
||||||
|
uintptr_t tail;
|
||||||
|
size_t size;
|
||||||
|
uint8_t* ptr;
|
||||||
|
} biner_zone_t;
|
||||||
|
|
||||||
|
#define BINER_ZONE_RESERVE 1024
|
||||||
|
|
||||||
|
static inline uintptr_t biner_zone_alloc(biner_zone_t* z, size_t sz) {
|
||||||
|
assert(z != NULL);
|
||||||
|
assert(sz > 0);
|
||||||
|
|
||||||
|
if (z->ptr == NULL) {
|
||||||
|
z->ptr = calloc(1, sz);
|
||||||
|
if (z->ptr == NULL) {
|
||||||
|
fprintf(stderr, "malloc failure\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const uintptr_t oldtail = z->tail;
|
||||||
|
z->tail += sz;
|
||||||
|
if (z->tail > z->size) {
|
||||||
|
z->size = z->tail;
|
||||||
|
z->ptr = realloc(z->ptr, z->size);
|
||||||
|
}
|
||||||
|
memset(z->ptr+oldtail, 0, sz);
|
||||||
|
return oldtail;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uintptr_t biner_zone_strnew(biner_zone_t* z, const char* str) {
|
||||||
|
assert(z != NULL);
|
||||||
|
|
||||||
|
const uintptr_t ret = biner_zone_alloc(z, strlen(str)+1);
|
||||||
|
strcpy((char*) (z->ptr+ret), str);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void biner_zone_deinitialize(biner_zone_t* z) {
|
||||||
|
assert(z != NULL);
|
||||||
|
|
||||||
|
if (z->ptr != NULL) free(z->ptr);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user