Annotation of embedaddon/libpdel/tmpl/tmpl.3, revision 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>