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); } }
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 }
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; }
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; }
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); }
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; }
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; }
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); }
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 }
// 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; }
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; }