Annotation of embedaddon/libpdel/tmpl/tmpl.3, revision 1.1.1.1
1.1 misho 1: .\" Copyright (c) 2001-2002 Packet Design, LLC.
2: .\" All rights reserved.
3: .\"
4: .\" Subject to the following obligations and disclaimer of warranty,
5: .\" use and redistribution of this software, in source or object code
6: .\" forms, with or without modifications are expressly permitted by
7: .\" Packet Design; provided, however, that:
8: .\"
9: .\" (i) Any and all reproductions of the source or object code
10: .\" must include the copyright notice above and the following
11: .\" disclaimer of warranties; and
12: .\" (ii) No rights are granted, in any manner or form, to use
13: .\" Packet Design trademarks, including the mark "PACKET DESIGN"
14: .\" on advertising, endorsements, or otherwise except as such
15: .\" appears in the above copyright notice or in the software.
16: .\"
17: .\" THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
18: .\" TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
19: .\" REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
20: .\" THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
21: .\" WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
22: .\" OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
23: .\" OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
24: .\" OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
25: .\" RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
26: .\" LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
27: .\" OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
28: .\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
29: .\" DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
30: .\" USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
31: .\" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32: .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
33: .\" THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
34: .\" THE POSSIBILITY OF SUCH DAMAGE.
35: .\"
36: .\" Author: Archie Cobbs <archie@freebsd.org>
37: .\"
38: .\" $Id: tmpl.3,v 1.13 2004/06/02 17:24:38 archie Exp $
39: .\"
40: .Dd April 22, 2002
41: .Dt TMPL 3
42: .Os
43: .Sh NAME
44: .Nm tmpl
45: .Nd templates
46: .Sh LIBRARY
47: PDEL Library (libpdel, \-lpdel)
48: .Sh SYNOPSIS
49: .Ft "struct tmpl *"
50: .Fn tmpl_create "FILE *input" "int *num_errors" "const char *mtype"
51: .Ft "struct tmpl *"
52: .Fn tmpl_create_mmap "const char *path" "int *num_errors" "const char *mtype"
53: .Ft void
54: .Fn tmpl_destroy "struct tmpl **tmplp"
55: .Ft "struct tmpl_ctx *"
56: .Fn tmpl_ctx_create "void *arg" "const char *mtype" "tmpl_handler_t *handler" "tmpl_errfmtr_t *errfmtr"
57: .Ft "void *"
58: .Fn tmpl_ctx_get_arg "struct tmpl_ctx *ctx"
59: .Ft "const char *"
60: .Fn tmpl_ctx_get_mtype "struct tmpl_ctx *ctx"
61: .Ft "const char *"
62: .Fn tmpl_ctx_get_var "struct tmpl_ctx *ctx" "const char *name"
63: .Ft "int"
64: .Fn tmpl_ctx_set_var "struct tmpl_ctx *ctx" "const char *name" "const char *value"
65: .Ft "char *"
66: .Fn tmpl_list_handler "struct tmpl_ctx *ctx" "const struct tmpl_func *userfuncs" "u_int uflen" "char **errmsgp" "int argc" "char **argv"
67: .Ft void
68: .Fn tmpl_ctx_destroy "struct tmpl_ctx **ctxp"
69: .Ft int
70: .Fn tmpl_execute "struct tmpl *tmpl" "struct tmpl_ctx *ctx" "FILE *output" "int flags"
71: .Ft int
72: .Fn tmpl_execute_func "struct tmpl_ctx *ctx" "FILE *output" "char **errmsgp" "int argc" "char **argv" "int flags"
73: .Ft void
74: .Fn tmpl_ctx_reset "struct tmpl_ctx *ctx"
75: .Sh DESCRIPTION
76: .\"
77: .Ss Overview
78: .\"
79: The
80: .Nm tmpl
81: library supports programmatic generation of output
82: based on input from
83: .Nm tmpl
84: template files.
85: Output is generated by parsing and then executing a tmpl file.
86: .Pp
87: The tmpl file simply contains the desired output, with invocations
88: of various tmpl functions, denoted by the
89: .Dq @
90: character, interspersed.
91: Tmpl functions take zero or more arguments, where each argument can
92: be either a doubly-quoted string or another, nested tmpl function.
93: .Pp
94: When executed, the output of a tmpl file is simply the contents of the
95: file, with each tmpl function replaced by the value returned by that function.
96: Several functions, including control flow constructs, are built-in,
97: and compile-time and run-time user defined functions are supported.
98: .Pp
99: Here is a simple example tmpl input file:
100: .Pp
101: .Bd -literal -compact -offset 3n
102: I'm going to count to three:
103:
104: @set("i", "1")
105: @while(@le(@get("i"), "3"))
106: @get("i")
107: @set("i", @add(@get("i"), "1"))
108: @endwhile
109:
110: Done.
111: .Ed
112: .Pp
113: If this template were executed, the output would be:
114: .Bd -literal -offset 3n
115: I'm going to count to three:
116:
117:
118:
119: 1
120:
121: 2
122:
123: 3
124:
125:
126:
127: Done.
128: .Ed
129: .Pp
130: While the example above uses only built-in functions, user-defined functions
131: written in C may be invoked in the same way.
132: .\"
133: .Sh Parsing
134: .\"
135: This section describes the precise rules that govern how
136: .Nm tmpl
137: files are parsed.
138: .Pp
139: A tmpl file is parsed by scanning for special function calls.
140: A function call is an at sign ('@') followed by a contiguous sequence
141: of letters, digits, and underscores, followed by matching parentheses
142: containing zero or more function arguments.
143: The text between functions calls is ignored (it doesn't even have to
144: be text).
145: .Pp
146: Function arguments may be either other nested function calls (the argument
147: to the outer function is the result of the inner function invocation),
148: or constant literal strings in double quotes (the argument is the
149: value of the string).
150: Therefore, all function arguments begin with either an at sign or
151: a double quote character.
152: Function arguments are separated by commas and may have surrounding
153: whitespace, which is ignored.
154: .Pp
155: Constant literal strings are enclosed in double quotes and respect the
156: usual C backslash escapes.
157: .Pp
158: Built-in functions (see below) that take zero arguments do not require
159: parentheses, but parentheses may be included for separation purposes.
160: .Pp
161: A parsed tmpl file is represented by a
162: .Li "struct tmpl" .
163: .\"
164: .Sh Execution
165: .\"
166: .Pp
167: The parsing of a tmpl file and its execution are separate steps.
168: Once a tmpl file has been parsed, it may be executed several times.
169: Execution requires a
170: .Em context ,
171: represented by a
172: .Li "struct tmpl_ctx" ,
173: and generates output which is written to an output stream.
174: .Pp
175: When the template is executed, the text between function calls is
176: copied to the output stream without modification, while the function
177: calls are replaced with their values, which are strings.
178: Functions are evaluated as they are encountered during execution.
179: .Pp
180: The
181: .Nm tmpl
182: library includes several built-in functions, including
183: special control flow functions that control input processing.
184: The user code may also implement custom functions.
185: .Pp
186: User functions may return
187: .Dv NULL
188: and set
189: .Va errno
190: to indicate an error; they may also set an error string (if
191: no error string is set,
192: .Xr strerror 3
193: is used to generate one).
194: When such an error occurs, the function does not return at all.
195: Instead, an error message is propagated up to the outer-most function call.
196: The error message is reformatted by an optional user-supplied error
197: formatter function, and then the formatted message is written
198: to the output stream.
199: .\"
200: .Sh Built-in Functions
201: .\"
202: The built-in functions are listed below.
203: In these definitions, the numeric value of a string is the result
204: of parsing it with
205: .Xr strtol 3 ,
206: and a string is considered "true" if it has a numeric value other than zero.
207: .Pp
208: .Bl -hang -compact -width "xx"
209: .It Em "Control flow"
210: .Bl -hang -width "xx"
211: .It Li "@while(x) ... @endwhile"
212: .Pp
213: The text in between is repeated as long as the argument supplied to
214: .Li "@while()"
215: is true.
216: .It Li "@loop(x) ... @endloop"
217: .Pp
218: The text in between is repeated N times, where N is the numerical value
219: of the argument passed to
220: .Li "@loop()" .
221: .It Li "@loopindex(x)"
222: .Pp
223: Takes zero or one argument; returns the loop index (counting from zero)
224: of the loop that is N loops out from the innermost containing loop, where
225: N is the numerical value of the argument, or -1 if no such loop exists.
226: If the argument is omitted it is assumed to be zero.
227: .It Li "@if(x) ... [ @elif(y) ... ] [ @else ... ] @endif"
228: .Pp
229: Conditional execution depending on the truth value of the argument to
230: .Li "@if()" .
231: Zero or more
232: .Li "@elif()"
233: blocks may be followed by zero or one
234: .Li "@else"
235: block.
236: An
237: .Li "@endif"
238: is always required.
239: .It Li "@break()"
240: .Pp
241: Break out of the innermost enclosing
242: .Li "@loop"
243: or
244: .Li "@while" .
245: .It Li "@continue()"
246: .Pp
247: Continue with the next iteration of the nearest enclosing
248: .Li "@loop"
249: or
250: .Li "@while" .
251: .It Li "@return()"
252: .Pp
253: Return from within a run-time function.
254: .It Li "@eval(x)
255: .Pp
256: Parses the argument as a template, executes it, and returns the resulting
257: output.
258: .El
259: .Pp
260: .It Em "Run-time variables and functions"
261: .Bl -hang -width "xx"
262: .It Li "@set(name, value)"
263: .Pp
264: Sets the run-time variable named by the first argument to have the
265: value equal to the second argument.
266: All run-time variables are global and exist as long as the associated
267: execution context exists.
268: .It Li "@get(name)"
269: .Pp
270: Returns the value of the run-time variable named by the first argument,
271: or the empty string if the variable is not set.
272: .It Li "@define(name) ... @enddef"
273: .Pp
274: Defines a run-time function.
275: The text in between is executed whenever @name(...) is invoked.
276: During this execution, the variables
277: .Fa argc
278: and
279: .Fa arg0 ,
280: .Fa arg1 ,
281: \&... are set to the function argument count and arguments, respectively;
282: .Fa arg0
283: is always equal to the name of the function.
284: All run-time functions are global and exist as long as the associated
285: execution context exists.
286: .It Li "@invoke()
287: .Pp
288: Invokes a function.
289: The function to be invoked and its arguments are described by the
290: run-time variables
291: .Fa argc
292: and
293: .Fa arg0 ,
294: .Fa arg1 ,
295: \&...
296: as above.
297: So
298: .Fa arg0
299: is the function name and
300: .Fa arg0 ,
301: .Fa arg1 ,
302: \&...
303: are the function arguments.
304: @invoke() itself does not take any arguments.
305: .El
306: .Pp
307: .It Em "Evaluators"
308: .Bl -hang -width "xx"
309: .It Li "@equal(x, y)"
310: .Pp
311: Returns "1" if x and y are identical, otherwise "0".
312: .It Li "@not(x)"
313: .Pp
314: Returns "1" if x is false, otherwise "0".
315: .It Li "@and(...)"
316: .Pp
317: Returns "1" if all of the arguments are true, otherwise "0".
318: .It Li "@or(...)"
319: .Pp
320: Returns "1" if any of the arguments is true, otherwise "0".
321: .It Li "@add(...)"
322: .Pp
323: Returns the sum of the arguments.
324: .It Li "@sub(x, ...)"
325: .Pp
326: Returns the second and subsequent arguments subtracted from the first.
327: .It Li "@mul(...)"
328: .Pp
329: Returns the product of the arguments.
330: .It Li "@div(x, y)"
331: .Pp
332: Returns the first argument divided by the second.
333: .It Li "@mod(x, y)"
334: .Pp
335: Returns the first argument modulo the second.
336: .It Li "@lt(x, y)"
337: .Pp
338: Returns "1" if the first argument is less than the second, otherwise "0".
339: .It Li "@le(x, y)"
340: .Pp
341: Returns "1" if the first argument is less than or equal to the second,
342: otherwise "0".
343: .It Li "@gt(x, y)"
344: .Pp
345: Returns "1" if the first argument is greater than the second, otherwise "0".
346: .It Li "@ge(x, y)"
347: .Pp
348: Returns "1" if the first argument is greater than or equal to the second,
349: otherwise "0".
350: .El
351: .Pp
352: .It Em "String functions"
353: .Bl -hang -width "xx"
354: .It Li "@cat(...)"
355: .Pp
356: Returns the concatenation of all of the arguments.
357: .It Li "@@()"
358: .Pp
359: Returns "@".
360: .It Li "@error(arg)
361: .Pp
362: Returns the argument formatted using the caller-supplied error formatter.
363: .It Li "@htmlencode(arg)
364: .Pp
365: Encodes the argument with HTML escapes and returns the result.
366: .It Li "@urlencode(arg)
367: .Pp
368: Encodes the argument with URL escapes and returns the result.
369: .El
370: .Pp
371: .It Em "I/O functions"
372: .Bl -hang -width "xx"
373: .It Li "@flush()
374: .Pp
375: Flushes the output stream.
376: .It Li "@output(arg)
377: .Pp
378: Outputs the argument directly to the output stream. That is,
379: if this function is invoked from within a user-defined function,
380: the argument goes directly to the template output rather than
381: being concatenated to the return value of the function.
382: .El
383: .Pp
384: .El
385: .\"
386: .Sh API
387: .\"
388: .Fn tmpl_create
389: parses input from
390: .Fa input
391: and creates and returns a new template object,
392: which uses
393: .Xr typed_mem 3
394: type
395: .Fa mtype .
396: If
397: .Fa num_errors
398: is not
399: .Dv NULL ,
400: then the number of parse errors detected is stored in
401: .Fa "*num_errors" .
402: A parse error is an occurrence of the
403: .Dq @
404: character that is not the beginning of a well-formed
405: .Nm
406: function invocation.
407: .Pp
408: .Fn tmpl_create_mmap
409: parses the contents of the file named
410: .Fa path ,
411: using
412: .Xr mmap 2
413: internally to avoid having to store the entire file in memory.
414: This results in less memory being used; however, if the file's contents
415: are changed then subsequent invocations of
416: .Fn tmpl_execute
417: may give garbled output.
418: .Pp
419: .Fn tmpl_destroy
420: destroys a template object.
421: Upon return,
422: .Fa "*tmplp"
423: will be set to
424: .Dv NULL .
425: If
426: .Fa "*tmplp"
427: is already
428: .Dv NULL
429: when
430: .Fn tmpl_destroy
431: is invoked, nothing happens.
432: .Pp
433: .Fn tmpl_ctx_create
434: creates a new template execution context.
435: .Fa mtype
436: is the
437: .Xr typed_mem 3
438: type used not only for the execution context object itself, but also
439: for all strings generated during execution.
440: In particular, all strings returned by user functions must be stored
441: in buffers allocated with this type.
442: The
443: .Fa arg
444: is a user cookie ignored by the
445: .Nm tmpl
446: functions.
447: The parameters
448: .Fa arg
449: and
450: .Fa mtype
451: may be retrieved with
452: .Fn tmpl_ctx_get_arg
453: and
454: .Fn tmpl_ctx_get_mtype ,
455: respectively.
456: .Pp
457: .Fa handler
458: and
459: .Fa errfmtr
460: point to functions having these types:
461: .Pp
462: .Bd -literal -compact -offset 3n
463: typedef char *tmpl_handler_t(struct tmpl_ctx *ctx, char **errmsgp,
464: int argc, char **argv);
465: typedef char *tmpl_errfmtr_t(struct tmpl_ctx *ctx, const char *errmsg);
466: .Ed
467: .Pp
468: .Fn handler
469: returns the result of invoking the function described by
470: .Fa argc
471: and
472: .Fa argv
473: as a '\\0'-terminated string allocated with the
474: .Xr typed_mem 3
475: type
476: .Fa mtype .
477: The first argument is always the function name, and subsequent arguments
478: are the (evaluated) arguments passed to the function.
479: Therefore,
480: .Fa argc
481: is always at least one.
482: .Pp
483: .Fn handler
484: may indicate an error by returning
485: .Dv NULL ,
486: in which case it should either set
487: .Va errno
488: appropriately or else set
489: .Fa "*errmsgp"
490: to point to an error message (which should also be allocated with
491: .Xr typed_mem 3
492: type
493: .Fa mtype) ;
494: .Fa "*errmsgp"
495: will be
496: .Dv NULL
497: when
498: .Fn handler
499: is invoked.
500: .Pp
501: The error formatter function
502: .Fn errfmtr
503: is optional.
504: It should return an error string allocated with
505: .Xr typed_mem 3
506: type
507: .Fa mtype
508: and formatted appropriately for the template output
509: (e.g., in HTML).
510: The
511: .Fa errmsg
512: is the original, unformatted error string returned by the function handler;
513: if the handler did not return an explicit error message,
514: .Li "strerror(errno)"
515: is used for
516: .Fa errmsg .
517: .Pp
518: .Fn tmpl_list_handler
519: may be useful for implementing
520: .Fn handler
521: when there is a fixed list of user functions.
522: The
523: .Fa userfuncs
524: parameter points to a length
525: .Fa uflen
526: array of
527: .Li "struct tmpl_func" :
528: .Pp
529: .Bd -literal -compact -offset 3n
530: struct tmpl_func {
531: const char *name; /* function name, null to end list */
532: u_int min_args; /* min # args (not counting name) */
533: u_int max_args; /* max # args (not counting name) */
534: tmpl_handler_t *handler; /* handler for function */
535: };
536: .Ed
537: .Pp
538: Each entry in the array describes a user function.
539: The function called
540: .Fa name
541: accepts at least
542: .Fa min_args
543: and at most
544: .Fa max_args
545: parameters, and is implemented by the
546: .Fa handler .
547: The array must be sorted lexicographically by name.
548: .Fn tmpl_list_handler
549: finds the function named by
550: .Li "argv[0]"
551: using a binary search of the array and invokes its
552: .Fn handler
553: with the supplied arguments.
554: In the case of an error,
555: .Fn tmpl_list_handler
556: prepends the returned error string with the offending function call
557: and arguments.
558: .Pp
559: .Fn tmpl_ctx_set_var
560: and
561: .Fn tmpl_ctx_get_var
562: may be used to set and retrieve variables associated with
563: .Fa ctx .
564: .Pp
565: .Fn tmpl_ctx_destroy
566: destroys a template context.
567: Upon return,
568: .Fa "*ctxp"
569: will be set to
570: .Dv NULL .
571: If
572: .Fa "*ctxp"
573: is already
574: .Dv NULL
575: when
576: .Fn tmpl_ctx_destroy
577: is invoked, nothing happens.
578: .Pp
579: .Fn tmpl_execute
580: executes the parsed template
581: .Fa tmpl
582: using the execution context
583: .Fa ctx ,
584: and writes the output to
585: .Fa output .
586: .Fa flags
587: may contain any of the following values OR'd together:
588: .Pp
589: .Bd -literal -compact -offset 3n
590: TMPL_SKIP_NL_WHITE Skip newline plus whitespace
591: .Ed
592: .Pp
593: .Dv TMPL_SKIP_NL_WHITE
594: causes any inter-function occurrences of a newline followed by whitespace
595: to be ignored.
596: This often generates more intuitive output.
597: The example template given previously would generate this output if
598: .Dv TMPL_SKIP_NL_WHITE
599: were specified:
600: .Pp
601: .Bd -literal -compact -offset 3n
602: I'm going to count to three:
603:
604: 123
605:
606: Done.
607: .Ed
608: .Pp
609: .Fn tmpl_execute_func
610: can be used to execute a single function defined in a template context.
611: This includes non-control flow built-in functions, user functions, and
612: run-time functions.
613: .Fa ctx ,
614: .Fa output ,
615: and
616: .Fa flags
617: are as with
618: .Fn tmpl_execute .
619: The function and arguments are described by
620: .Fa argc
621: and
622: .Fa argv ,
623: and
624: .Fa errmsgp
625: must point to a
626: .Li "char *"
627: error message pointer.
628: .Pp
629: .Fn tmpl_ctx_reset
630: resets an execution context to its initial state.
631: This causes any runtime variables and functions defined during a previous
632: execution using
633: .Fa ctx
634: to be forgotten.
635: .Sh RETURN VALUES
636: .Fn tmpl_create ,
637: .Fn tmpl_ctx_create ,
638: and
639: .Fn tmpl_execute
640: return
641: .Dv NULL
642: or -1 to indicate an error, with
643: .Va errno
644: set appropriately.
645: .Pp
646: .Fn tmpl_execute_func
647: returns -1 if there was an error.
648: In the case of a system error,
649: .Fa "*errmsgp"
650: will be set to
651: .Dv NULL
652: and
653: .Va errno
654: will be set appropriately; otherwise,
655: .Fa "*errmsgp"
656: will point to an appropriate error message allocated with
657: .Xr typed_mem 3
658: type
659: .Fa mtype ,
660: which the caller must eventually free.
661: .Sh SEE ALSO
662: .Xr http_servlet_tmpl 3 ,
663: .Xr libpdel 3 ,
664: .Xr strtol 3 ,
665: .Xr typed_mem 3
666: .Sh IMPLEMENTATION NOTES
667: Here are two common sources of bugs:
668: .Pp
669: .Bl -dash -compact -offset 3n
670: .It
671: User functions returning constant strings or strings allocated
672: with the wrong
673: .Xr typed_mem 3
674: type.
675: .It
676: Not sorting the user function array given to
677: .Fn tmpl_list_handler .
678: .El
679: .Sh HISTORY
680: The PDEL library was developed at Packet Design, LLC.
681: .Dv "http://www.packetdesign.com/"
682: .Sh AUTHORS
683: .An Archie Cobbs Aq archie@freebsd.org
684: .Sh BUGS
685: .Fn tmpl_create ,
686: .Fn tmpl_execute ,
687: and
688: .Fn tmpl_execute_func
689: may leak small amounts of memory if the thread is canceled.
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>