void hlt_execution_context_delete(hlt_execution_context* ctx) { hlt_exception* excpt = 0; // Do this first, it may still need the context. hlt_timer_mgr_expire(ctx->tmgr, 0, &excpt, ctx); GC_DTOR(ctx->tmgr, hlt_timer_mgr, ctx); __hlt_globals_dtor(ctx); GC_DTOR(ctx->excpt, hlt_exception, ctx); if ( ctx->fiber ) hlt_fiber_delete(ctx->fiber, ctx); if ( ctx->pstate ) __hlt_profiler_state_delete(ctx->pstate); if ( ctx->tcontext ) { GC_DTOR_GENERIC(&ctx->tcontext, ctx->tcontext_type, ctx); } __hlt_fiber_pool_delete(ctx->fiber_pool); if ( ctx->nullbuffer ) __hlt_memory_nullbuffer_delete(ctx->nullbuffer, ctx); hlt_free(ctx); }
static void __dtor_state(__parser_state* state, hlt_execution_context* ctx) { for ( ; state; state = state->next ) { GC_DTOR(state->parser, hlt_BinPACHilti_Parser, ctx); GC_DTOR_GENERIC(&state->pobj, state->parser->type_info, ctx); GC_DTOR(state->data, hlt_bytes, ctx); GC_DTOR(state->resume, hlt_exception, ctx); } }
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); }
int __spicy_global_state_done() { if ( ! __globals->initialized ) return 0; if ( __globals->finished ) return 0; GC_DTOR(__globals->parsers, hlt_list, hlt_global_execution_context()); GC_DTOR(__globals->mime_types, hlt_map, hlt_global_execution_context()); __globals->finished = 1; return 1; }
int main() { hlt_execution_context* ctx = 0; hlt_exception* excpt = 0; hlt_string s; hlt_init(); ctx = hlt_global_execution_context(); hlt_port a; a = hlt_port_from_asciiz("80/tcp", &excpt, ctx); s = hlt_object_to_string(&hlt_type_info_hlt_port, &a, 0, &excpt, ctx); hlt_string_print(stdout, s, 1, &excpt, ctx); assert(! excpt); a = hlt_port_from_asciiz("53/udp", &excpt, ctx); s = hlt_object_to_string(&hlt_type_info_hlt_port, &a, 0, &excpt, ctx); hlt_string_print(stdout, s, 1, &excpt, ctx); assert(! excpt); a = hlt_port_from_asciiz("can't parse", &excpt, ctx); assert(excpt); GC_DTOR(excpt, hlt_exception, ctx); return 0; }
void hlt_match_token_state_dtor(hlt_type_info* ti, hlt_match_token_state* t, hlt_execution_context* ctx) { if ( t->re ) // Will be set to zero once match_state_done is called. jrx_match_state_done(&t->ms); GC_DTOR(t->re, hlt_regexp, ctx); }
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); }
void hlt_regexp_dtor(hlt_type_info* ti, hlt_regexp* re, hlt_execution_context* ctx) { for ( int i = 0; i < re->num; i++ ) GC_DTOR(re->patterns[i], hlt_string, ctx); hlt_free(re->patterns); if ( re->num > 0 ) jrx_regfree(&re->regexp); }
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); } }
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 }
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; }
static void __delete_chunk(__chunk* c, hlt_exception** excpt, hlt_execution_context* ctx) { GC_DTOR(c->data, hlt_bytes, ctx); hlt_free(c); }
void __binpac_globals_done() { assert(_globals); GC_DTOR(_globals->parsers, hlt_list, hlt_global_execution_context()); GC_DTOR(_globals->mime_types, hlt_map, hlt_global_execution_context()); }