Content originally posted in LPCWare by OldManVimes on Sat Jan 11 10:17:28 MST 2014
Hi,
I'm using RedLib for my project and am loving it so far. It really keeps code size to a minimum. However, is there a way to provide feedback to the developers/maintainers?
I have one nagging issue that I've solved, but not in a very clean way. I want GCC to check the format string and arguments for printf() llike calls at compile-time.
Mismatches in the format string and arguments can lead to crashes (at least that is my experience on Linux with GLIBC). Unfortunately, Redlib does not offer support for this out of the box, so I made my own. See below for how this is done and why Redlib makes this slightly tricky. Note that it assumes you are using GCC, so additional #ifdef-s are needed to make it compiler type aware.
---
// The next commented block is from RedLib stdio.h
// It shows function re-mapping via macros that
// causes issues when combined with __attribute__ ((format(printf, 1, 2)))
#if 0
#ifdef CR_INTEGER_PRINTF
#define fprintf _fprintf
#define sprintf _sprintf
#define vfprintf _vfprintf
#define vsprintf _vsprintf
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#if CR_PRINTF_CHAR
#define printf _printf_char
#define puts puts_char
#else
#define printf _printf
#endif
#elif CR_PRINTF_CHAR
#define printf printf_char
#define puts puts_char
#endif
#endif
// RedLib turns printf into _printf in stdio.h via a macro if CR_INTEGER_PRINTF is defined (sigh).
// This makes __attribute__ ((format(printf... fail since it turns printf into _printf
// We want CR_INTEGER_PRINTF since it makes the code smaller because it leaves out floating point support.
// To 'fix' this simply undef the macro and re-define it after all __attribute((format(printf... specifiers.
#ifdef CR_INTEGER_PRINTF
#undef printf
#endif
// Another thing RedLib does not do is to define printf like functions in a way that makes
// the compiler check the format and arguments. A mismatch potentially causes crashes, so
// preventing these is important.
extern int printf(const char * restrict format, ...) __attribute__ ((format(printf, 1, 2)));
extern int scanf(const char * restrict format, ...) __attribute__ ((format(printf, 1, 2)));
extern int snprintf(char * restrict s, size_t n,
const char * restrict format, ...) __attribute__ ((format(printf, 3, 4)));
extern int sprintf(char * restrict s,
const char * restrict format, ...) __attribute__ ((format(printf, 2, 3)));
extern int sscanf(const char * restrict s,
const char * restrict format, ...) __attribute__ ((format(printf, 2, 3)));
// Redefine printf macro so it matches stdio.h
#ifdef CR_INTEGER_PRINTF
#if CR_PRINTF_CHAR
#define printf _printf_char
#else
#define printf _printf
#endif
#endif