Quick Navigator

Search Site

Unix VPS
A - Starter
B - Basic
C - Preferred
D - Commercial
MPS - Dedicated
Previous VPSs
* Sign Up! *

Contact Us
Online Help
Domain Status
Man Pages

Virtual Servers

Topology Map

Server Agreement
Year 2038

USA Flag



Man Pages

Manual Reference Pages  -  FORMATF (3)


format_init, format_free, format_metarule, formatf, format_lastresult, format_lastsize, format_detach - template formatting functions.


Active Template Definition
Active Template Example
Programming Example
See Also


.Fd #include <strfunc.h>

fmt_base * format_init void format_free fmt_base *base int format_metarule fmt_base *base char leftBrace char rightBrace char **(*function)(char *found, void *optKeyPassed) char * formatf fmt_base *base char *template void *optKeyToPass char * format_lastresult fmt_base *base size_t *optSize size_t format_lastsize fmt_base *base char * format_detach fmt_base *base size_t *optReturnSize


It is widely used for programs to read a template and display the data according to it.

Those functions forms a powerful solution to work with a kind of "active" templates. The term "active" means that some operations, like a test of existence of a keyword, or equality tests, can be placed directly to the template and no special handling needed in an application to support it. strfunc(3) library will automagically do the dirty work for you.

The internal language of defining the template is powerful yet simple. Before we run into detailed explanation, let’s talk about programming.

First, programmer needed to initialize the formatting engine by defining the formatting rules. Formatting rules are stored inside the special structure fmt_base. format_init creates an empty structure and returns the pointer to it. One may define a numerous formatting bases and randomly use them. Formatting base may be freed using format_free fmt_base *. Please note that format_init will never return the NULL pointer.

Second, there is a need to fill this empty structure with some formatting rules using the format_metarule function. Formatting rules are defined by specifiyng a braces and the function which will handle the data inside the braces.

Say, we have a template "abc${def}ghi". Programmer should call the format_metarule fb ’{’ ’}’ handler, where fb is the pointer to the formatting base returned by format_init. If two braces are equal, the result is undefined. handler is the function which should be defined as

char ** handler char *found void *optKeyPassed.

It is possible to define a number of such a rules for the single fmt_base. The handler function should return the pointer to the internal char ** data when it is possible, and NULL pointer otherwise. Please NOTE that this pointer is never modified or freed and probably it should be the semi-static structure inside the handler function.

When you’re finished to fill the fmt_base with the rules, the function formatf can be used multiple times to convert the specified template to the destination text. The optional optKeyToPass argument may be specified to pass some additional data, if necessary.

formatf will place the output to the buffer located in the fmt_base and return a pointer to it. The pointer will never be NULL, and is not to be freed. If you need this buffer to be completely yours and do not want to strdup(3) it, there is a function called format_detach fmt_base * size_t *optReturnSize to achive this.

Two other functions, char * format_lastresult fmt_base * size_t *optSize and size_t format_lastsize fmt_base *, are to be used to obtain the pointer to the buffer and its size without invoking formatf once more.


If a template is not containing the special tokens it will considered as plain text and returned unmodified.

Special token and the whole template are defined in the following BNF:

<template>  :=  *(*<string> *<token> *<string>)

<token> := <simple> | <join> | <index> | <choice> | <equality>

<simple> := ’$’ <LB> <param> <RB>

<join> := ’$’ <LB> <param> ’+’ <delimiter> <RB>

<index> := ’$’ <LB> <param> ’[’ <number> ’]’ <RB>

<choice> := ’$’ <LB> <param> ’?’ <iftrue> ’:’ <iffalse> <RB>

<equality> := ’$’ <LB> <param> { "==" | "!=" } *<string> ’?’ <iftrue> ’:’ <iffalse> <RB>

<LB> := <the second argument of format_metarule()>

<RB> := <the third argument of format_metarule()>

<param> := <string>

<delimiter> := <string>

<iftrue> := <template>

<iffalse> := <template>

<string> := *<CHAR>

<number> := 1*<character from ’0’ to ’9’>

The word param defined above, will be passed as the first argument to the handler function.


The following is an example of the typical template. It may be placed to a file, then read and passed to formatf. It is also can be defined as the argument’s value within the configuration file read by cfgread(3).
Login: ${login[0]}
Password: ${password}
Username: ${name?${name}:Unknown name}
Comments: ${comment+, }
$<status==Busy?User is busy>

You can see the index token "${login[0]}", the simple token "${password}", the join token right after the "Comments: ", and equality token is the whole last string. Please note that the last token is formed using the angle braces: you should specify an additional handler function to handle this case. Refer to the PROGRAMMING EXAMPLE section.

Simple tokens are used to display the data returned by the handler function almost without the modification. One exception from this rule exists: if handler return multiple values they are joined together with the string ", " as the separator.

Join tokens are used to join the multiple values. As mentioned above, the handler function return the string array. In this case all values will be joined together separated by the specified delimiter. For this primer the delimiter is ", " (comma followed by single space).

Index token used to get the specified value from the string array returned by handler. Values are counted from zero, so zero index will represent the first available string.

Choice token used to give the dynamic behavior to the templates. The <iftrue> section will be placed to the output buffer if the handler return the valid non-NULL pointer to the non-empty array. This form can be used to rule the output if the expected parameter is not present or empty.

Equality token used to test the array returned by the handler against the string value. The <iftrue> section will be placed to the output buffer if this string match at least one of the array’s elements. All comparisons are canse-insensitive.


Here’s how to implement the above template example’s parsing.
#include <strfunc.h>

char **handler1(char *found, void *optKeyPassed); char **handler2(char *found, void *optKeyPassed);

int main() {         fmt_base *fb;         char *template = "Login: ${login[0]}\nPassword: ${password}\nUsername: ${name?${name}:Unknown name}\nComments: ${comment+, }\n$<status==Busy?User is busy>\n";         char *s;

        /* Create empty structure */         fb = format_init();

        /* Add one formatting rule */         format_metarule(fb, ’{’, ’}’, handler1);

        /* Add another formatting rule to parse angle braces */         format_metarule(fb, ’<’, ’>’, handler1);

        /* Format the template */         s = formatf(fb, template, NULL);

        /* Print out the result */         printf("%s", s);

        /* Free the formatting structure */         format_free(fb);

        return 0; };

char ** handler1(char *found, void *optKeyPassed) {         static char *arr[3] = { NULL, NULL, NULL };


        arr[1] = NULL;

        if(strcasecmp(found, "login") == 0) {                 arr[0] = "john";                 return arr;         };

        if(strcasecmp(found, "name") == 0) {                 arr[0] = "John Smith";                 return arr;         };

        if(strcasecmp(found, "password") == 0) {                 arr[0] = "123";                 return arr;         };

        if(strcasecmp(found, "comment") == 0) {                 arr[0] = "Comment value #1";                 arr[1] = "Comment value #2";                 return arr;         };

        return NULL; };

char ** handler2(char *found, void *optKeyPassed) {         static char *arr[] = { NULL, NULL };


        if(strcasecmp(found, status) == 0) {                 arr[0] = "busy";                 return arr;         };

        return NULL; };


strfunc(3), cfgread(3).


.An Lev Walkin <>
Search for    or go to Top of page |  Section 3 |  Main Index

Powered by GSP Visit the GSP FreeBSD Man Page Interface.
Output converted with manServer 1.07.