@ -11,8 +11,101 @@
# 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 ] )
# 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 < n ; i + + )
if ( ! ( * dest + + = * src + + ) ) return i ;
dest [ i ] = 0 ;
return i ;
}
// Will not write past `dn` bytes of `dest`, will not read past `sn` bytes of `src`. Otherwise, same as `strncpy_n()`.
static usize s_strncpy_n ( usize sn , usize dn ; char dest [ static pOUT dn ] , usize dn , const char src [ static restrict sn ] , usize sn )
{
usize i ;
usize n = MIN ( sn , dn ) ;
for ( i = 0 ; i < n ; i + + )
if ( ! ( * dest + + = * src + + ) ) return i ;
if ( i < dn ) dest [ i ] = 0 ;
return i ;
}
// Will not write past `dn` bytes of `dest`, will not read past `sn` bytes of `src`. Otherwise, same as `strncat_n()`.
static inline usize s_strncat_n ( usize sn , usize dn ; char dest [ static pOUT dn ] , usize dn , const char src [ static restrict sn ] , usize sn )
{
usize dl = MINv ( strlen ( dest ) , dn ) ;
return s_strncpy_n ( dest + dl , dn - dl , src , sn ) ;
}
// Returns number of bytes written to (dest+strlen(dest)). Otherwise same as `strncat()`.
static inline usize strncat_n ( char * pOUT dest , const char * restrict src , usize n )
{
usize dl = strlen ( dest ) ;
return strncpy_n ( dest + dl , src , n ) ;
}
//TODO: This isn't working at all...
# ifdef _DEBUG_USE_UNSAFE_DISPLAY_FMT_ARGS
_dead
# endif
static usize _display_get_fmt_n ( dispflags_t flags , bool matched , usize _n , char str [ pOUT _n ] )
{
register usize n = _n , fw = 0 ;
const char * fmts [ ] = {
DFLAGSET ( flags , FAILURES )
? " failure: "
: " " ,
" match: " ,
" %lu: " ,
SLICE_FORMAT ,
" (len %lu) " ,
( const char * ) NULL ,
} ;
usize w = s_strncpy_n ( str , n , fmts [ ! ! matched ] , n ) ; // SAFETY: Will never read past `fmts[x]` nul-terminator, so setting n as both dest and src length here is safe.
//TODO: Fix this... It isn't working...
# define ADDSTR(s) do { \
debug_assert ( ( s ) ) ; \
w = MINv ( s_strncat_n ( str , n , ( s ) , n ) , n ) ; \
/* Remove written from `n` */ \
n - = w ; \
/* Check if we have written into the limit (if so, w will be equal to n above, since w is high-bounded to n by `MINv()` above. So if n is 0, we have hit the limit. */ \
ifU ( ! n ) { \
/*XXX: Should this be `str[w-1]?` If this assert fails then yes it should. */ \
debug_assert ( w < _n ) ; \
str [ w ] = 0 ; \
return fw + w ; \
} \
/* Increase `str` pointer by written */ \
str + = w ; \
/* Increase return value by written. */ \
fw + = w ; \
} while ( 0 )
if ( DFLAGSET ( flags , NUMBER ) ) ADDSTR ( fmts [ 2 ] ) ;
if ( DFLAGSET ( flags , SLICE ) ) ADDSTR ( fmts [ 3 ] ) ;
if ( DFLAGSET ( flags , LENGTH ) ) ADDSTR ( fmts [ 4 ] ) ;
ADDSTR ( " \n " ) ;
TRACE ( " Output string written: %lu, (rlen %lu) " , fw , n ) ;
# undef ADDSTR
return fw ;
}
//XXX: This works, but seems inherantly unsafe. Rewrite to use the above `strn*_n()` functions for better length tracking.
# ifndef _DEBUG_USE_UNSAFE_DISPLAY_FMT_ARGS
_dead deprecated_message ( " this is unsafe, use `_display_get_fmt_n` " )
# endif
static usize _display_get_fmt0 ( 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 } ;
@ -30,6 +123,12 @@ static usize _display_get_fmt(dispflags_t flags, bool matched, usize _len, char
# 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 ;
@ -49,9 +148,14 @@ static void _display_normal(FILE* output, dispin_t*pIN input, dispflags_t flags)
# 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`
// --- get format string from `flags` ---
char fmt [ 200 ] ; //TODO: Find the realistic max for this.
fmt [ _display_get_fmt ( flags , matched , 100 , fmt ) ] = 0 ;
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 ) ;
}