//! 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) #define CMP(x,cmp,y) ( (x) cmp (y) ? (x) : (y) ) #define CMPv(x,cmp,y) ({ let _x = (x); let _y = (y); CMP(_x, cmp, _y); }) #define MIN(x, y) CMP((x), <, (y)) #define MINv(x, y) CMPv((x), <, (y)) #define MAX(x, y) CMP((x), >, (y)) #define MAXv(x, y) CMPv((x), >, (y)) // Returns number of bytes written to `dest`. Otherwise same as `strncpy()`. static usize strncpy_n(char*pOUT dest, const char* restrict src, usize n) { usize i; for(i=0;i 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; #undef ADDSTR } #ifdef _DEBUG_USE_UNSAFE_DISPLAY_FMT_ARGS #define _display_get_fmt(...) _display_get_fmt0(__VA_ARGS__) #else #define _display_get_fmt(...) _display_get_fmt_n(__VA_ARGS__) #endif 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); // --- get format string from `flags` --- char fmt[200]; //TODO: Find the realistic max for this. usize fmtw = _display_get_fmt(flags, matched, sizeof(fmt)-1, fmt); assert(fmtw+1 < sizeof(fmt)); fmt[fmtw+1] = 0; // --- TRACE("Format string get: `%s' (%lu)", fmt, fmtw); 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)); } }