/* * Copyright (c) 2001-2002 Packet Design, LLC. * All rights reserved. * * Subject to the following obligations and disclaimer of warranty, * use and redistribution of this software, in source or object code * forms, with or without modifications are expressly permitted by * Packet Design; provided, however, that: * * (i) Any and all reproductions of the source or object code * must include the copyright notice above and the following * disclaimer of warranties; and * (ii) No rights are granted, in any manner or form, to use * Packet Design trademarks, including the mark "PACKET DESIGN" * on advertising, endorsements, or otherwise except as such * appears in the above copyright notice or in the software. * * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, * OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE, * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, * RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * * Author: Archie Cobbs */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "structs/structs.h" #include "structs/type/array.h" #include "tmpl/tmpl.h" #include "io/string_fp.h" #include "util/typed_mem.h" #include "util/string_quote.h" #ifndef TMPL_DEBUG #define TMPL_DEBUG 0 #endif #if TMPL_DEBUG != 0 && defined(__GNUC__) #define DBG(fmt, args...) \ do { fprintf(stderr, fmt , ## args); } while(0) #else #define DBG(fmt, args...) do { } while (0) #endif /* How much nesting is too much */ #define INFINITE_LOOP 128 /* Function types */ enum func_type { TY_NORMAL, TY_LOOP, TY_ENDLOOP, TY_WHILE, TY_ENDWHILE, TY_IF, TY_ELIF, TY_ELSE, TY_ENDIF, TY_DEFINE, TY_ENDDEF, TY_BREAK, TY_CONTINUE, TY_RETURN }; /* Return values from _tmpl_execute_elems() */ enum exec_rtn { RTN_NORMAL, RTN_BREAK, RTN_CONTINUE, RTN_RETURN }; /* Template element flags */ #define TMPL_ELEM_NL_WHITE 0x0001 /* text is nl+space */ #define TMPL_ELEM_MMAP_TEXT 0x0002 /* text is mmap()'d */ /* Function call */ struct func_call { enum func_type type; /* type of function */ char *funcname; /* name of function */ int nargs; /* number of args */ struct func_arg *args; /* function arguments */ tmpl_handler_t *handler; /* built-in: handler */ }; /* Function argument */ struct func_arg { u_char is_literal; /* literal vs. func */ union { struct func_call call; /* function call */ char *literal; /* literal string */ } u; }; /* This represents one parsed chunk of the template */ struct tmpl_elem { /* Lexical information */ char *text; /* text, or NULL if function */ u_int len; /* length of text */ u_int16_t flags; /* element flags */ /* Semantic information */ struct func_call call; /* function and arguments */ union { struct { int endloop;/* endloop element */ } u_loop; /* TY_LOOP */ struct { int endwhile;/* endwhile element */ } u_while; /* TY_WHILE */ struct { int elsie; /* else element, or -1 */ int endif; /* endif element */ } u_if; /* TY_IF */ struct { int enddef; /* enddef element */ } u_define; /* TY_DEFINE */ } u; }; /* Run-time variables */ struct exec_var { char *name; /* variable name */ char *value; /* variable value */ }; /* Run-time functions */ struct exec_func { char *name; /* function name */ int num_elems; /* number of elements */ struct tmpl_elem *elems; /* function elements */ void *eblock; /* unified memory block */ }; /* Looping info */ struct loop_ctx { u_int index; /* current loop index */ struct loop_ctx *outer; /* enclosing loop info */ }; /* Parsed template file */ struct tmpl { void *mmap_addr; /* mmap() address, or NULL */ size_t mmap_len; /* mmap() length */ int num_elems; /* number of parsed elements */ struct tmpl_elem *elems; /* parsed template elements */ void *eblock; /* unified memory block */ char *mtype; /* memory type */ char mtype_buf[TYPED_MEM_TYPELEN]; }; /* Template context */ struct tmpl_ctx { FILE *output; /* current output */ FILE *orig_output; /* original output */ int flags; /* flags */ u_char close_output; /* close 'output' when done */ int depth; /* execution nesting level */ void *arg; /* user function cookie */ tmpl_handler_t *handler; /* user function handler */ tmpl_errfmtr_t *errfmtr; /* user error formatter */ struct loop_ctx *loop; /* innermost loop, if any */ int num_vars; /* number of variables */ struct exec_var *vars; /* runtime variables */ int num_funcs; /* number of functions */ struct exec_func *funcs; /* runtime functions */ char *mtype; /* memory type */ char mtype_buf[TYPED_MEM_TYPELEN]; }; /* * Functions */ __BEGIN_DECLS /* Parsing */ extern int _tmpl_parse(struct tmpl *tmpl, FILE *input, int *num_errors); /* Variable and function handling */ extern int _tmpl_find_var(struct tmpl_ctx *ctx, const char *name); extern int _tmpl_find_func(struct tmpl_ctx *ctx, const char *name); extern int _tmpl_set_func(struct tmpl_ctx *ctx, const char *name, const struct tmpl_elem *elems, int count); /* Memory management */ extern void _tmpl_compact_elems(const char *mtype, struct tmpl_elem *elems, int num_elems, char *mem, size_t *bsize); extern void _tmpl_compact(const char *mtype, char *mem, void *ptrp, size_t len, size_t *bsize); extern void _tmpl_free_func(struct tmpl_ctx *ctx, struct exec_func *func); extern void _tmpl_free_elems(const char *mtype, void *eblock, struct tmpl_elem *elems, int num); extern void _tmpl_free_call(const char *mtype, struct func_call *call); extern void _tmpl_free_arg(const char *mtype, struct func_arg *arg); /* Template execution */ extern enum exec_rtn _tmpl_execute_elems(struct tmpl_ctx *ctx, struct tmpl_elem *elems, int first_elem, int last_elem); extern char *_tmpl_invoke(struct tmpl_ctx *ctx, char **errmsgp, const struct func_call *call); /* Truth determination */ extern int _tmpl_true(const char *s); #if TMPL_DEBUG /* Debugging */ extern const char *_tmpl_elemstr(const struct tmpl_elem *elem, int index); #endif __END_DECLS