|
|
| |
TMPL(3) |
FreeBSD Library Functions Manual |
TMPL(3) |
PDEL Library (libpdel, -lpdel)
struct tmpl *
tmpl_create (FILE
*input, int
*num_errors, const char
*mtype);
struct tmpl *
tmpl_create_mmap (const
char *path, int
*num_errors, const char
*mtype);
void
tmpl_destroy (struct
tmpl **tmplp);
struct tmpl_ctx *
tmpl_ctx_create (void
*arg, const char
*mtype, tmpl_handler_t
*handler, tmpl_errfmtr_t
*errfmtr);
void *
tmpl_ctx_get_arg (struct
tmpl_ctx *ctx);
const char *
tmpl_ctx_get_mtype (struct
tmpl_ctx *ctx);
const char *
tmpl_ctx_get_var (struct
tmpl_ctx *ctx, const char
*name);
int
tmpl_ctx_set_var (struct
tmpl_ctx *ctx, const char
*name, const char
*value);
char *
tmpl_list_handler (struct
tmpl_ctx *ctx, const
struct tmpl_func *userfuncs,
u_int uflen,
char **errmsgp,
int argc,
char **argv);
void
tmpl_ctx_destroy (struct
tmpl_ctx **ctxp);
int
tmpl_execute (struct
tmpl *tmpl, struct
tmpl_ctx *ctx, FILE
*output, int
flags);
int
tmpl_execute_func (struct
tmpl_ctx *ctx, FILE
*output, char
**errmsgp, int
argc, char **argv,
int flags);
void
tmpl_ctx_reset (struct
tmpl_ctx *ctx);
The tmpl library supports programmatic generation of
output based on input from tmpl template files. Output
is generated by parsing and then executing a tmpl file.
The tmpl file simply contains the desired output, with invocations
of various tmpl functions, denoted by the “@” character,
interspersed. Tmpl functions take zero or more arguments, where each
argument can be either a doubly-quoted string or another, nested tmpl
function.
When executed, the output of a tmpl file is simply the contents of
the file, with each tmpl function replaced by the value returned by that
function. Several functions, including control flow constructs, are
built-in, and compile-time and run-time user defined functions are
supported.
Here is a simple example tmpl input file:
I'm going to count to three:
@set("i", "1")
@while(@le(@get("i"), "3"))
@get("i")
@set("i", @add(@get("i"), "1"))
@endwhile
Done.
If this template were executed, the output would be:
I'm going to count to three:
1
2
3
Done.
While the example above uses only built-in functions, user-defined
functions written in C may be invoked in the same way.
This section describes the precise rules that govern how
tmpl files are parsed.
A tmpl file is parsed by scanning for special function calls. A
function call is an at sign ('@') followed by a contiguous sequence of
letters, digits, and underscores, followed by matching parentheses
containing zero or more function arguments. The text between functions calls
is ignored (it doesn't even have to be text).
Function arguments may be either other nested function calls (the
argument to the outer function is the result of the inner function
invocation), or constant literal strings in double quotes (the argument is
the value of the string). Therefore, all function arguments begin with
either an at sign or a double quote character. Function arguments are
separated by commas and may have surrounding whitespace, which is
ignored.
Constant literal strings are enclosed in double quotes and respect
the usual C backslash escapes.
Built-in functions (see below) that take zero arguments do not
require parentheses, but parentheses may be included for separation
purposes.
A parsed tmpl file is represented by a struct
tmpl .
The parsing of a tmpl file and its execution are separate steps. Once a tmpl
file has been parsed, it may be executed several times. Execution requires a
context, represented by a struct
tmpl_ctx , and generates output which is written to an output stream.
When the template is executed, the text between function calls is
copied to the output stream without modification, while the function calls
are replaced with their values, which are strings. Functions are evaluated
as they are encountered during execution.
The tmpl library includes several built-in
functions, including special control flow functions that control input
processing. The user code may also implement custom functions.
User functions may return NULL and set
errno to indicate an error; they may also set an error
string (if no error string is set,
strerror(3)
is used to generate one). When such an error occurs, the function does not
return at all. Instead, an error message is propagated up to the outer-most
function call. The error message is reformatted by an optional user-supplied
error formatter function, and then the formatted message is written to the
output stream.
The built-in functions are listed below. In these definitions, the numeric value
of a string is the result of parsing it with
strtol(3),
and a string is considered "true" if it has a numeric value other
than zero.
- Control flow
-
@while(x)
... @endwhile
-
The text in between is repeated as long as the argument
supplied to @while() is true.
@loop(x)
... @endloop
-
The text in between is repeated N times, where N is the
numerical value of the argument passed to
@loop() .
@loopindex(x)
-
Takes zero or one argument; returns the loop index
(counting from zero) of the loop that is N loops out from the
innermost containing loop, where N is the numerical value of the
argument, or -1 if no such loop exists. If the argument is omitted
it is assumed to be zero.
@if(x)
... [ @elif(y) ... ] [ @else ... ] @endif
-
Conditional execution depending on the truth value of the
argument to @if() . Zero or more
@elif() blocks may be followed by zero or
one @else block. An
@endif is always required.
@break()
-
Break out of the innermost enclosing
@loop or @while .
@continue()
-
Continue with the next iteration of the nearest enclosing
@loop or @while .
@return()
-
Return from within a run-time function.
@eval(x)
-
Parses the argument as a template, executes it, and
returns the resulting output.
- Run-time variables and functions
-
@set(name,
value)
-
Sets the run-time variable named by the first argument to
have the value equal to the second argument. All run-time variables
are global and exist as long as the associated execution context
exists.
@get(name)
-
Returns the value of the run-time variable named by the
first argument, or the empty string if the variable is not set.
@define(name)
... @enddef
-
Defines a run-time function. The text in between is
executed whenever @name(...) is invoked. During this execution, the
variables argc and arg0,
arg1, ... are set to the function argument
count and arguments, respectively; arg0 is
always equal to the name of the function. All run-time functions are
global and exist as long as the associated execution context
exists.
@invoke()
-
Invokes a function. The function to be invoked and its
arguments are described by the run-time variables
argc and arg0,
arg1, ... as above. So
arg0 is the function name and
arg0, arg1, ... are the
function arguments. @invoke() itself does not take any
arguments.
- Evaluators
-
@equal(x,
y)
-
Returns "1" if x and y are identical, otherwise
"0".
@not(x)
-
Returns "1" if x is false, otherwise
"0".
@and(...)
-
Returns "1" if all of the arguments are true,
otherwise "0".
@or(...)
-
Returns "1" if any of the arguments is true,
otherwise "0".
@add(...)
-
Returns the sum of the arguments.
@sub(x,
...)
-
Returns the second and subsequent arguments subtracted
from the first.
@mul(...)
-
Returns the product of the arguments.
@div(x,
y)
-
Returns the first argument divided by the second.
@mod(x,
y)
-
Returns the first argument modulo the second.
@lt(x,
y)
-
Returns "1" if the first argument is less than
the second, otherwise "0".
@le(x,
y)
-
Returns "1" if the first argument is less than
or equal to the second, otherwise "0".
@gt(x,
y)
-
Returns "1" if the first argument is greater
than the second, otherwise "0".
@ge(x,
y)
-
Returns "1" if the first argument is greater
than or equal to the second, otherwise "0".
- String functions
-
@cat(...)
-
Returns the concatenation of all of the arguments.
@@()
-
Returns "@".
@error(arg)
-
Returns the argument formatted using the caller-supplied
error formatter.
@htmlencode(arg)
-
Encodes the argument with HTML escapes and returns the
result.
@urlencode(arg)
-
Encodes the argument with URL escapes and returns the
result.
- I/O functions
-
@flush()
-
Flushes the output stream.
@output(arg)
-
Outputs the argument directly to the output stream. That
is, if this function is invoked from within a user-defined function,
the argument goes directly to the template output rather than being
concatenated to the return value of the function.
tmpl_create () parses input from
input and creates and returns a new template object,
which uses
typed_mem(3)
type mtype. If num_errors is not
NULL , then the number of parse errors detected is
stored in *num_errors. A parse error is an occurrence of
the “@” character that is not the beginning of a well-formed
tmpl function invocation.
tmpl_create_mmap () parses the contents of
the file named path, using
mmap(2)
internally to avoid having to store the entire file in memory. This results
in less memory being used; however, if the file's contents are changed then
subsequent invocations of tmpl_execute () may give
garbled output.
tmpl_destroy () destroys a template object.
Upon return, *tmplp will be set to
NULL . If *tmplp is already
NULL when tmpl_destroy () is
invoked, nothing happens.
tmpl_ctx_create () creates a new template
execution context. mtype is the
typed_mem(3)
type used not only for the execution context object itself, but also for all
strings generated during execution. In particular, all strings returned by
user functions must be stored in buffers allocated with this type. The
arg is a user cookie ignored by the
tmpl functions. The parameters
arg and mtype may be retrieved
with tmpl_ctx_get_arg () and
tmpl_ctx_get_mtype (), respectively.
handler and errfmtr
point to functions having these types:
typedef char *tmpl_handler_t(struct tmpl_ctx *ctx, char **errmsgp,
int argc, char **argv);
typedef char *tmpl_errfmtr_t(struct tmpl_ctx *ctx, const char *errmsg);
handler () returns the result of invoking
the function described by argc and
argv as a '\0'-terminated string allocated with the
typed_mem(3)
type mtype. The first argument is always the function
name, and subsequent arguments are the (evaluated) arguments passed to the
function. Therefore, argc is always at least one.
handler () may indicate an error by
returning NULL , in which case it should either set
errno appropriately or else set
*errmsgp to point to an error message (which should
also be allocated with
typed_mem(3)
type mtype); *errmsgp will be
NULL when handler () is
invoked.
The error formatter function errfmtr () is
optional. It should return an error string allocated with
typed_mem(3)
type mtype and formatted appropriately for the
template output (e.g., in HTML). The errmsg is the
original, unformatted error string returned by the function handler; if the
handler did not return an explicit error message,
strerror(errno) is used for
errmsg.
tmpl_list_handler () may be useful for
implementing handler () when there is a fixed list of
user functions. The userfuncs parameter points to a
length uflen array of struct
tmpl_func :
struct tmpl_func {
const char *name; /* function name, null to end list */
u_int min_args; /* min # args (not counting name) */
u_int max_args; /* max # args (not counting name) */
tmpl_handler_t *handler; /* handler for function */
};
Each entry in the array describes a user function. The function
called name accepts at least
min_args and at most max_args
parameters, and is implemented by the handler. The
array must be sorted lexicographically by name.
tmpl_list_handler () finds the function named by
argv[0] using a binary search of the array and
invokes its handler () with the supplied arguments.
In the case of an error, tmpl_list_handler ()
prepends the returned error string with the offending function call and
arguments.
tmpl_ctx_set_var () and
tmpl_ctx_get_var () may be used to set and retrieve
variables associated with ctx.
tmpl_ctx_destroy () destroys a template
context. Upon return, *ctxp will be set to
NULL . If *ctxp is already
NULL when tmpl_ctx_destroy ()
is invoked, nothing happens.
tmpl_execute () executes the parsed
template tmpl using the execution context
ctx, and writes the output to
output. flags may contain any of
the following values OR'd together:
TMPL_SKIP_NL_WHITE Skip newline plus whitespace
TMPL_SKIP_NL_WHITE causes any
inter-function occurrences of a newline followed by whitespace to be
ignored. This often generates more intuitive output. The example template
given previously would generate this output if
TMPL_SKIP_NL_WHITE were specified:
I'm going to count to three:
123
Done.
tmpl_execute_func () can be used to execute
a single function defined in a template context. This includes non-control
flow built-in functions, user functions, and run-time functions.
ctx, output, and
flags are as with
tmpl_execute (). The function and arguments are
described by argc and argv, and
errmsgp must point to a char *
error message pointer.
tmpl_ctx_reset () resets an execution
context to its initial state. This causes any runtime variables and
functions defined during a previous execution using
ctx to be forgotten.
tmpl_create (),
tmpl_ctx_create (), and
tmpl_execute () return NULL or
-1 to indicate an error, with errno set appropriately.
tmpl_execute_func () returns -1 if there
was an error. In the case of a system error, *errmsgp
will be set to NULL and errno
will be set appropriately; otherwise, *errmsgp will
point to an appropriate error message allocated with
typed_mem(3)
type mtype, which the caller must eventually free.
Here are two common sources of bugs:
- User functions returning constant strings or strings allocated with the
wrong
typed_mem(3)
type.
- Not sorting the user function array given to
tmpl_list_handler ().
The PDEL library was developed at Packet Design, LLC.
http://www.packetdesign.com/
Archie Cobbs ⟨archie@freebsd.org⟩
tmpl_create (), tmpl_execute (),
and tmpl_execute_func () may leak small amounts of
memory if the thread is canceled.
Visit the GSP FreeBSD Man Page Interface. Output converted with ManDoc. |