~siborgium/Regex

be44956a8ac5d5a55f16231829bc5128e7e135f0 — Sergey Smirnykh 2 years ago 6179ec7
Replace the majority of asserts with brand new CHECK_ macro & error codes
M Include/check.h => Include/check.h +2 -0
@@ 1,3 1,5 @@
#pragma once

#define CHECK(x) { int _impl_check_result; if ((_impl_check_result = (x))) { return _impl_check_result; } }

#define CHECK_(x, code) { if (!(x)) { return (code); } }

A Include/errors.h => Include/errors.h +10 -0
@@ 0,0 1,10 @@
#pragma once

enum {
    E_UNIMPLEMENTED = -1,
    E_UNEXPECTED    = -2,
    E_LOGIC         = -3,
    E_UNINITIALIZED = -4,
    E_ALREADY       = -5,
    E_NIL           = -6
};

M Src/ast.c => Src/ast.c +9 -10
@@ 9,6 9,7 @@
#include <set.h>

#include <check.h>
#include <errors.h>

enum ast_store ast_store_type(struct ast* a) {
    switch (a->type) {


@@ 32,7 33,7 @@ int ast_get_children(struct ast* a, struct ast** begin, struct ast** end) {
            *end   = a->store.child + 1;
            break;
        default:
            assert(0 && "ast_store_type: unhandled type");
            return E_UNEXPECTED;
    }
    return 0;
}


@@ 43,19 44,17 @@ int ast_new(struct ast* a, int tag) {
    a->max_repetitions = 1;
    a->next = NULL;
    switch (ast_store_type(a)) {
        case AST_STORE_NODE: a->store.child = NULL; return 0;
        case AST_STORE_CHAR: a->store.glyph = '\0'; return 0;
        case AST_STORE_NONE: break;
        case AST_STORE_NODE: a->store.child = NULL; break;
        case AST_STORE_CHAR: a->store.glyph = '\0'; break;
        case AST_STORE_SET:  a->store.set = NULL;   break;
        case AST_STORE_LIST:
            a->store.children.first = NULL;
            a->store.children.last  = NULL;
            return 0;
        case AST_STORE_SET:
            a->store.set = NULL;
            return 0;
        case AST_STORE_NONE: return 0;
        default: return E_UNEXPECTED;
    }
    assert(0 && "ast_new: unknown type");
    return -1;
    return 0;
}

int ast_setup_repetition(struct ast* a, char repetition) {


@@ 63,7 62,7 @@ int ast_setup_repetition(struct ast* a, char repetition) {
        case '?': a->min_repetitions = 0; a->max_repetitions = 1;        break;
        case '*': a->min_repetitions = 0; a->max_repetitions = UINT_MAX; break;
        case '+': a->min_repetitions = 1; a->max_repetitions = UINT_MAX; break;
        default: return -1;
        default: return E_UNEXPECTED;
    }
    return 0;
}

M Src/ast_normalize.c => Src/ast_normalize.c +4 -4
@@ 1,10 1,10 @@

#include <ast_normalize.h>

#include <assert.h>
#include <limits.h>
#include <string.h>
#include <check.h>
#include <errors.h>

static inline int ast_free(struct ast* a, struct mem_mgr* m) {
    (void)a;


@@ 22,7 22,7 @@ static void safe_sum(unsigned* a, unsigned b) {
}

static int merge_equivalent_entries(struct ast* a, struct mem_mgr* mgr) {
    assert(a->type == AST_TYPE_SEQ);
    CHECK_(a->type == AST_TYPE_SEQ, E_UNEXPECTED);

    struct ast* current = a->store.children.first;



@@ 79,7 79,7 @@ static int merge_equivalent_entries(struct ast* a, struct mem_mgr* mgr) {

static int remove_equivalent_branches(struct ast* a, struct mem_mgr* mgr) {
    // OR should be at least 1 elements long
    assert(a);
    CHECK_(a, E_NIL);
    if (!a->next) {
        return 0;
    }


@@ 132,7 132,7 @@ int ast_normalize(struct ast* a, struct mem_mgr* mgr) {
        }
        case AST_TYPE_SEQ:
        {
            assert(a->store.children.first && a->store.children.first->next);
            CHECK_(a->store.children.first && a->store.children.first->next, E_LOGIC);
            FOR_AST(a, a1, CHECK(ast_normalize(a1, mgr)));
            CHECK(merge_equivalent_entries(a, mgr));
            break;

M Src/dump_tree.c => Src/dump_tree.c +0 -1
@@ 1,5 1,4 @@

#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <dump_tree.h>

M Src/main.c => Src/main.c +0 -1
@@ 1,5 1,4 @@

#include <assert.h>
#include <locale.h>
#include <stdlib.h>
#include <stdio.h>

M Src/memory_manager.c => Src/memory_manager.c +5 -4
@@ 5,6 5,7 @@
#include <memory_manager.h>

#include <check.h>
#include <errors.h>

static inline void* ext_alloc(struct mem_mgr_config* cfg, size_t size) {
    return cfg->ext_alloc(size, cfg->data);


@@ 84,10 85,10 @@ static inline int block_owns_ptr(struct block* b, void* ptr) {

static int pool_free(struct pool* p, void* ptr) {
    struct block* b = p->list;
    assert(b && "ast_mem_mgr: mgr is not initialized");
    CHECK_(b, E_UNINITIALIZED);

    if (block_owns_ptr(b, ptr)) {
        assert(b->ref_count && "ast_mem_mgr: double-free");
        CHECK_(b->ref_count, E_ALREADY);
        --b->ref_count;
        if (!b->ref_count) {
            // no reason to push it into free blocks -- it's first & already clean


@@ 96,7 97,7 @@ static int pool_free(struct pool* p, void* ptr) {
        return 0;
    }

    assert(b->next && "ast_mem_mgr: tried to free ptr that was not alloc'd here");
    CHECK_(b->next, E_UNEXPECTED);
    struct block* bn = b->next;

    while (bn && (ptr < (void*)bn->begin || ptr >= (void*)bn->end)) {


@@ 107,7 108,7 @@ static int pool_free(struct pool* p, void* ptr) {
        return -1;
    }

    assert(bn->ref_count);
    CHECK_(bn->ref_count, E_LOGIC);

    --bn->ref_count;
    if (bn->ref_count == 0) {

M Src/transitions.c => Src/transitions.c +6 -2
@@ 5,6 5,7 @@
#include <transitions.h>

#include <check.h>
#include <errors.h>

static inline int is_leaf(struct ast* a) {
    switch (a->type) {


@@ 86,7 87,7 @@ static int to_graph_impl_or(struct transition_vec* ts, struct ast* a, struct con
        CHECK(to_graph_impl(ts, a1, &newctx))

        size_t new_len = transition_vec_len(ts);
        assert(old_len + leafs == new_len);
        CHECK_(old_len + leafs == new_len, E_LOGIC);

        // the last transition in a subexpression should jump to the end of OR
        // rather than passing control to the next subexpr


@@ 136,7 137,10 @@ static int to_graph_impl(struct transition_vec* ts, struct ast* a, struct contex
            CHECK(to_graph_impl(ts, a->store.child, ctx));

            t_prev = transition_vec_at(ts, transition_vec_len(ts) - 1);
            assert(t_prev->on_ok == SIZE_MAX || t_prev->on_ok == transition_vec_len(ts));
            CHECK_(
                (t_prev->on_ok == SIZE_MAX || t_prev->on_ok == transition_vec_len(ts)),
                E_LOGIC
            );
            on_ok_(t_prev, transition_vec_len(ts));

            struct transition* t2 = transition_vec_alloc(ts);