mcPrint, mcVPrint, mcSPrint, mcVSPrint — Safe and Portable Formatted Output Conversion
#include <memcom.h> int mcPrint(FILE* out, const char* fmt, ...); int mcVPrint(FILE* out, const char* fmt, va_list ap); int mcSPrint(char* buffer, mcSize bufsize, const char* fmt, ...); int mcVSPrint(char* buffer, mcSize bufsize, const char* fmt, va_list ap);
mcPrint
, mcVPrint
, mcSPrint
, and mcVSPrint
take a format string
and a variable number of arguments, either convert them into a
string and dump this string to a file stream
(mcPrint
and mcVPrint
), or
convert them directly in a user-supplied buffer
(mcSPrint
and
mcSVPrint
).
out
Stdio stream which is writable, such as
stdout
or stderr
. See
stdio
(3) for more information on how
to create and use streams.
buffer
Buffer provided by the caller. The size of the buffer
must be equal to bufsize
. The formatted
string will be copied into this buffer.
bufsize
The size of the buffer. This argument is important to
avoid buffer overflows, an error condition which happens
frequently when using the (deprecated)
s
printf
(3) function
call.
fmt
The format string. It is composed of zero or more
directives and ordinary characters (not '%'). The ordinary
characters are unchanged while the directives specify the
conversions to be applied to the arguments supplied
after the fmt
argument. The functions support all directives which are
supported by fprintf
in addition, the
following directives are supported:
O
The next argument is of type
mcOff
.
U
The next argument is of type
mcSize
.
These functions return the number of characters of the
converted string, not including the trailing 0 character used to
terminate the string. The mcSPrint
and
mcSVPrint
never write past the end of the
supplied buffer and always terminate the string with a trailing 0
character.
To test if the buffer is too small and the string had thus to be truncated, use:
char buf[10]; if (mcSPrint(buf, sizeof(buf), "This is a test") >= sizeof(buf)) { mcPrint(stderr, "buffer too small (%s)!\n", buf); ... }
The functions mcVPrint
and
mcVSPrint
can be called from
within functions that take a variable number of
arguments:
void my_log(const char* fmt, ...) { va_list ap; mcPrint(stderr, "log entry: "); va_start(ap, fmt); mcVPrint(stderr, fmt, ap); va_end(ap); }
To print the offset of a dataset:
mcSetAttributes att; if (mcDBinqSetAtt(handle, dsname, &att) != 1) mcPrint(stderr, "dataset %s does not exist!\n", dsname); else { mcPrint(stdout, "file offset for dataset %s: %O\n", dsname, att.faddr); mcPrint(stdout, "descriptor size for %s: %U\n", dsname, att.dsize); }