Affix

 view release on metacpan or  search on metacpan

infix/src/emit/emit.c  view on Meta::CPAN

#define EMIT_DEFAULT_SECTION_CAPACITY 4096
#define EMIT_SECTION_GROWTH_FACTOR 2

void _emit_context_init(emit_context_t * ctx, emit_architecture_t arch, emit_format_t format) {
    ctx->arch = arch;
    ctx->format = format;
    ctx->state = EMIT_STATE_IDLE;
    ctx->sections = NULL;
    ctx->current_section = NULL;
    ctx->symbols = NULL;
    ctx->relocations = NULL;
    ctx->binary_spec = NULL;
    ctx->current_block_name = NULL;
    ctx->section_count = 0;
}

void _emit_context_free(emit_context_t * ctx) {
    if (!ctx)
        return;

    emit_section_t * sec = ctx->sections;
    while (sec) {
        emit_section_t * next = sec->next;
        infix_free(sec->name);
        infix_free(sec->data);
        infix_free(sec);
        sec = next;
    }

    emit_symbol_t * sym = ctx->symbols;
    while (sym) {
        emit_symbol_t * next = sym->next;
        infix_free(sym->name);
        infix_free(sym);
        sym = next;
    }

    emit_relocation_t * rel = ctx->relocations;
    while (rel) {
        emit_relocation_t * next = rel->next;
        infix_free(rel->symbol_name);
        infix_free(rel->section_name);
        infix_free(rel);
        rel = next;
    }

    infix_free(ctx->current_block_name);
}

static char * _emit_strdup(const char * s) {
    if (!s)
        return NULL;

    size_t len = strlen(s) + 1;
    char * copy = infix_malloc(len);
    if (copy)
        memcpy(copy, s, len);
    return copy;
}

static emit_section_t * _create_section(const char * name, emit_section_flags_t flags) {
    emit_section_t * section = infix_calloc(1, sizeof(emit_section_t));
    if (!section)
        return NULL;

    section->name = _emit_strdup(name);
    section->flags = flags;
    section->data = infix_malloc(EMIT_DEFAULT_SECTION_CAPACITY);
    if (!section->data) {
        infix_free(section->name);
        infix_free(section);
        return NULL;
    }
    section->capacity = EMIT_DEFAULT_SECTION_CAPACITY;
    section->size = 0;
    section->next = NULL;

    return section;
}

emit_section_t * _emit_lookup_section(emit_context_t * ctx, const char * name) {
    if (!ctx || !name)
        return NULL;

    for (emit_section_t * sec = ctx->sections; sec != NULL; sec = sec->next)
        if (strcmp(sec->name, name) == 0)
            return sec;
    return NULL;
}

emit_symbol_t * _emit_lookup_symbol(emit_context_t * ctx, const char * name) {
    if (!ctx || !name)
        return NULL;

    for (emit_symbol_t * sym = ctx->symbols; sym != NULL; sym = sym->next)
        if (strcmp(sym->name, name) == 0)
            return sym;
    return NULL;
}

INFIX_API infix_status emit_create(emit_context_t ** out_ctx, emit_architecture_t arch, emit_format_t format) {
    _infix_clear_error();
    if (!out_ctx) {
        _infix_set_error(INFIX_CATEGORY_PARSER, INFIX_CODE_INVALID_KEYWORD, 0);
        return INFIX_ERROR_INVALID_ARGUMENT;
    }

    emit_context_t * ctx = infix_calloc(1, sizeof(emit_context_t));
    if (!ctx)
        return INFIX_ERROR_ALLOCATION_FAILED;

    _emit_context_init(ctx, arch, format);

    *out_ctx = ctx;
    return INFIX_SUCCESS;
}

INFIX_API void emit_destroy(emit_context_t * ctx) {
    _emit_context_free(ctx);
    infix_free(ctx);
}

INFIX_API infix_status emit_add_section(emit_context_t * ctx, const char * name, emit_section_flags_t flags) {
    _infix_clear_error();
    if (!ctx || !name) {
        _infix_set_error(INFIX_CATEGORY_PARSER, INFIX_CODE_INVALID_KEYWORD, 0);
        return INFIX_ERROR_INVALID_ARGUMENT;
    }

    emit_section_t * existing = _emit_lookup_section(ctx, name);
    if (existing) {
        _infix_set_error(INFIX_CATEGORY_PARSER, INFIX_CODE_INVALID_KEYWORD, 0);
        return INFIX_ERROR_INVALID_ARGUMENT;
    }

    emit_section_t * section = _create_section(name, flags);
    if (!section)
        return INFIX_ERROR_ALLOCATION_FAILED;

    section->next = ctx->sections;
    ctx->sections = section;
    ctx->section_count++;

    return INFIX_SUCCESS;
}

INFIX_API infix_status emit_begin_section(emit_context_t * ctx, const char * section_name) {
    _infix_clear_error();
    if (!ctx || !section_name) {
        _infix_set_error(INFIX_CATEGORY_PARSER, INFIX_CODE_INVALID_KEYWORD, 0);
        return INFIX_ERROR_INVALID_ARGUMENT;
    }

    emit_section_t * section = _emit_lookup_section(ctx, section_name);
    if (!section) {
        _infix_set_error(INFIX_CATEGORY_PARSER, INFIX_CODE_INVALID_KEYWORD, 0);
        return INFIX_ERROR_INVALID_ARGUMENT;
    }

    ctx->current_section = section;
    ctx->state = EMIT_STATE_SECTION_ACTIVE;
    return INFIX_SUCCESS;
}

INFIX_API infix_status emit_define_symbol(emit_context_t * ctx,
                                          const char * name,
                                          emit_visibility_t visibility,
                                          bool is_function) {
    _infix_clear_error();
    if (!ctx || !name) {
        _infix_set_error(INFIX_CATEGORY_PARSER, INFIX_CODE_INVALID_KEYWORD, 0);
        return INFIX_ERROR_INVALID_ARGUMENT;
    }

    (void)visibility;

    emit_symbol_t * sym = _emit_lookup_symbol(ctx, name);
    if (!sym) {
        sym = infix_calloc(1, sizeof(emit_symbol_t));
        if (!sym)
            return INFIX_ERROR_ALLOCATION_FAILED;

        sym->name = _emit_strdup(name);
        sym->next = ctx->symbols;
        ctx->symbols = sym;
    }

    sym->is_defined = true;
    sym->is_function = is_function;
    sym->section = ctx->current_section;
    sym->value = ctx->current_section ? ctx->current_section->size : 0;

    return INFIX_SUCCESS;
}

INFIX_API infix_status emit_emit_label(emit_context_t * ctx, const char * name) {



( run in 1.920 second using v1.01-cache-2.11-cpan-a49fcb8fa48 )