You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
naka/src/display.c

75 lines
2.5 KiB

//! Displaying match data
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <macros.h>
#include <comp.h>
#include <display.h>
#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));
}
}