The messages of a library are mostly about what went wrong. mstring has four artefacts for that.

Exceptions and throw functions

$EXCEPTION INHERITED std::exception
$THROW ENABLE

$MESSAGE ConfigMissing
@ path std::string const &
"configuration file '{$path}' is missing"
try
{
  app::errors::ThrowConfigMissing( path );          // [[noreturn]]
}
catch ( app::errors::ConfigMissingException const &e )
{
  log( e.path( ) );                                 // the stored parameter
}
catch ( std::exception const &e )
{
  std::cerr << e.what( ) << '\n';                   // the message
}

The exception stores the parameters by value (a getter each), keeps the locale it was created with, and formats the message once in the constructor — what() does not allocate.

Fatal errors

$ERROR ENABLE
$ERROR EXIT std::exit( 2 )
$ERROR PREFIX Fatal

$MESSAGE Error
@ code int
|fatal error {$code}, giving up

FatalError( 7 ) prints to std::cerr and runs std::exit( 2 ). The EXIT statement can be anything — std::abort( ), throw Fatal{ }.

Syslog

$SYSLOG ENABLE FACILITY DAEMON LEVEL NOTICE
$MESSAGE Started
@ pid long
"started, pid {$pid}"

LogStarted( getpid( ) ) calls syslog( LOG_DAEMON | LOG_NOTICE, "%s", … ); pass another priority as the last argument.

One message, several artefacts

$MESSAGE Timeout : STRING THROW

The list after the colon picks this message's artefacts without touching the settings for the rest of the file.

The errors walkthrough is the complete example.