dump output, but `assoc` still doesn't work for read symbols, and we now have a segfault on exit.
186 lines
5.4 KiB
C
186 lines
5.4 KiB
C
/**
|
|
* debug.c
|
|
*
|
|
* Post Scarcity Software Environment: debugging messages.
|
|
*
|
|
* Print debugging output.
|
|
*
|
|
*
|
|
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
|
* Licensed under GPL version 2.0, or, at your option, any later version.
|
|
*/
|
|
|
|
#include <stdarg.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "debug.h"
|
|
|
|
#include "io/fopen.h"
|
|
#include "io/io.h"
|
|
#include "io/print.h"
|
|
|
|
#include "memory/dump.h"
|
|
|
|
int verbosity = 0;
|
|
|
|
|
|
/**
|
|
* @brief print this debug `message` to stderr, if `verbosity` matches `level`.
|
|
*
|
|
* `verbosity` is a set of flags, see debug_print.h; so you can
|
|
* turn debugging on for only one part of the system.
|
|
*
|
|
* NOTE THAT: contrary to behaviour in the 0.0.X prototypes, a line feed is
|
|
* always printed before a debug_print message. Hopefully this will result
|
|
* in clearer formatting.
|
|
*
|
|
* @param message The message to be printed, in *wide* (32 bit) characters.
|
|
* @param level a mask for `verbosity`. If a bitwise and of `verbosity` and
|
|
* `level` is non-zero, print this `message`, else don't.
|
|
* @param indent print `indent` spaces before the message.
|
|
*/
|
|
void debug_print( char32_t *message, int level, int indent ) {
|
|
#ifdef DEBUG
|
|
if ( level & verbosity ) {
|
|
fwide( stderr, 1 );
|
|
fputws( L"\n", stderr );
|
|
for ( int i = 0; i < indent; i++ ) {
|
|
fputws( L" ", stderr );
|
|
}
|
|
fputws( message, stderr );
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief print a 128 bit integer value to stderr, if `verbosity` matches `level`.
|
|
*
|
|
* `verbosity` is a set of flags, see debug_print.h; so you can
|
|
* turn debugging on for only one part of the system.
|
|
*
|
|
* stolen from https://stackoverflow.com/questions/11656241/how-to-print-uint128-t-number-using-gcc
|
|
*
|
|
* @param n the large integer to print.
|
|
* @param level a mask for `verbosity`. If a bitwise and of `verbosity` and
|
|
* `level` is non-zero, print this `message`, else don't.
|
|
*/
|
|
void debug_print_128bit( __int128_t n, int level ) {
|
|
#ifdef DEBUG
|
|
if ( level & verbosity ) {
|
|
if ( n == 0 ) {
|
|
fwprintf( stderr, L"0" );
|
|
} else {
|
|
char str[40] = { 0 }; // log10(1 << 128) + '\0'
|
|
char *s = str + sizeof( str ) - 1; // start at the end
|
|
while ( n != 0 ) {
|
|
if ( s == str )
|
|
return; // never happens
|
|
|
|
*--s = "0123456789"[n % 10]; // save last digit
|
|
n /= 10; // drop it
|
|
}
|
|
fwprintf( stderr, L"%s", s );
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief print a line feed to stderr, if `verbosity` matches `level`.
|
|
*
|
|
* `verbosity` is a set of flags, see debug_print.h; so you can
|
|
* turn debugging on for only one part of the system.
|
|
*
|
|
* @param level a mask for `verbosity`. If a bitwise and of `verbosity` and
|
|
* `level` is non-zero, print this `message`, else don't.
|
|
*/
|
|
void debug_println( int level ) {
|
|
#ifdef DEBUG
|
|
if ( level & verbosity ) {
|
|
fwide( stderr, 1 );
|
|
fputws( L"\n", stderr );
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief `wprintf` adapted for the debug logging system.
|
|
*
|
|
* Print to stderr only if `verbosity` matches `level`. All other arguments
|
|
* as for `wprintf`.
|
|
*
|
|
* @param level a mask for `verbosity`. If a bitwise and of `verbosity` and
|
|
* `level` is non-zero, print this `message`, else don't.
|
|
* @param indent print `indent` spaces before the message.
|
|
* @param format Format string in *wide characters*, but otherwise as used by
|
|
* `printf` and friends.
|
|
*
|
|
* Remaining arguments should match the slots in the format string.
|
|
*/
|
|
void debug_printf( int level, int indent, char32_t *format, ... ) {
|
|
#ifdef DEBUG
|
|
if ( level & verbosity ) {
|
|
fwide( stderr, 1 );
|
|
for ( int i = 0; i < indent; i++ ) {
|
|
fputws( L" ", stderr );
|
|
}
|
|
va_list( args );
|
|
va_start( args, format );
|
|
vfwprintf( stderr, format, args );
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief print the object indicated by this `pointer` to stderr, if `verbosity`
|
|
* matches `level`.
|
|
*
|
|
* `verbosity` is a set of flags, see debug_print.h; so you can
|
|
* turn debugging on for only one part of the system.
|
|
*/
|
|
void debug_print_object( struct pso_pointer pointer, int level, int indent ) {
|
|
#ifdef DEBUG
|
|
if ( level & verbosity ) {
|
|
URL_FILE *ustderr = file_to_url_file( stderr );
|
|
fwide( stderr, 1 );
|
|
in_write( pointer, ustderr, PRINT_VARIANT_PRINT, indent );
|
|
free( ustderr );
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* @brief Like `dump_object`, q.v., but protected by the verbosity mechanism.
|
|
*
|
|
* `verbosity` is a set of flags, see debug_print.h; so you can
|
|
* turn debugging on for only one part of the system.
|
|
*/
|
|
void debug_dump_object( struct pso_pointer pointer, int level, int indent ) {
|
|
#ifdef DEBUG
|
|
if ( level & verbosity ) {
|
|
URL_FILE *ustderr = file_to_url_file( stderr );
|
|
fwide( stderr, 1 );
|
|
dump_object( pointer );
|
|
free( ustderr );
|
|
}
|
|
#endif
|
|
}
|
|
|
|
///**
|
|
// * Standardise printing of binding trace messages.
|
|
// */
|
|
//void debug_print_binding( struct cons_pointer key, struct cons_pointer val,
|
|
// bool deep, int level, int indent ) {
|
|
//#ifdef DEBUG
|
|
// // char32_t * depth = (deep ? L"Deep" : L"Shallow");
|
|
//
|
|
// debug_print( ( deep ? L"Deep" : L"Shallow" ), level, indent );
|
|
// debug_print( L" binding `", level, indent );
|
|
// debug_print_object( key, level, indent );
|
|
// debug_print( L"` to `", level, indent );
|
|
// debug_print_object( val, level, indent );
|
|
// debug_print( L"`\n", level, indent );
|
|
//#endif
|
|
//}
|