//! Displaying match data #include #include #include #include #include #include #define FLAGSET(f, flag) (( (f) & (flag) ) == (flag)) #define DFLAGSET(f, flagname) FLAGSET(f, DISPF_SHOW_ ## flagname) //TODO: This probably won't work. Write wrappers for strncpy(), strncat() that return number of bytes written isntead of useless pointer that we already have. static usize _display_get_fmt(dispflags_t flags, bool matched, usize _len, char str[pOUT _len]) { register usize len = _len; static const char* fmts[] = { "match: ", "%lu: ", SLICE_FORMAT, " (len %lu)", "failure: ", (const char*)NULL }; #define ADDSTR(s) do { debug_assert((s)); strncat(str, (s), len); w = strlen((s)); w = w > len ? len : w; ifU(len<=w) { str[len-1] = 0; return w; } len -= w; str += w; fw+=w; } while(0) usize fw; usize w = strlen(strncpy(str, matched ? fmts[0] : DFLAGSET(flags, FAILURES) ? fmts[4] : "", len)); if(len<=w || w == 0) { str[len-1] = 0; return 0; } len -= w; str += w; fw = w; if(DFLAGSET(flags, NUMBER)) ADDSTR(fmts[1]); if(DFLAGSET(flags, SLICE)) ADDSTR(fmts[2]); if(DFLAGSET(flags, LENGTH)) ADDSTR(fmts[3]); ADDSTR("\n"); TRACE("Output string written: %lu, (rlen %lu)", fw, len); return fw; } static void _display_normal(FILE* output, dispin_t*pIN input, dispflags_t flags) { bool matched = input->matched; slice_t cslice = input->cslice; const void* base = input->base; usize i = input->index; #ifdef _DEBUG_MANCALC_OFFSETS struct { usize start, end; } pos = { .start = AS(cslice.ptr - base, usize), }; pos.end = pos.start + cslice.len; #else let pos = slice_sted((slice_t[]){ SLICE(AS(cslice.ptr - base, usize), cslice.len)}); #endif INFO("Mapped region slice for %lu, pre-transform (at %p): " SLICE_FORMAT ", len: %lu", i+1, base, SLICE_FORMAT_ARGS(&cslice), cslice.len); //Honour `flags` char fmt[200]; //TODO: Find the realistic max for this. fmt[_display_get_fmt(flags, matched, 100, fmt)] = 0; fprintf(output, fmt, i+1, pos.start, pos.end, pos.end-pos.start); } void display_result(FILE* output, dispin_t input, dispkind_t how, dispflags_t flags) { flags = flags ?: DISPLAY_FLAGS_DEFAULT; output = output ?: stdout; TRACE("Outputting as %d to %p with flags 0x%08lx", (int)how, output, (usize)flags); switch(how) { case DISPK_NORMAL: _display_normal(output, &input, flags); break; case DISPK_CSV: case DISPK_BINARY: case DISPK_INI: TODO("display kind %d is unimplemented", (int)how); default: COLD_EXPR(FATAL("unknown display kind: %d", (int)how)); } }