FMT(3)

NAME
fmt_print, fmt_eprint, fmt_fprint, fmt_sfmt, fmt_vsfmt, fmt_string, fmt_vstring, fmt_start, fmt_starts, fmt_build, fmt_finalize, fmt_register - Replacement for *printf with extension semantics.

SYNOPSIS
#include <format/fmt.h>

void fmt_print (const char * format, ...);

void fmt_eprint (const char * format, ...);

void fmt_fprint (FILE * fp, const char * format, ...);

int fmt_sfmt (char * buf, int size, const char * format, ...);

int fmt_vsfmt (char * buf, int size, const char * format, va_list ap);

char * fmt_string ( const char * format, ...);

char * fmt_vstring ( const char * format, va_list ap);

stringvec_t * fmt_start (size_t len);

stringvec_t * fmt_starts (stringvec_t * vec, size_t len);

void fmt_build (stringvec_t vec, int len, char * fmt, ... );

char * fmt_finalize (stringvec_t vec, size_t * len);

fmt_handler_info_t fmt_register (int code, fmt_t cvt); .SH "DESCRIPTION"

The fmt library provides an extensible replacement to *printf(). Fmt is portable (it will behave the same way on every platform it is compiled on) and provides extensions such as quadword formatting (%Lx). Most importantly, fmt allows callbacks to be registered for format specifiers, for instance mapping IP address formatting to %i. For the most part, the fmt interface is so similar to that of *printf that fmt can be swapped in with a series of #defines.

  PRINTF EQUIVALENCES

•   fmt_print is printf

•   fmt_eprint is fprintf(stderr, ...)

•   fmt_fprint is fprintf

•   fmt_sfmt is snprintf

•   fmt_vsfmt is vsnprintf

•   fmt_string is asprintf

•   fmt_vstring is vasprintf

  INCREMENTAL STRING CONSTRUCTION

A string can be built up from multiple calls to snprintf by observing the return values of the snprintf calls, and keeping an incrementing pointer into a buffer. This has two obvious problems: first, it is tedious to write and maintain this code, and second, the string must be marshalled into a fixed size buffer.

The fmt_build function allows strings to be built incrementally without regard for bookkeeping details. fmt_build maintains a dynamic array (with vector-like resizing) behind the scenes; repeated calls to fmt_build add more text to the end of this array.

fmt_build operates on stringvec_t objects. These are opaque types; obtain them from fmt_start (to allocate one from malloc) or fmt_starts (to allocate one on the stack). When the string is completely built, a call to fmt_finalize returns the string. Both the string, and the stringvec_t (if it was obtained from fmt_start) must be free()'d.

  ADDING FORMAT EXTENSIONS

New extensions are mapped to format codes by calling fmt_register. fmt_register takes a callback as its second argument; this callback takes a fmt_code_info_t as its only argument. This structure is defined as:

       typedef struct {
	int                 code;
	void               *cl;
	va_list            *app;
	putfunc_t           put;
	void               *put_cl;
	int                 width;
	int                 prec;
	const char         *arg;
	size_t              arg_len;
	struct cvt_array_t *cvt;
	unsigned char       flags[256];
       };
} fmt_code_info_t;

The most important of these arguments is "app", which provides a varargs pointer to the data passed in as the argument to this function. Fmt callbacks use the fmt_puts to output strings. For instance, a callback that prints resolved IP addresses on encountering a %D:

void
fmt_domainname(fmt_code_info_t *cvt) {
	char buf[500];
        char *str = va_arg(*cvt->app, char *);   // Retrieve argument
        struct hostent *hp = gethostbyname(str);
        if(hp) {
               fmt_sfmt(buf, sizeof buf, "%i", hp->h_addr);
        } else
               fmt_sfmt(buf, sizeof buf, "unresolved IP");

	fmt_puts(buf, strlen(buf), cvt);
}
fmt_register('D', fmt_domainname);

SEE ALSO

printf(3)

AUTHOR

Original code: David Hanson <drh@microsoft.com>

Interface and Extensions: Thomas H. Ptacek <tqbf@arbor.net>