/* * Copyright (c) 2008 Teodor Sigaev * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON 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 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /****************************************************************************** * SYNTAX * ****************************************************************************** * <% EXPRESSION , "FORMAT"] [# "DEFAULTVALUE"] [|(h|u)]%> * - format value should be as in strftime for time value and printf * for all other. Currently, bool values have only "true"/"false" * string values * <@IF EXPRESSION @> * <@ELSE@> * <@ENDIF@> * * Expression is classical with support following: * - ['^'] VARNAME * variable defined from C-code. Mark '^' means global * variable, not local in loop. * - expression (+|-|*|/|%) expression * ariphmetic operations * - expression ( || | && ) expression * ! expression * logical OR, AND and NOT * - expression ( < | <= | == | >= | > | != | <> ) expression * compare expression * - LENGTH(expression) * computes length of string * - DEFINED(expression) * returns true if expression is defined * - expression ? expression : expression * - ( expression ) * - USERDEFINEDFUNCTION( [expression[,expression[...]]] ) * User defined function call. Function should be defined at * C-level. * * <@LOOP MARKNAME@> * <@ENDLOOP@> * Loop has predefined variables: * __FIRST - true for first iteration * __LAST - true for last iteration * __COUNTER - iteration's number * __SIZE - number of iterations * __ODD - true for odd iteraion * __EVEN - true for even iteraion * * <& FILENAME &> * * <# comment #> * ****************************************************************************** * C-Interface ****************************************************************************** * - setTemplateValueInt * setTemplateValueString * setTemplateValueTime * setTemplateValueBool * setTemplateValueDouble * setTemplateValueUndefined * Sets varibale's value * - addTemplateRow * Add one iteration to the pointed loop. Local variable in loop should * pointed with predecence loop's mark(s) separated by dot. Example: * HTML: * <@Loop outerLoop@> * <% var1 %> * <@Loop innerLoop@> * <% var2 %> * <@endloop@> * <@endloop@> * C: * addTemplateRow("outerLoop"); * setTemplateValueBool("outerLoop.var1"); * addTemplateRow("innerLoop"); * setTemplateValueBool("outerLoop.innerLoop.var2"); * ******************************************************************************/ #ifndef __TEMPLATE_H__ #define __TEMPLATE_H__ #include #include #include "glist.h" #include "sfxstr.h" #include "tmalloc.h" typedef enum TemplateNodeType { /* node tree types */ TextNode = 100, VariableNode, IncludeNode, LoopNode, ConditionNode, CollectionNode, ExpressionNode, PrintNode, ConstNode, /* value's types of variables */ valueInt = 200, /* smallest of any values type */ valueString, valueTime, valueBool, valueDouble, valuePointer } TemplateNodeType; #define TND_HTMLESCAPE (0x0001) #define TND_URLESCAPE (0x0002) #define TND_GLOBAL (0x0004) #define TND___FIRST (0x0008) #define TND___LAST (0x0010) #define TND___COUNTER (0x0020) #define TND___SIZE (0x0040) #define TND___ODD (0x0080) #define TND___EVEN (0x0100) #define TND_DEFINED (0x0200) #define TND__SPECIALMASK (TND___FIRST | TND___LAST | TND___COUNTER | TND___SIZE | TND___ODD | TND___EVEN) typedef struct TemplateData *Template; typedef struct TemplateNodeData *TemplateNode; typedef struct VariableValueData * VariableValue; typedef struct VariableValueData { TemplateNodeType type; /* should be first, see resetTemplate/freeTemplate */ int flags; union { int intValue; char *stringValue; time_t timeValue; int boolValue; double doubleValue; VariableValue ptrValue; /* special value to handle loop variables, points to members of loopValues */ } value; } VariableValueData; typedef struct executeFunctionDescData *executeFunctionDesc; typedef struct executeFunctionDescData { char *name; int nargs; /* -1 - variable number */ VariableValue (*execFn)(Template, int, VariableValue*); } executeFunctionDescData; typedef struct LoopInstanceData * LoopInstance; typedef struct LoopInstanceData { int nrow; GList *rowValues; } LoopInstanceData; typedef struct TemplateNodeData { TemplateNodeType type; /* should be first, see resetTemplate/freeTemplate */ union { /* TextNode */ struct { char *value; int valueLength; } text; /* VariableNode */ struct { char *varName; int varNameLength; VariableValue value; int flags; } variable; /* ExpressionNode */ struct { VariableValue *argsValue; int nargs; char *functionName; executeFunctionDesc function; GList *argsNode; /* list of nodes after parsing but before compile */ } expression; /* ConstNode */ VariableValueData value; /* PrintNode */ struct { TemplateNode expressionNode; char *formatValue; char *defaultValue; int flags; } print; /* IncludeNode */ char *includeFile; /* LoopNode */ struct { char *varName; int varNameLength; TemplateNode bodyNode; int counter; GList *childrenLoop; /* to reset instance */ GList *listVarValues; /* list of loop variables */ GList *listInstance; } loop; /* ConditionNode */ struct { TemplateNode expressionNode; TemplateNode ifNode; TemplateNode elseNode; } condition; /* CollectionNode */ GList *children; } nodeData; } TemplateNodeData; /* prints result */ typedef void (*outFn)(char *, int); typedef char* (*urlEscapeFn)(char *, int * /* in/out */); typedef char* (*htmlEscapeFn)(char *, int * /* in/out */); typedef struct TemplateData { TemplateNode tree; MemoryContext *templateContext; SFSTree variables; outFn printString; urlEscapeFn urlEscape; htmlEscapeFn htmlEscape; executeFunctionDesc functions; } TemplateData; int parseTemplateFile(Template tmpl, char* filename ); /* return non-zero if error */ int initTemplate( Template tmpl, MemoryContext *mc, executeFunctionDesc functions, char *basedir, char *filename ); void freeTemplate( Template tmpl ); void resetTemplate( Template tmpl ); int printTemplate( Template tmpl ); #define TVAR_OK (0) #define TVAR_NOTFOUND (1) #define TVAR_FORBIDDEN (2) #define TVAR_NOROW (3) #define TVAR_LOOPMARK (4) int setTemplateValueInt( Template tmpl, char * key, int val ); int setTemplateValueString( Template tmpl, char * key, char * val ); int setTemplateValueTime( Template tmpl, char * key, time_t val ); int setTemplateValueBool( Template tmpl, char * key, int val ); int setTemplateValueUndefined( Template tmpl, char * key ); int setTemplateValueDouble( Template tmpl, char * key, double val ); int addTemplateRow( Template tmpl, char * key ); void dumpTemplate( Template tmpl ); #endif