Skip site navigation (1)Skip section navigation (2)

  
 
  

home | help
TMPL(3) 		     Library Functions Manual			 TMPL(3)

NAME
     tmpl -- templates

LIBRARY
     PDEL Library (libpdel, -lpdel)

SYNOPSIS
     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);

DESCRIPTION
   Overview
     The  tmpl library supports programmatic generation of output based on input
     from tmpl template files.	Output is generated by parsing and then  execut-
     ing a tmpl file.

     The tmpl file simply contains the desired output, with invocations of vari-
     ous tmpl functions, denoted by the "@" character, interspersed.  Tmpl func-
     tions take zero or more arguments, where each argument can be either a dou-
     bly-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  func-
     tion.   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  func-
     tions written in C may be invoked in the same way.

Parsing
     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, dig-
     its,  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.

Execution
     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 re-
     quires  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  re-
     placed  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.

Built-in Functions
     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 re-
	     sulting 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  ex-
	     ists.

	 @get(name)

	     Returns the value of the run-time variable named by the first argu-
	     ment, or the empty string if the variable is not set.

	 @define(name) ... @enddef

	     Defines a run-time function.  The text in between is executed when-
	     ever  @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 argu-
	     ments.

     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, other-
	     wise "0".

	 @le(x, y)

	     Returns "1" if the first argument is less than or equal to the sec-
	     ond, otherwise "0".

	 @gt(x, y)

	     Returns "1" if the first argument is greater than the second,  oth-
	     erwise "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 for-
	     matter.

	 @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.

API
     tmpl_create()  parses  input  from input and creates and returns a new tem-
     plate 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 out-
     put.

     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 ar-
     guments 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 appropri-
     ately 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 im-
     plemented by the handler.	The array must be  sorted  lexicographically  by
     name.   tmpl_list_handler() finds the function named by argv[0] using a bi-
     nary search of the array and invokes its handler() with the supplied  argu-
     ments.   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  con-
     text  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  fol-
     lowed  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 execu-
     tion using ctx to be forgotten.

RETURN VALUES
     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 appropri-
     ately; otherwise, *errmsgp will point to an appropriate error message allo-
     cated with typed_mem(3) type mtype, which the caller must eventually free.

SEE ALSO
     http_servlet_tmpl(3), libpdel(3), strtol(3), typed_mem(3)

IMPLEMENTATION NOTES
     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().

HISTORY
     The    PDEL    library    was    developed    at	 Packet   Design,   LLC.
     http://www.packetdesign.com/

AUTHORS
     Archie Cobbs <archie@freebsd.org>

BUGS
     tmpl_create(),  tmpl_execute(),  and  tmpl_execute_func()	may  leak  small
     amounts of memory if the thread is canceled.

FreeBSD ports 15.quarterly	 April 22, 2002 			 TMPL(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=tmpl_ctx_reset&sektion=3&manpath=FreeBSD+Ports+15.1.quarterly>

home | help