Example #1
0
File: sink.c Project: Chunjie/hilti
static void __cctor_state(__parser_state* state, hlt_execution_context* ctx)
{
    for ( ; state; state = state->next ) {
        GC_CCTOR(state->parser, hlt_BinPACHilti_Parser, ctx);
        GC_CCTOR_GENERIC(&state->pobj, state->parser->type_info, ctx);
        GC_CCTOR(state->data, hlt_bytes, ctx);
        GC_CCTOR(state->resume, hlt_exception, ctx);
    }
}
Example #2
0
File: sink.c Project: Chunjie/hilti
void _binpachilti_sink_connect_intern(binpac_sink* sink, const hlt_type_info* type, void** pobj, binpac_parser* parser, hlt_bytes* mtype, hlt_exception** excpt, hlt_execution_context* ctx)
{
    __parser_state* state = hlt_malloc(sizeof(__parser_state));
    state->parser = parser;
    GC_CCTOR(state->parser, hlt_BinPACHilti_Parser, ctx);
    state->pobj = *pobj;
    GC_CCTOR_GENERIC(&state->pobj, type, ctx);
    state->data = 0;
    state->resume = 0;
    state->disconnected = 0;
    state->next = sink->head;

    sink->head = state;

#ifdef DEBUG
    if ( mtype ) {
        hlt_string s = hlt_string_decode(mtype, Hilti_Charset_ASCII, excpt, ctx);
        char* r1 = hlt_string_to_native(s, excpt, ctx);
        char* r2 = hlt_string_to_native(parser->name, excpt, ctx);

        DBG_LOG("binpac-sinks", "connected parser %s [%p] to sink %p for MIME type %s", r2, *pobj, sink, r1);

        hlt_free(r1);
        hlt_free(r2);
    }
    else {
        char* p = hlt_string_to_native(parser->name, excpt, ctx);
        DBG_LOG("binpac-sinks", "connected parser %s [%p] to sink %p", p, *pobj, sink);
        hlt_free(p);
    }
#endif

}
Example #3
0
hlt_execution_context* __hlt_execution_context_new_ref(hlt_vthread_id vid, int8_t run_module_init)
{
    hlt_execution_context* ctx = (hlt_execution_context*)hlt_malloc(sizeof(hlt_execution_context) +
                                                                    __hlt_globals()->globals_size);

    ctx->vid = vid;
    ctx->nullbuffer = __hlt_memory_nullbuffer_new(); // init first
    ctx->excpt = 0;
    ctx->fiber = 0;
    ctx->fiber_pool = __hlt_fiber_pool_new();
    ctx->worker = 0;
    ctx->tcontext = 0;
    ctx->tcontext_type = 0;
    ctx->pstate = 0;
    ctx->blockable = 0;
    ctx->tmgr = hlt_timer_mgr_new(&ctx->excpt, ctx);
    GC_CCTOR(ctx->tmgr, hlt_timer_mgr, ctx);

    __hlt_globals_init(ctx);

    if ( run_module_init )
        __hlt_modules_init(ctx);

    if ( ctx->excpt )
        hlt_exception_print_uncaught_abort(ctx->excpt, ctx);

    return ctx;
}
Example #4
0
void __binpac_globals_init()
{
    assert(! _globals);

    hlt_exception* excpt = 0;
    hlt_execution_context* ctx = hlt_global_execution_context();

    _globals = &_our_globals;

    _globals->parsers = hlt_list_new(&hlt_type_info_hlt_BinPACHilti_Parser, 0, &excpt, ctx);
    GC_CCTOR(_globals->parsers, hlt_list, ctx);

    _globals->mime_types = hlt_map_new(&hlt_type_info_hlt_bytes, &hlt_type_info___mime_parser, 0, &excpt, ctx);
    GC_CCTOR(_globals->mime_types, hlt_map, ctx);

    _globals->debugging = 0;
}
Example #5
0
File: sink.c Project: Chunjie/hilti
void binpachilti_sink_add_filter(binpac_sink* sink, hlt_enum ftype, hlt_exception** excpt, hlt_execution_context* ctx)
{
    binpac_filter* old_filter = sink->filter;
    sink->filter = binpachilti_filter_add(sink->filter, ftype, excpt, ctx);
    GC_CCTOR(sink->filter, binpac_filter, ctx);
    GC_DTOR(old_filter, binpac_filter, ctx);

    DBG_LOG("binpac-sinks", "attached filter %s to sink %p", sink->filter->def->name, sink);
}
Example #6
0
int __spicy_global_state_init()
{
    if ( __globals->initialized )
        return 0;

    __globals->initialized = 1;

    hlt_exception* excpt = 0;
    hlt_execution_context* ctx = hlt_global_execution_context();

    __globals->parsers = hlt_list_new(&hlt_type_info_hlt_SpicyHilti_Parser, 0, &excpt, ctx);
    GC_CCTOR(__globals->parsers, hlt_list, ctx);

    __globals->mime_types =
        hlt_map_new(&hlt_type_info_hlt_bytes, &hlt_type_info___mime_parser, 0, &excpt, ctx);
    GC_CCTOR(__globals->mime_types, hlt_map, ctx);

    __globals->debugging = 0;

    return 1;
}
Example #7
0
binpac_filter* __binpachilti_filter_add(binpac_filter* head, binpac_filter* filter, hlt_exception** excpt, hlt_execution_context* ctx)
{
    if ( ! head )
        return filter;

    while ( head->next )
        head = head->next;

    head->next = filter;
    GC_CCTOR(filter, binpac_filter, ctx);

    return head;
}
Example #8
0
File: sink.c Project: Chunjie/hilti
static void __finish_parser(binpac_sink* sink, __parser_state* state, hlt_exception** excpt, hlt_execution_context* ctx)
{
    if ( state->data && state->resume ) {
        hlt_bytes_freeze(state->data, 1, excpt, ctx);

        // TODO: Not sure if we need this wrapping with fiber/excpt here
        // (neither in main write function).
        hlt_fiber* saved_fiber = ctx->fiber;
        ctx->fiber = 0;
        hlt_exception* sink_excpt = 0;

        // We may trigger a safepoint so make sure we refcount our locoal.
        GC_CCTOR(sink, binpac_sink, ctx);
        __cctor_state(state, ctx);

        (state->parser->resume_func_sink)(state->resume, &sink_excpt, ctx);

        GC_DTOR(sink, binpac_sink, ctx);
        __dtor_state(state, ctx);

        GC_CLEAR(state->resume, hlt_exception, ctx);
        __hlt_context_clear_exception(ctx);
        ctx->fiber = saved_fiber;

        // TODO: Not quite sure why the yield exception can occur here, but
        // we ignore it.
        //
        // Update: Actually I think I do: when two separate filters (like
        // first for a sink and then for the unit connected to it) filter the
        // same data, the frozen flags doesn't get propagated.
        //
        // We forbid that for now and hope it won't be used ...
        //
        // sink-unit-filter.pac2 tests for this but is currently disabled ...
        if ( sink_excpt && sink_excpt->type == &hlt_exception_yield ) {
            assert(false);
        }

        else if ( sink_excpt && sink_excpt->type == &binpac_exception_parserdisabled ) {
            // Disabled, nothing to do.
            DBG_LOG("binpac-sinks", "- final writing to sink %p disabled for parser %p", sink, state->pobj);
            GC_DTOR(sink_excpt, hlt_exception, ctx);
        }

        else
            *excpt = sink_excpt;
    }

    __unlink_state(sink, state, ctx);
}
Example #9
0
File: mime.c Project: Chunjie/hilti
static void __connect_one(binpac_sink* sink, hlt_bytes* mtype, hlt_bytes* mtype_full, int8_t try_mode, void* cookie, hlt_exception** excpt, hlt_execution_context* ctx)
{
    if ( ! __binpac_globals_get()->mime_types )
        return;

    __mime_parser** current = hlt_map_get_default(__binpac_globals_get()->mime_types, &hlt_type_info_hlt_bytes, &mtype, &hlt_type_info___mime_parser, 0, excpt, ctx);

    if ( ! current )
        return;

    __mime_parser* mparser = *current;
    for ( __mime_parser* mp = mparser; mp; mp = mp->next ) {
        assert(mp->parser->new_func);

        // The C stub for the ctor function may mess with our yield/resume
        // information. We need to restore that afterwards.
        hlt_fiber* saved_fiber = ctx->fiber;
        __hlt_thread_mgr_blockable* saved_blockable = ctx->blockable;

        // We may trigger a safepoint so make sure we refcount our locoal.
        GC_CCTOR(sink, binpac_sink, ctx);
        GC_CCTOR(mtype, hlt_bytes, ctx);
        GC_CCTOR(mtype_full, hlt_bytes, ctx);

        void* pobj = mp->parser->new_func(sink, mtype, try_mode, cookie, excpt, ctx);
        assert(pobj);

        GC_DTOR(sink, binpac_sink, ctx);
        GC_DTOR(mtype, hlt_bytes, ctx);
        GC_DTOR(mtype_full, hlt_bytes, ctx);

        ctx->fiber = saved_fiber;
        ctx->blockable = saved_blockable;

        _binpachilti_sink_connect_intern(sink, mp->parser->type_info, &pobj, mp->parser, mtype_full, excpt, ctx);
    }
}
Example #10
0
File: mime.c Project: Chunjie/hilti
static void __add_parser(hlt_bytes* mt, binpac_parser* parser, hlt_exception** excpt, hlt_execution_context* ctx)
{
    __mime_parser* mp = GC_NEW_REF(__mime_parser, ctx);
    GC_INIT(mp->parser, parser, hlt_BinPACHilti_Parser, ctx);
    mp->next = 0;

    // Deep-copy the pointers, the map needs that.

    __mime_parser** cmp = hlt_malloc(sizeof(__mime_parser*));
    hlt_bytes**     cmt = hlt_malloc(sizeof(hlt_bytes*));
    *cmt = mt;
    *cmp = mp;

    __mime_parser** current = hlt_map_get_default(__binpac_globals_get()->mime_types, &hlt_type_info_hlt_bytes, cmt, &hlt_type_info___mime_parser, 0, excpt, ctx);

    if ( current ) {
        mp->next = *current;
        GC_CCTOR(mp->next, __mime_parser, ctx);
    }

    hlt_map_insert(__binpac_globals_get()->mime_types, &hlt_type_info_hlt_bytes, cmt, &hlt_type_info___mime_parser, cmp, excpt, ctx);

    GC_DTOR(mp, __mime_parser, ctx);

    hlt_free(cmp);
    hlt_free(cmt);

#ifdef DEBUG
    hlt_string s = hlt_string_decode(mt, Hilti_Charset_ASCII, excpt, ctx);

    char* r1 = hlt_string_to_native(s, excpt, ctx);
    char* r2 = hlt_string_to_native(parser->name, excpt, ctx);

    DBG_LOG("binpac-sinks", "MIME type %s registered for parser %s", r1, r2);

    hlt_free(r1);
    hlt_free(r2);
#endif
}
Example #11
0
// patter not net ref'ed.
static void _compile_one(hlt_regexp* re, hlt_string pattern, int idx, int re_refed, hlt_exception** excpt, hlt_execution_context* ctx)
{
    // FIXME: For now, the pattern must contain only ASCII characters.
    hlt_bytes* p = hlt_string_encode(pattern, Hilti_Charset_ASCII, excpt, ctx);
    if ( hlt_check_exception(excpt) )
        return;

    hlt_bytes_size plen = hlt_bytes_len(p, excpt, ctx);
    int8_t tmp[plen];
    int8_t* praw = hlt_bytes_to_raw(tmp, plen, p, excpt, ctx);
    assert(praw);

    if ( jrx_regset_add(&re->regexp, (const char*)praw, plen) != 0 ) {
        hlt_set_exception(excpt, &hlt_exception_pattern_error, pattern, ctx);
        return;
    }

    if ( ! re_refed )
        GC_CCTOR(pattern, hlt_string, ctx);

    re->patterns[idx] = pattern;
}
Example #12
0
File: sink.c Project: Chunjie/hilti
static int8_t __deliver_chunk(binpac_sink* sink, hlt_bytes* data, uint64_t rseq, uint64_t rupper, void* user, hlt_exception** excpt, hlt_execution_context* ctx)
{
    if ( ! data ) {
        // A gap.
        DBG_LOG("binpac-sinks", "hit gap with sink %p at rseq %" PRIu64, sink, rseq);

        if ( sink->cur_rseq != rupper ) {
            __report_gap(sink, rseq, (rupper - rseq), user, excpt, ctx);
            sink->cur_rseq = rupper;

            if ( sink->auto_trim )
                // We trim just up to the gap here, excluding the gap itself. This
                // will prevent future data beyond the gap from being delivered until
                // we explicitly skip over it.
                __trim(sink, rseq, user, excpt, ctx);
        }

        return 0;
    }

    DBG_LOG("binpac-sinks", "starting to deliver to sink %p at rseq %" PRIu64, sink, rseq);

    // If the HILTI function that we'll call suspends, it will change the
    // yield/resume fields. We need to reset them when we leave this
    // function.

    hlt_fiber* saved_fiber = ctx->fiber;
    __hlt_thread_mgr_blockable* saved_blockable = ctx->blockable;

    ctx->fiber = 0;
    ctx->blockable = 0;

    binpac_dbg_deliver(sink, data, 0, excpt, ctx);

    if ( sink->filter ) {
        hlt_bytes* decoded = binpachilti_filter_decode(sink->filter, data, excpt, ctx); // &noref!

        if ( ! decoded )
            goto exit;

        data = decoded;
    }

    sink->size += hlt_bytes_len(data, excpt, ctx);

    if ( *excpt )
        goto exit;

    if ( ! sink->head ) {
        DBG_LOG("binpac-sinks", "done delivering to sink %p, no parser connected", sink);
        goto exit;
    }

    // data at +1 here.

    __parser_state* s = sink->head;

    // Now pass it onto parsers.
    while ( s ) {

        if ( s->disconnected )
            continue;

        hlt_exception* sink_excpt = 0;

        if ( ! s->data ) {
            // First chunk.
            DBG_LOG("binpac-sinks", "- start delivering to sink %p for parser %p", sink, s->pobj);
            s->data = hlt_bytes_copy(data, excpt, ctx);
            GC_CCTOR(s->data, hlt_bytes, ctx);

            if ( hlt_bytes_is_frozen(data, excpt, ctx) )
                hlt_bytes_freeze(s->data, 1, excpt, ctx);

            // We may trigger a safepoint so make sure we refcount our locoal.
            GC_CCTOR(sink, binpac_sink, ctx);
            GC_CCTOR(data, hlt_bytes, ctx);
            __cctor_state(s, ctx);

            (s->parser->parse_func_sink)(s->pobj, s->data, user, &sink_excpt, ctx);

            GC_DTOR(sink, binpac_sink, ctx);
            GC_DTOR(data, hlt_bytes, ctx);
            __dtor_state(s, ctx);
        }

        else {
            if ( ! s->resume ) {
                // Parsing has already finished for this parser. We ignore this here,
                // as otherwise we'd have to throw an exception and thus abort the
                // other parsers as well.
                s = s->next;
                continue;
            }

            DBG_LOG("binpac-sinks", "- resuming delivering to sink %p for parser %p", sink, s->pobj);

            // Subsequent chunk, resume.
            hlt_bytes_append(s->data, data, excpt, ctx);

            if ( hlt_bytes_is_frozen(data, excpt, ctx) )
                hlt_bytes_freeze(s->data, 1, excpt, ctx);

            // We may trigger a safepoint so make sure we refcount our locoal.
            GC_CCTOR(sink, binpac_sink, ctx);
            GC_CCTOR(data, hlt_bytes, ctx);
            __cctor_state(s, ctx);

            (s->parser->resume_func_sink)(s->resume, &sink_excpt, ctx);

            GC_DTOR(sink, binpac_sink, ctx);
            GC_DTOR(data, hlt_bytes, ctx);
            __dtor_state(s, ctx);

            GC_CLEAR(s->resume, hlt_exception, ctx);
        }

        // Clear any left-over exceptions.
        __hlt_context_clear_exception(ctx);

        if ( sink_excpt && sink_excpt->type == &hlt_exception_yield ) {
            // Suspended.
            DBG_LOG("binpac-sinks", "- delivering to sink %p suspended for parser %p", sink, s->pobj);
            GC_CCTOR(sink_excpt, hlt_exception, ctx);
            s->resume = sink_excpt;
            s = s->next;
            sink_excpt = 0;
        }

        else if ( sink_excpt && sink_excpt->type == &binpac_exception_parserdisabled ) {
            // Disabled
            DBG_LOG("binpac-sinks", "- writing to sink %p disabled for parser %p", sink, s->pobj);
            GC_DTOR(sink_excpt, hlt_exception, ctx);
            sink_excpt = 0;
            __parser_state* next = s->next;
            // This guy is finished, remove.
            __unlink_state(sink, s, ctx);
            s = next;
        }

        else {
            DBG_LOG("binpac-sinks", "- delivering to sink %p finished for parser %p", sink, s->pobj);
            __parser_state* next = s->next;
            // This guy is finished, remove.
            __unlink_state(sink, s, ctx);
            s = next;
        }

        if ( sink_excpt ) {
            // Error, abort.
            *excpt = sink_excpt;
            goto exit;
        }
    }

    // Savely delete disconnected parsers.

    int done = 0;

    while ( ! done ) {
        done = 1;
        for ( __parser_state* s = sink->head; s; s = s->next ) {
            if ( s->disconnected ) {
                // We ignore parse error triggered by the disconnect.
                hlt_exception* ignore_excpt = 0;
                __finish_parser(sink, s, &ignore_excpt, ctx);

                if ( ignore_excpt )
                    GC_DTOR(ignore_excpt, hlt_exception, ctx);

                done = 0;
                break;
            }
        }
    }

exit:
    ctx->fiber = saved_fiber;
    ctx->blockable = saved_blockable;

    sink->cur_rseq = rupper;
    sink->last_reassem_rseq = rupper;

    if ( sink->auto_trim )
        __trim(sink, rupper, user, excpt, ctx);

    DBG_LOG("binpac-sinks", "done delivering to sink %p", sink);

    return 1;
}