2018-01-05 04:18:05 +03:00
# ifndef STRACE_XSTRING_H
# define STRACE_XSTRING_H
# include <stdarg.h>
# include <stdio.h>
# include "error_prints.h"
# include "gcc_compat.h"
/**
* Print to static buffer and die on ( really unexpected ) errors and overflows .
* Shouldn ' t be used directly ; please refer to helper macros xsnprintf and
* xsprint instead .
*
* @ param str String buffer to print into .
* @ param size Size of the string buffer in bytes .
* @ param func Function name from which this function is called .
* @ param argstr Stringified arguments ( including format argument ) .
* @ param format Format string .
* @ param . . . Format arguments .
* @ return Number of characters printed , excluding terminating null byte
* ( the same as s ( n ) printf ) .
*/
static inline int ATTRIBUTE_FORMAT ( ( printf , 5 , 6 ) )
xsnprintf_ ( char * str , size_t size , const char * func , const char * argstr ,
const char * format , . . . )
{
int ret ;
va_list ap ;
va_start ( ap , format ) ;
ret = vsnprintf ( str , size , format , ap ) ;
va_end ( ap ) ;
if ( ret < 0 | | ( unsigned int ) ret > = size )
error_msg_and_die ( " %s: got unexpected return value %d for "
" snprintf(buf, %zu, %s) " ,
func , ret , size , argstr ) ;
return ret ;
}
/**
* snprintf that dies on ( really unexpected ) errors and overflows .
*
* @ param str_ String buffer to print into .
* @ param size_ Size of the string buffer in bytes .
* @ param fmt_ Format string .
* @ param . . . Format arguments .
*/
# define xsnprintf(str_, size_, fmt_, ...) \
xsnprintf_ ( ( str_ ) , ( size_ ) , __func__ , # fmt_ " , " # __VA_ARGS__ , \
( fmt_ ) , __VA_ARGS__ )
/**
* Print to a character array buffer and die on ( really unexpected ) errors and
* overflows . Buffer size is obtained with sizeof ( ) .
*
* @ param str_ Character array buffer to print into .
* @ param fmt_ Format string .
* @ param . . . Format arguments .
*/
# define xsprintf(str_, fmt_, ...) \
xsnprintf ( ( str_ ) , sizeof ( str_ ) + MUST_BE_ARRAY ( str_ ) , ( fmt_ ) , \
__VA_ARGS__ )
2018-01-08 23:00:39 +03:00
static inline size_t
get_pos_diff_ ( char * str , size_t size , char * pos , const char * func ,
const char * call )
{
if ( ( str + size ) < str )
error_msg_and_die ( " %s: string size overflow (%p+%zu) in %s " ,
func , str , size , call ) ;
if ( pos > ( str + size ) )
error_msg_and_die ( " %s: got position (%p) beyond string "
" (%p+%zu) in %s " ,
func , pos , str , size , call ) ;
if ( pos < str )
error_msg_and_die ( " %s: got position %p before string %p in %s " ,
func , pos , str , call ) ;
return pos - str ;
}
/**
* Helper function for constructing string in a character array by appending
2018-02-10 16:43:16 +03:00
* new formatted parts . Returns new position . Fails on error or buffer
* overflow , in line with the rest of x * functions . Obtains buffer size via
2018-01-08 23:00:39 +03:00
* sizeof ( str_ ) .
*
* @ param str_ Character array buffer to print into .
* @ param pos_ Current position .
* @ param fmt_ Format string .
* @ param . . . Format arguments .
* @ return New position .
*/
# define xappendstr(str_, pos_, fmt_, ...) \
( xsnprintf ( ( pos_ ) , sizeof ( str_ ) + MUST_BE_ARRAY ( str_ ) - \
get_pos_diff_ ( ( str_ ) , sizeof ( str_ ) , ( pos_ ) , __func__ , \
" xappendstr( " # str_ " , " # pos_ " , " # fmt_ " , " \
# __VA_ARGS__ ")"), \
( fmt_ ) , # # __VA_ARGS__ ) + ( pos_ ) )
2018-01-05 04:18:05 +03:00
# endif /* !STRACE_XSTRING_H */