Introduce template instance concept to simplify freeing memory
authorteodor <teodor>
Tue, 7 Oct 2008 11:46:38 +0000 (11:46 +0000)
committerteodor <teodor>
Tue, 7 Oct 2008 11:46:38 +0000 (11:46 +0000)
template.c
template.h
tmpltest.c

index 73d9cc4..b20fb89 100644 (file)
 #include "tlog.h"
 #include "template.h"
 
+/*
+ * Simple list implementation
+ */
+#define        TListPush(l,c)  do      {                                               \
+       (c)->nextCell = NULL;                                                   \
+       if ( (l)->tailList == NULL ) {                                  \
+               (l)->headList = (l)->tailList = (c);            \
+       } else {                                                                                \
+               (l)->tailList->nextCell = (c);                          \
+               (l)->tailList = (c);                                            \
+       }                                                                                               \
+} while(0)
+
+#define TListUnShift(l,c)  do  {                                       \
+       (c)->nextCell = (l)->headList;                                  \
+       if ( (l)->headList == NULL ) {                                  \
+               (l)->headList = (l)->tailList = (c);            \
+       } else {                                                                                \
+               (l)->headList = (c);                                            \
+       }                                                                                               \
+} while(0)
+
+#define TListShift(l,c)  do  {                                         \
+       (c) = (l)->headList;                                                    \
+       if ( (c) != NULL )      {                                                       \
+               (l)->headList = (c)->nextCell;                          \
+               if ( (l)->headList == NULL )                            \
+                       (l)->tailList = NULL;                                   \
+       }                                                                                               \
+} while(0)
+
+#define TListIsEmpty(l)                ( (l)->headList == NULL )
+
 /*
  * Default operations and functions
  */
@@ -69,7 +102,7 @@ isVariable(VariableValue value) {
 }
 
 static VariableValue
-makeBoolValue(Template tmpl, int v) {
+makeBoolValue(TemplateInstance tmpl, int v) {
        VariableValue   outvalue = mcalloc(tmpl->templateContext, sizeof(VariableValueData));
 
        outvalue->type = valueBool;
@@ -79,7 +112,7 @@ makeBoolValue(Template tmpl, int v) {
 }
 
 static VariableValue
-copyValue(Template tmpl, VariableValue in) {
+copyValue(TemplateInstance tmpl, VariableValue in) {
        VariableValue   out= mcalloc(tmpl->templateContext, sizeof(VariableValueData));
 
        if (in)
@@ -92,7 +125,7 @@ copyValue(Template tmpl, VariableValue in) {
 }
 
 static VariableValue
-isDefinedFn(Template tmpl, int n, VariableValue *vals) {
+isDefinedFn(TemplateInstance tmpl, int n, VariableValue *vals) {
        return makeBoolValue(tmpl, vals[0]->flags & TND_DEFINED );
 }
 
@@ -113,7 +146,7 @@ strmblen(char *str) {
 }
 
 static VariableValue
-LengthFn(Template tmpl, int n, VariableValue *vals) {
+LengthFn(TemplateInstance tmpl, int n, VariableValue *vals) {
        VariableValue   outvalue = NULL;
 
        outvalue = copyValue( tmpl, NULL );
@@ -130,27 +163,27 @@ LengthFn(Template tmpl, int n, VariableValue *vals) {
 }
 
 static VariableValue
-NotFn(Template tmpl, int n, VariableValue *vals) {
+NotFn(TemplateInstance tmpl, int n, VariableValue *vals) {
        return makeBoolValue(tmpl, !isVariable(vals[0]));
 }
 
 static VariableValue
-AndFn(Template tmpl, int n, VariableValue *vals) {
+AndFn(TemplateInstance tmpl, int n, VariableValue *vals) {
        return makeBoolValue(tmpl, isVariable(vals[0]) && isVariable(vals[1]) );
 }
 
 static VariableValue
-OrFn(Template tmpl, int n, VariableValue *vals) {
+OrFn(TemplateInstance tmpl, int n, VariableValue *vals) {
        return makeBoolValue(tmpl, isVariable(vals[0]) || isVariable(vals[1]) );
 }
 
 static VariableValue
-CondFn(Template tmpl, int n, VariableValue *vals) {
+CondFn(TemplateInstance tmpl, int n, VariableValue *vals) {
        return isVariable(vals[0]) ? vals[1] : vals[2]; 
 }
 
 static VariableValue
-ModFn(Template tmpl, int n, VariableValue *vals) {
+ModFn(TemplateInstance tmpl, int n, VariableValue *vals) {
        VariableValue   outvalue = copyValue( tmpl, NULL );
 
        outvalue->type = valueInt;
@@ -167,7 +200,7 @@ ModFn(Template tmpl, int n, VariableValue *vals) {
 }
 
 static VariableValue
-UnaryMinesFn(Template tmpl, int n, VariableValue *vals) {
+UnaryMinesFn(TemplateInstance tmpl, int n, VariableValue *vals) {
        VariableValue   outvalue = copyValue( tmpl, vals[0] );
 
        if (outvalue->type == valueInt)
@@ -204,25 +237,25 @@ UnaryMinesFn(Template tmpl, int n, VariableValue *vals) {
        }
 
 static VariableValue
-PlusFn(Template tmpl, int n, VariableValue *vals) {
+PlusFn(TemplateInstance tmpl, int n, VariableValue *vals) {
        ARIPHACT(+)
        return outvalue;
 }
 
 static VariableValue
-MinesFn(Template tmpl, int n, VariableValue *vals) {
+MinesFn(TemplateInstance tmpl, int n, VariableValue *vals) {
        ARIPHACT(-)
        return outvalue;
 }
 
 static VariableValue
-MulFn(Template tmpl, int n, VariableValue *vals) {
+MulFn(TemplateInstance tmpl, int n, VariableValue *vals) {
        ARIPHACT(*)
        return outvalue;
 }
 
 static VariableValue
-DivFn(Template tmpl, int n, VariableValue *vals) {
+DivFn(TemplateInstance tmpl, int n, VariableValue *vals) {
        ARIPHACT(/)
        return outvalue;
 }
@@ -249,37 +282,37 @@ DivFn(Template tmpl, int n, VariableValue *vals) {
        }
 
 static VariableValue
-LtFn(Template tmpl, int n, VariableValue *vals) {
+LtFn(TemplateInstance tmpl, int n, VariableValue *vals) {
        CMPACT(<)
        return outvalue;
 }
 
 static VariableValue
-LeFn(Template tmpl, int n, VariableValue *vals) {
+LeFn(TemplateInstance tmpl, int n, VariableValue *vals) {
        CMPACT(<=)
        return outvalue;
 }
 
 static VariableValue
-EqFn(Template tmpl, int n, VariableValue *vals) {
+EqFn(TemplateInstance tmpl, int n, VariableValue *vals) {
        CMPACT(==)
        return outvalue;
 }
 
 static VariableValue
-GeFn(Template tmpl, int n, VariableValue *vals) {
+GeFn(TemplateInstance tmpl, int n, VariableValue *vals) {
        CMPACT(>=)
        return outvalue;
 }
 
 static VariableValue
-GtFn(Template tmpl, int n, VariableValue *vals) {
+GtFn(TemplateInstance tmpl, int n, VariableValue *vals) {
        CMPACT(>)
        return outvalue;
 }
 
 static VariableValue
-NeFn(Template tmpl, int n, VariableValue *vals) {
+NeFn(TemplateInstance tmpl, int n, VariableValue *vals) {
        CMPACT(!=)
        return outvalue;
 }
@@ -366,12 +399,14 @@ findIncludes(ParseState *state, TemplateNode *node) {
                        *node = tmp.tree;
                        break;
                case    LoopNode:
+                       state->tmpl->templateInstanceSize += sizeof( LoopTemplateInstanceData );
                        if ( findIncludes(state, &( (*node)->nodeData.loop.bodyNode )) != 0 )
                                return 1;
                        break;
                case    ConditionNode:
                        if ( findIncludes(state, &( (*node)->nodeData.condition.ifNode )) != 0 ||
-                                       findIncludes(state, &( (*node)->nodeData.condition.elseNode )) != 0 )
+                                       findIncludes(state, &( (*node)->nodeData.condition.elseNode )) != 0  || 
+                                       findIncludes(state, &( (*node)->nodeData.condition.expressionNode )) != 0 )
                                return 1;
                        break;
                case    CollectionNode:
@@ -384,10 +419,23 @@ findIncludes(ParseState *state, TemplateNode *node) {
                                GLCELL_DATA(cell) = chld;
                        }
                        break;
-               case    ExpressionNode: /* any expression node can not include files */
+               case    VariableNode:
+                       state->tmpl->templateInstanceSize += sizeof( VariableValueData );
+                       break;
+               case    ExpressionNode:
+                       GListForeach(cell, (*node)->nodeData.expression.argsNode) {
+                               TemplateNode    chld = (TemplateNode)GLCELL_DATA(cell);
+
+                               if ( findIncludes(state, &chld) != 0 )
+                                       return 1;
+                               GLCELL_DATA(cell) = chld;
+                       }
+                       break;
                case    PrintNode:
+                       if ( findIncludes(state, &( (*node)->nodeData.print.expressionNode )) )
+                               return 1;
+                       break;
                case    ConstNode:
-               case    VariableNode:
                case    TextNode:
                case    NestNode:
                        break;
@@ -470,40 +518,47 @@ checkSpecialVariable(int flags, char *varName) {
        return flags;
 }
 
-static VariableValue
+static Offset
 findVariable( Template tmpl, TemplateNode loopParentNode, int flags, char *varName, int varNameLength ) {
-       VariableValue   *pvarval;
+       Offset                  *pOffset;
 
-       if ( (pvarval = SFSFindData(&tmpl->variables, varName, varNameLength)) == NULL ) {
-               VariableValue           pdata = mc0alloc(tmpl->templateContext, sizeof(VariableValueData));
+       if ( (pOffset = SFSFindData(&tmpl->variables, varName, varNameLength)) == NULL ) {
+               Offset                          offset = tmpl->templateInstanceSize;
+               VariableValue           pdata = (VariableValue)(tmpl->templateInstance + tmpl->templateInstanceSize);
                SFSDataIO                       in;
 
                in.key = varName;
                in.keylen = varNameLength;
-               in.data = &pdata;
+               in.data = &offset;
+
+               tmpl->templateInstanceSize += sizeof(VariableValueData);
 
                SFSAdd(&tmpl->variables, &in);
 
+               pdata->flags = 0;
+
                if ( loopParentNode && (flags & TND_GLOBAL) == 0 ) {
                        /*
-                        * copy special flags to support new inform loopParentNode
+                        * copy special flags to support loopParentNode
                         */
                        pdata->flags |=  flags & TND__SPECIALMASK;
                        pdata->type = valuePointer;
+                       pdata->value.ptrValue = NULL;
 
                        loopParentNode->nodeData.loop.listVarValues = 
-                                       GListPush( loopParentNode->nodeData.loop.listVarValues, pdata ); 
+                                       GListPush( loopParentNode->nodeData.loop.listVarValues, (void*)offset ); 
                }
 
-               return pdata;
+               return offset;
        }
 
-       return *pvarval;
+       return *pOffset;
 }
 
 static int
 addLoop(Template tmpl, TemplateNode node, TemplateNode loopParentNode) {
-       SFSDataIO               in;
+       SFSDataIO                               in;
+       LoopTemplateInstance    lti;
 
        if ( SFSFindData(&tmpl->variables, node->nodeData.loop.varName, node->nodeData.loop.varNameLength) != NULL ) {
                tlog(TL_CRIT,"Loop marked '%s' is already defined", node->nodeData.loop.varName);
@@ -512,10 +567,18 @@ addLoop(Template tmpl, TemplateNode node, TemplateNode loopParentNode) {
 
        in.key = node->nodeData.loop.varName;
        in.keylen = node->nodeData.loop.varNameLength;
-       in.data = &node;
+       in.data = &tmpl->templateInstanceSize;
 
        SFSAdd(&tmpl->variables, &in);
 
+       node->nodeData.loop.loopDataOffset = tmpl->templateInstanceSize; 
+       lti = (LoopTemplateInstance)(tmpl->templateInstance + tmpl->templateInstanceSize);
+       memset(lti, 0, sizeof( LoopTemplateInstanceData ));
+       lti->type = LoopData;
+       lti->loopNode = node;
+
+       tmpl->templateInstanceSize += sizeof( LoopTemplateInstanceData );
+
        if ( loopParentNode ) { 
                loopParentNode->nodeData.loop.childrenLoop = 
                        GListPush( loopParentNode->nodeData.loop.childrenLoop, node );
@@ -603,7 +666,7 @@ compileTree( Template tmpl, TemplateNode node, TemplateNode loopParentNode ) {
                                                                                                        node->nodeData.variable.varName,
                                                                                                        &node->nodeData.variable.varNameLength);
 
-                       node->nodeData.variable.value = findVariable( tmpl, loopParentNode,
+                       node->nodeData.variable.varValueOffset = findVariable( tmpl, loopParentNode,
                                                                                                node->nodeData.variable.flags,
                                                                                                node->nodeData.variable.varName, 
                                                                                                node->nodeData.variable.varNameLength );
@@ -647,7 +710,7 @@ initTemplate( Template tmpl, MemoryContext *mc, executeFunctionDesc functions, c
 
        memset(tmpl, 0, sizeof(TemplateData));
        tmpl->templateContext = mc;
-       SFSInit_dp(&tmpl->variables, sizeof(void*), NULL);
+       SFSInit_dp(&tmpl->variables, sizeof(Offset), NULL);
 
        if ( functions ) {
                executeFunctionDesc     ptr = functions;
@@ -667,6 +730,9 @@ initTemplate( Template tmpl, MemoryContext *mc, executeFunctionDesc functions, c
 
        if ( (err=recursiveReadTemplate(&state, NULL, filename))!=0 )
                return err;
+
+       tmpl->templateInstance = mcalloc( tmpl->templateContext, tmpl->templateInstanceSize );
+       tmpl->templateInstanceSize = 0;
        if ( (err=compileTree( tmpl, tmpl->tree, NULL ))!=0 )
                return err;
 
@@ -674,41 +740,9 @@ initTemplate( Template tmpl, MemoryContext *mc, executeFunctionDesc functions, c
 }
 
 /*
- * Reset/cleanup
+ * cleanup
  */
 
-void
-resetTemplate( Template tmpl ) {
-       SFSDataIO       out;
-       GListCell       *cell;
-
-       SFSIteratorStart( &tmpl->variables );
-
-       while( SFSIterate( &tmpl->variables, &out ) ) {
-               VariableValue   varval = *(VariableValue*) out.data;
-
-               if ( varval->type >= valueInt ) 
-                       varval->flags &= ~TND_DEFINED;
-               else if ( varval->type == LoopNode ) {
-                       TemplateNode    node = (TemplateNode) varval; 
-
-                       GListForeach( cell, node->nodeData.loop.listVarValues ) {
-                               varval = (VariableValue) GLCELL_DATA(cell);
-
-                               if ( varval->type == valuePointer )
-                                       varval->value.ptrValue = NULL;
-                       }
-
-                       GListForeach( cell, node->nodeData.loop.listInstance ) {
-                               LoopInstance instance = GLCELL_DATA(cell);
-
-                               GListFree(instance->rowValues );
-                       }
-                       GListTruncate( node->nodeData.loop.listInstance, 0 ); 
-               }
-       }
-}
-
 static void
 freeNode( TemplateNode node ) {
        GListCell   *cell;
@@ -721,13 +755,6 @@ freeNode( TemplateNode node ) {
                        freeNode( node->nodeData.loop.bodyNode ); /* selfNode is somewhere inside bodyNode */
                        GListFree( node->nodeData.loop.childrenLoop );
                        GListFree( node->nodeData.loop.listVarValues );
-
-                       GListForeach( cell, node->nodeData.loop.listInstance ) {
-                               LoopInstance instance = GLCELL_DATA(cell);
-
-                               GListFree(instance->rowValues );
-                       }
-                       GListFree( node->nodeData.loop.listInstance );
                        break;
                case    CollectionNode:
                        GListForeach( cell, node->nodeData.children ) 
@@ -769,135 +796,174 @@ freeTemplate( Template tmpl ) {
  * Set value routines
  */
 
+TemplateInstance
+newTemplateInstance(Template tmpl, MemoryContext *mc) {
+       TemplateInstance        ti;
+
+       if (mc == NULL)
+               mc = tmpl->templateContext;
+
+       ti = mcalloc(mc, sizeof(TemplateInstanceData) + tmpl->templateInstanceSize);
+       ti->tmpl = tmpl;
+       ti->templateContext = mc;
+       memcpy( ti->instanceData, tmpl->templateInstance, tmpl->templateInstanceSize);
+
+       return ti;
+}
+
 static void
-newLoopInstance( Template tmpl, TemplateNode node ) {
-       LoopInstance    upper = NULL;
+newLoopInstance( TemplateInstance tmpl, TemplateNode node ) {
+       LoopInstance                    upper = NULL;
+       LoopTemplateInstance    loopData = (LoopTemplateInstance)
+                                                       (tmpl->instanceData + node->nodeData.loop.loopDataOffset);
 
-       if ( node->nodeData.loop.currentInstance )
-               upper = node->nodeData.loop.currentInstance->upperInstance;
+       if ( loopData->currentInstance )
+               upper = loopData->currentInstance->upperInstance;
 
-       node->nodeData.loop.currentInstance = 
+       loopData->currentInstance = 
                                mc0alloc(tmpl->templateContext, sizeof(LoopInstanceData) );
-       node->nodeData.loop.currentInstance->upperInstance = upper;
+       loopData->currentInstance->upperInstance = upper;
 
-       node->nodeData.loop.listInstance = GListPush( 
-                               node->nodeData.loop.listInstance,
-                               node->nodeData.loop.currentInstance );
+       TListPush( loopData, loopData->currentInstance );
 
-       node->nodeData.loop.lastRow = NULL;
+       loopData->lastRow = NULL;
 }
 
 int
-addTemplateRow( Template tmpl, char * key) {
-       TemplateNode    *pnode, node;
+addTemplateRow( TemplateInstance tmpl, char * key) {
+       Offset                  *pOffset;
+       TemplateNode    node;
+       LoopTemplateInstance    loopData;
        char            *lkey = strlower(mcstrdup(tmpl->templateContext, key));
        GListCell               *cell;
        int                             i=0, nvar;
        LoopRow                 rowData;
 
-       pnode = SFSFindData(&tmpl->variables, lkey, 0);
+       pOffset = SFSFindData(&tmpl->tmpl->variables, lkey, 0);
        mcfree(lkey);
 
-       if ( pnode == NULL )
+       if ( pOffset == NULL )
                return TVAR_NOTFOUND;
 
-       node = *pnode;
+       loopData = (LoopTemplateInstance)(tmpl->instanceData + *pOffset);
 
-       if ( node->type != LoopNode )
+       if ( loopData->type != LoopData )
                return TVAR_FORBIDDEN;
+       node = loopData->loopNode;
+
+       tassert( *pOffset == node->nodeData.loop.loopDataOffset );
 
        nvar = GLIST_LENGTH( node->nodeData.loop.listVarValues );
        if ( nvar == 0 )
                /* loop without vars can not be looped */
                return TVAR_NOROW;
 
-       if ( GLIST_LENGTH(node->nodeData.loop.listInstance) == 0 )
+       if ( TListIsEmpty(loopData) )
                newLoopInstance(tmpl, node);
 
        GListForeach( cell, node->nodeData.loop.childrenLoop )
                newLoopInstance( tmpl, GLCELL_DATA(cell) );
 
-       node->nodeData.loop.lastRow = rowData = mcalloc( tmpl->templateContext, LRDHDRSZ + sizeof(VariableValueData) * nvar );
+       loopData->lastRow = rowData = mcalloc( tmpl->templateContext, LRDHDRSZ + sizeof(VariableValueData) * nvar );
        rowData->loop = node;
        rowData->nestedInstance = NULL;
 
        GListForeach( cell, node->nodeData.loop.listVarValues ) {       
-               VariableValue   vv = GLCELL_DATA(cell);
+               VariableValue   vv = (VariableValue) (tmpl->instanceData + ((Offset)GLCELL_DATA(cell)));
 
                vv->value.ptrValue = rowData->varvals + i;
                rowData->varvals[i].flags = 0;
                i++;
        }
 
-       node->nodeData.loop.currentInstance->nrow++;
-       node->nodeData.loop.currentInstance->rowValues = 
-                               GListPush( node->nodeData.loop.currentInstance->rowValues, rowData );
+       loopData->currentInstance->nrow++;
+       TListPush( loopData->currentInstance, rowData );
 
        return TVAR_OK;
 }
 
 int 
-addTemplateNestedLoop( Template tmpl, char * key) {
-       TemplateNode    *pnode, node;
+addTemplateNestedLoop( TemplateInstance tmpl, char * key) {
+       Offset                  *pOffset;
+       TemplateNode    node;
+       LoopTemplateInstance    loopData;
        char            *lkey = strlower(mcstrdup(tmpl->templateContext, key));
        GListCell               *cell;
 
-       pnode = SFSFindData(&tmpl->variables, lkey, 0);
+       pOffset = SFSFindData(&tmpl->tmpl->variables, lkey, 0);
        mcfree(lkey);
 
-       if ( pnode == NULL )
+       if ( pOffset == NULL )
                return TVAR_NOTFOUND;
 
-       node = *pnode;
+       loopData = (LoopTemplateInstance)(tmpl->instanceData + *pOffset);
 
-       if ( node->type != LoopNode || node->nodeData.loop.selfNode == 0 )
+       if ( loopData->type != LoopData )
                return TVAR_FORBIDDEN;
+       node = loopData->loopNode;
 
-       if ( GLIST_LENGTH(node->nodeData.loop.listInstance) == 0 || node->nodeData.loop.lastRow == NULL )
+       if ( node->nodeData.loop.selfNode == NULL )
+               return TVAR_FORBIDDEN;
+
+       if ( TListIsEmpty(loopData) || loopData->lastRow == NULL )
                return TVAR_NOROW;
 
-       GListForeach( cell, node->nodeData.loop.childrenLoop )
-               ((TemplateNode)GLCELL_DATA(cell))->nodeData.loop.lastRow = NULL;        
+       GListForeach( cell, node->nodeData.loop.childrenLoop ) {
+               LoopTemplateInstance    childData = (LoopTemplateInstance)
+                               (tmpl->instanceData + ((TemplateNode)GLCELL_DATA(cell))->nodeData.loop.loopDataOffset); 
+                                                                                       
+               childData->lastRow = NULL;
+       }
 
-       node->nodeData.loop.lastRow->nestedInstance = 
+       loopData->lastRow->nestedInstance = 
                                mc0alloc(tmpl->templateContext, sizeof(LoopInstanceData) );
-       node->nodeData.loop.lastRow->nestedInstance->upperInstance = 
-                               node->nodeData.loop.currentInstance;
-       node->nodeData.loop.currentInstance =  
-                               node->nodeData.loop.lastRow->nestedInstance;
-       node->nodeData.loop.lastRow = NULL;
+       loopData->lastRow->nestedInstance->upperInstance = 
+                               loopData->currentInstance;
+       loopData->currentInstance =  
+                               loopData->lastRow->nestedInstance;
+       loopData->lastRow = NULL;
 
        return TVAR_OK;
 }
 
 int
-returnTemplateNestedLoop( Template tmpl, char * key) {
-       TemplateNode    *pnode, node;
+returnTemplateNestedLoop( TemplateInstance tmpl, char * key) {
+       Offset                  *pOffset;
+       TemplateNode    node;
+       LoopTemplateInstance    loopData;
        char            *lkey = strlower(mcstrdup(tmpl->templateContext, key));
        GListCell               *cell;
 
-       pnode = SFSFindData(&tmpl->variables, lkey, 0);
+       pOffset = SFSFindData(&tmpl->tmpl->variables, lkey, 0);
        mcfree(lkey);
 
-       if ( pnode == NULL )
+       if ( pOffset == NULL )
                return TVAR_NOTFOUND;
 
-       node = *pnode;
+       loopData = (LoopTemplateInstance)(tmpl->instanceData + *pOffset);
 
-       if ( node->type != LoopNode || node->nodeData.loop.selfNode == 0 )
+       if ( loopData->type != LoopData )
                return TVAR_FORBIDDEN;
+       node = loopData->loopNode;
 
-       if ( GLIST_LENGTH(node->nodeData.loop.listInstance) == 0 )
+       if ( node->nodeData.loop.selfNode == NULL )
+               return TVAR_FORBIDDEN;
+
+       if ( TListIsEmpty(loopData) )
                return TVAR_NOROW;
 
-       if ( node->nodeData.loop.currentInstance == NULL )
+       if ( loopData->currentInstance == NULL )
                return TVAR_NOROW;
 
-       GListForeach( cell, node->nodeData.loop.childrenLoop )
-               ((TemplateNode)GLCELL_DATA(cell))->nodeData.loop.lastRow = NULL;        
+       GListForeach( cell, node->nodeData.loop.childrenLoop ) {
+               LoopTemplateInstance    childData = (LoopTemplateInstance)
+                               (tmpl->instanceData + ((TemplateNode)GLCELL_DATA(cell))->nodeData.loop.loopDataOffset); 
+                                                                                       
+               childData->lastRow = NULL;
+       }
 
-       node->nodeData.loop.currentInstance = node->nodeData.loop.currentInstance->upperInstance; 
-       node->nodeData.loop.lastRow = NULL;
+       loopData->currentInstance = loopData->currentInstance->upperInstance; 
+       loopData->lastRow = NULL;
 
        return TVAR_OK;
 
@@ -906,17 +972,18 @@ returnTemplateNestedLoop( Template tmpl, char * key) {
 static VariableValueData storage;
        
 static int
-setTemplateValue( Template tmpl, char *key) {
-       VariableValue   *pvarval, varval;
+setTemplateValue( TemplateInstance tmpl, char *key) {
+       Offset                  *pOffset;
+       VariableValue   varval;
        char                    *lkey = strlower(mcstrdup(tmpl->templateContext, key));
        
-       pvarval = SFSFindData(&tmpl->variables, lkey, 0);
+       pOffset = SFSFindData(&tmpl->tmpl->variables, lkey, 0);
        mcfree(lkey);
 
-       if ( pvarval == NULL )
+       if ( pOffset == NULL )
                return TVAR_NOTFOUND;
 
-       varval = *pvarval;
+       varval = (VariableValue)(tmpl->instanceData + *pOffset);
 
        if ( varval->type != 0 && varval->type < valueInt ) {
                return TVAR_LOOPMARK;
@@ -946,7 +1013,7 @@ setTemplateValue( Template tmpl, char *key) {
 
 
 int
-setTemplateValueInt( Template tmpl, char * key, int val ) {
+setTemplateValueInt( TemplateInstance tmpl, char * key, int val ) {
        storage.flags = TND_DEFINED;
        storage.type = valueInt;
        storage.value.intValue = val;
@@ -954,7 +1021,7 @@ setTemplateValueInt( Template tmpl, char * key, int val ) {
 }
 
 int
-setTemplateValueString( Template tmpl, char * key, char * val ) {
+setTemplateValueString( TemplateInstance tmpl, char * key, char * val ) {
        storage.flags = TND_DEFINED;
        storage.type = valueString;
        storage.value.stringValue = val;
@@ -962,7 +1029,7 @@ setTemplateValueString( Template tmpl, char * key, char * val ) {
 }
 
 int
-setTemplateValueTime( Template tmpl, char * key, time_t val ) {
+setTemplateValueTime( TemplateInstance tmpl, char * key, time_t val ) {
        storage.flags = TND_DEFINED;
        storage.type = valueTime;
        storage.value.timeValue = val;
@@ -970,7 +1037,7 @@ setTemplateValueTime( Template tmpl, char * key, time_t val ) {
 }
 
 int
-setTemplateValueBool( Template tmpl, char * key, int val ) {
+setTemplateValueBool( TemplateInstance tmpl, char * key, int val ) {
        storage.flags = TND_DEFINED;
        storage.type = valueBool;
        storage.value.boolValue = val;
@@ -978,7 +1045,7 @@ setTemplateValueBool( Template tmpl, char * key, int val ) {
 }
 
 int
-setTemplateValueDouble( Template tmpl, char * key, double val ) {
+setTemplateValueDouble( TemplateInstance tmpl, char * key, double val ) {
        storage.flags = TND_DEFINED;
        storage.type = valueDouble;
        storage.value.boolValue = val;
@@ -986,7 +1053,7 @@ setTemplateValueDouble( Template tmpl, char * key, double val ) {
 }
 
 int
-setTemplateValueUndefined( Template tmpl, char * key ) {
+setTemplateValueUndefined( TemplateInstance tmpl, char * key ) {
        storage.flags = 0;
        return setTemplateValue( tmpl, key );
 }
@@ -996,7 +1063,7 @@ setTemplateValueUndefined( Template tmpl, char * key ) {
  */
 
 static char *
-printVal( Template tmpl, VariableValue value, int *len, char *format ) {
+printVal( TemplateInstance tmpl, VariableValue value, int *len, char *format ) {
        int             printedlen;
        char    *res;
 
@@ -1065,7 +1132,7 @@ printVal( Template tmpl, VariableValue value, int *len, char *format ) {
 
 
 static VariableValue
-executeExpression( Template tmpl, TemplateNode node ) {
+executeExpression( TemplateInstance tmpl, TemplateNode node ) {
        VariableValue   outvalue = NULL;
        GListCell               *cell;
        int                             i = 0;
@@ -1076,10 +1143,12 @@ executeExpression( Template tmpl, TemplateNode node ) {
                        outvalue = &node->nodeData.value;
                        break;
                case VariableNode:
-                       if ( node->nodeData.variable.value->type == valuePointer )
-                               outvalue = node->nodeData.variable.value->value.ptrValue;
-                       else
-                               outvalue = node->nodeData.variable.value;
+                       outvalue = (VariableValue)(tmpl->instanceData + node->nodeData.variable.varValueOffset);
+
+                       tassert( (outvalue->flags & TND_DEFINED) == 0 || (outvalue->type >= valueInt && outvalue->type <= valuePointer) );
+
+                       if ( outvalue->type == valuePointer )
+                               outvalue = outvalue->value.ptrValue;
                        break;
                case ExpressionNode:
                        GListForeach(cell, node->nodeData.expression.argsNode)
@@ -1110,7 +1179,7 @@ executeExpression( Template tmpl, TemplateNode node ) {
 }
 
 static void
-printNode( Template tmpl, TemplateNode node, LoopInstance loopInstance ) {
+printNode( TemplateInstance tmpl, TemplateNode node, LoopInstance loopInstance ) {
        GListCell       *cell;
        VariableValue   value;
        int                             i;
@@ -1121,18 +1190,17 @@ printNode( Template tmpl, TemplateNode node, LoopInstance loopInstance ) {
        switch (node->type) {
                case    LoopNode:
                        {
+                               LoopTemplateInstance    loopData = (LoopTemplateInstance)
+                                                                               (tmpl->instanceData + node->nodeData.loop.loopDataOffset);
                                GListCell               *cell;
                                LoopInstance    instance;
 
                                if ( loopInstance ) {
                                        instance = loopInstance;
                                } else {
-                                       cell = GListShift( node->nodeData.loop.listInstance );
-                                       if ( cell == NULL )
+                                       TListShift( loopData, instance );
+                                       if ( instance == NULL )
                                                return;
-
-                                       instance = GLCELL_DATA(cell);
-                                       GListFreeCell( node->nodeData.loop.listInstance, cell );
                                }
 
                                for(i=0; i<instance->nrow;i++) {
@@ -1140,12 +1208,10 @@ printNode( Template tmpl, TemplateNode node, LoopInstance loopInstance ) {
                                        int                             j = 0;
                                        VariableValue   realValue;
 
-                                       cell = GListShift( instance->rowValues );
-                                       rowData = GLCELL_DATA(cell);
-                                       GListFreeCell( instance->rowValues, cell );
+                                       TListShift( instance, rowData );
 
                                        GListForeach( cell, node->nodeData.loop.listVarValues ) {
-                                               value = (VariableValue)GLCELL_DATA(cell);
+                                               value = (VariableValue) (tmpl->instanceData + ((Offset)GLCELL_DATA(cell)));
                                
                                                tassert( value->type == valuePointer );
                                                realValue = value->value.ptrValue = rowData->varvals+j;
@@ -1194,8 +1260,6 @@ printNode( Template tmpl, TemplateNode node, LoopInstance loopInstance ) {
 
                                        printNode( tmpl, node->nodeData.loop.bodyNode, NULL );
                                }
-
-                               GListFree( instance->rowValues );
                        }
                        break;
                case    NestNode:
@@ -1213,14 +1277,13 @@ printNode( Template tmpl, TemplateNode node, LoopInstance loopInstance ) {
                                        i=0;
                                        GListForeach( cell, node->nodeData.nest.childrenLoopAfterSelf) {
                                                TemplateNode    chld = GLCELL_DATA(cell);
-                                               GListCell               *cellInstance = GListShift( chld->nodeData.loop.listInstance );
+                                               LoopTemplateInstance    loopData = (LoopTemplateInstance)
+                                                                                                       (tmpl->instanceData + chld->nodeData.loop.loopDataOffset);
+                                               LoopInstance    cellInstance;
 
-                                               if ( cellInstance == NULL )
-                                                       savedChildrenInstance[i++] = NULL;
-                                               else {
-                                                       savedChildrenInstance[i++] = GLCELL_DATA(cellInstance);
-                                                       GListFreeCell( chld->nodeData.loop.listInstance, cellInstance );
-                                               }
+                                               TListShift( loopData, cellInstance );
+
+                                               savedChildrenInstance[i++] = cellInstance;
                                        }
                                }
 
@@ -1231,7 +1294,8 @@ printNode( Template tmpl, TemplateNode node, LoopInstance loopInstance ) {
                                 */
                                i=0;
                                GListForeach( cell, node->nodeData.nest.loop->nodeData.loop.listVarValues ) {
-                                       ((VariableValue)GLCELL_DATA(cell))->value.ptrValue = savedRowData->varvals + i;
+                                       value = (VariableValue) (tmpl->instanceData + ((Offset)GLCELL_DATA(cell)));
+                                       value->value.ptrValue = savedRowData->varvals + i;
                                        i++;
                                }
 
@@ -1239,9 +1303,11 @@ printNode( Template tmpl, TemplateNode node, LoopInstance loopInstance ) {
                                        i=0;
                                        GListForeach( cell, node->nodeData.nest.childrenLoopAfterSelf) {
                                                TemplateNode    chld = GLCELL_DATA(cell);
+                                               LoopTemplateInstance    loopData = (LoopTemplateInstance)
+                                                                                                       (tmpl->instanceData + chld->nodeData.loop.loopDataOffset);
 
                                                if ( savedChildrenInstance[i] )
-                                                       GListUnshift( chld->nodeData.loop.listInstance, savedChildrenInstance[i]);
+                                                       TListUnShift( loopData, savedChildrenInstance[i] );
                                                i++;
                                        }
                                }
@@ -1268,22 +1334,22 @@ printNode( Template tmpl, TemplateNode node, LoopInstance loopInstance ) {
 
                                res = printVal(tmpl, value, &len, node->nodeData.print.formatValue);
 
-                               if ( (node->nodeData.variable.flags & TND_HTMLESCAPE) && tmpl->htmlEscape )
-                                       res = tmpl->htmlEscape(res, &len);
-                               if ( (node->nodeData.variable.flags & TND_URLESCAPE) && tmpl->urlEscape )
-                                       res = tmpl->urlEscape(res, &len);
+                               if ( (node->nodeData.variable.flags & TND_HTMLESCAPE) && tmpl->tmpl->htmlEscape )
+                                       res = tmpl->tmpl->htmlEscape(res, &len);
+                               if ( (node->nodeData.variable.flags & TND_URLESCAPE) && tmpl->tmpl->urlEscape )
+                                       res = tmpl->tmpl->urlEscape(res, &len);
 
                                if ( res && len>0  ) {
-                                       tmpl->printString( res, len );
+                                       tmpl->tmpl->printString( res, len );
                                        mcfree(res);
                                }
                        } else if ( node->nodeData.print.defaultValue ) {
-                               tmpl->printString( node->nodeData.print.defaultValue,
+                               tmpl->tmpl->printString( node->nodeData.print.defaultValue,
                                                                        strlen( node->nodeData.print.defaultValue ) );
                        }
                        break;
                case    TextNode:
-                       tmpl->printString( node->nodeData.text.value,  node->nodeData.text.valueLength );
+                       tmpl->tmpl->printString( node->nodeData.text.value,  node->nodeData.text.valueLength );
                        break;
                case    IncludeNode:
                case    VariableNode:
@@ -1298,11 +1364,11 @@ printNode( Template tmpl, TemplateNode node, LoopInstance loopInstance ) {
 }
 
 int
-printTemplate( Template tmpl ) {
-       if (!tmpl->printString)
+printTemplate( TemplateInstance tmpl ) {
+       if (!tmpl->tmpl->printString)
                return 1;
 
-       printNode(tmpl, tmpl->tree, NULL);
+       printNode(tmpl, tmpl->tmpl->tree, NULL);
 
        return 0;
 }
index 7953de4..cd80d75 100644 (file)
  * in library. So, library uses mixed plain malloc and memory context
  * concepts (tmalloc.h).
  * To work with library it's needed to allocate persistent memory context
- * for initTemplate() call and provide temporary memory context for usual work.
- * after printTemplate is called it's needed to call resetTemplate() and 
- * then resetMemoryContext() for second context. 
+ * for initTemplate().
+ * To work with template it's needed to get template's instance by 
+ * newTemplateInstance() call with separated memory context. In any time
+ * that memory context can be reseted or freeed and it will be enough
+ * to free template's instance.
  * 
  ******************************************************************************/
 
@@ -143,6 +145,7 @@ typedef     enum TemplateNodeType {
        PrintNode,
        ConstNode,
        NestNode,
+       LoopData,
 
        /* value's types of variables */
        valueInt = 200, /* smallest of any values type */
@@ -170,6 +173,8 @@ typedef     enum TemplateNodeType {
 
 typedef struct TemplateData *Template;
 
+typedef struct TemplateInstanceData *TemplateInstance;
+
 typedef struct TemplateNodeData *TemplateNode;
 
 typedef struct VariableValueData * VariableValue;
@@ -192,7 +197,7 @@ typedef struct executeFunctionDescData *executeFunctionDesc;
 typedef struct executeFunctionDescData {
        char                    *name;
        int                             nargs; /* -1 - variable number */
-       VariableValue   (*execFn)(Template, int, VariableValue*);
+       VariableValue   (*execFn)(TemplateInstance, int, VariableValue*);
 } executeFunctionDescData;
 
 typedef struct LoopInstanceData * LoopInstance;
@@ -202,6 +207,7 @@ typedef struct LoopRowData *LoopRow;
 typedef struct LoopRowData {
        TemplateNode            loop;
        LoopInstance            nestedInstance;
+       LoopRow                         nextCell;
        VariableValueData       varvals[1];
 } LoopRowData;
 #define LRDHDRSZ       (offsetof(LoopRowData, varvals))
@@ -209,9 +215,26 @@ typedef struct LoopRowData {
 typedef struct LoopInstanceData {
        int                             nrow;
        LoopInstance    upperInstance;
-       GList                   *rowValues; /*list of LoopRow */
+
+       LoopInstance    nextCell;
+       LoopRow                 headList;
+       LoopRow                 tailList;
+       /* GList                        *rowValues; */ /*list of LoopRow */
 } LoopInstanceData;
 
+typedef struct LoopTemplateInstanceData *LoopTemplateInstance;
+typedef struct LoopTemplateInstanceData {
+       TemplateNodeType        type; /* LoopData */
+       TemplateNode            loopNode;
+       LoopRow                         lastRow;
+       LoopInstance            currentInstance;
+       LoopInstance            headList;
+       LoopInstance            tailList;
+       /*GList                         *listInstance;*/
+}      LoopTemplateInstanceData;
+
+typedef long Offset; 
+
 typedef struct  TemplateNodeData {
        TemplateNodeType        type; /* should be first, see resetTemplate/freeTemplate */
 
@@ -226,7 +249,8 @@ typedef struct  TemplateNodeData {
                struct {
                        char                    *varName;
                        int                             varNameLength;
-                       VariableValue   value;
+                       Offset                  varValueOffset;
+                       /* VariableValue        value; */
                        int                             flags;
                } variable;
 
@@ -268,16 +292,7 @@ typedef struct  TemplateNodeData {
                        TemplateNode    selfNode; /* pointer to self-nested plase to insert */
                        GList                   *childrenLoop;  /* to reset loop's instance  */
                        GList                   *listVarValues; /* list of loop variables */
-                       GList                   *listInstance;
-                       /*      listInstace -+
-                                                        +->instance-+
-                                                                                +->row
-                                                                                |
-                                                                                |
-                                                                                +->row->currentInstance
-                        */
-                       LoopRow                 lastRow;
-                       LoopInstance    currentInstance;                
+                       Offset                  loopDataOffset;
                } loop;
 
                /* ConditionNode */
@@ -307,13 +322,22 @@ typedef struct TemplateData {
        urlEscapeFn                     urlEscape;
        htmlEscapeFn            htmlEscape;
        executeFunctionDesc functions;
+
+       Offset                          templateInstanceSize;
+       char                            *templateInstance;
 } TemplateData;
 
+typedef struct TemplateInstanceData {
+       Template                        tmpl;
+       MemoryContext           *templateContext;
+       char                            instanceData[1];
+} TemplateInstanceData;
+
 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 );
+TemplateInstance       newTemplateInstance(Template tmpl, MemoryContext *mc);
+int printTemplate( TemplateInstance tmpl );
 
 #define TVAR_OK                        (0)
 #define TVAR_NOTFOUND  (1)
@@ -321,14 +345,14 @@ int printTemplate( Template tmpl );
 #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 );
-int addTemplateNestedLoop( Template tmpl, char * key);
-int returnTemplateNestedLoop( Template tmpl, char * key);
+int setTemplateValueInt( TemplateInstance tmpl, char * key, int val );
+int setTemplateValueString( TemplateInstance tmpl, char * key, char * val );
+int setTemplateValueTime( TemplateInstance tmpl, char * key, time_t val );
+int setTemplateValueBool( TemplateInstance tmpl, char * key, int val );
+int setTemplateValueUndefined( TemplateInstance tmpl, char * key );
+int setTemplateValueDouble( TemplateInstance tmpl, char * key, double val );
+int addTemplateRow( TemplateInstance tmpl, char * key );
+int addTemplateNestedLoop( TemplateInstance tmpl, char * key);
+int returnTemplateNestedLoop( TemplateInstance tmpl, char * key);
 void dumpTemplate( Template tmpl );
 #endif
index a605f0b..57d4491 100644 (file)
@@ -57,7 +57,7 @@ outfunc(char *str, int len) {
 static int counter = 0;
 
 static VariableValue 
-localCounter(Template tmpl, int nargs, VariableValue *args) {
+localCounter(TemplateInstance tmpl, int nargs, VariableValue *args) {
        VariableValue out = tmalloc(sizeof(VariableValue));
 
        out->type = valueInt;
@@ -75,6 +75,7 @@ main(int argn, char *argv[]) {
        MemoryContext   *base;
        char                    *name = NULL;
        TemplateData    template;
+       TemplateInstance tinstance;
        int                     i,j,k;
        int                             cnt=0;
        executeFunctionDescData funcs[] = {
@@ -108,93 +109,94 @@ main(int argn, char *argv[]) {
        printf("initTemplate: %d\n",  initTemplate(&template, base, funcs, ".", name) );
        /* dumpTemplate(&template); */
 
-       setTemplateValueInt(&template, "ID", 17);
-       setTemplateValueUndefined(&template, "emptyID");
-       setTemplateValueInt(&template, "zeroid", 0);
-       setTemplateValueString(&template, "str", "QWERTY");
+       tinstance = newTemplateInstance(&template, NULL);
 
-       addTemplateRow(&template, "outerLoop");
-       setTemplateValueString(&template, "outerLoop.data1", "ha1");
-       setTemplateValueUndefined(&template, "outerLoop.data2");
+       setTemplateValueInt(tinstance, "ID", 17);
+       setTemplateValueUndefined(tinstance, "emptyID");
+       setTemplateValueInt(tinstance, "zeroid", 0);
+       setTemplateValueString(tinstance, "str", "QWERTY");
 
-       addTemplateRow(&template, "outerLoop");
-       setTemplateValueInt(&template, "outerLoop.data1", 10);
-       setTemplateValueString(&template, "outerLoop.data2", "WOW");
-               addTemplateRow(&template, "outerLoop.innerLoop");
-               setTemplateValueString(&template, "outerLoop.innerLoop.camenty", "Number 1");
-               addTemplateRow(&template, "outerLoop.innerLoop");
-               setTemplateValueString(&template, "outerLoop.innerLoop.camenty", "Number 2");
+       addTemplateRow(tinstance, "outerLoop");
+       setTemplateValueString(tinstance, "outerLoop.data1", "ha1");
+       setTemplateValueUndefined(tinstance, "outerLoop.data2");
 
-       addTemplateRow(&template, "outerLoop");
-       setTemplateValueString(&template, "outerLoop.data1", "ha3");
+       addTemplateRow(tinstance, "outerLoop");
+       setTemplateValueInt(tinstance, "outerLoop.data1", 10);
+       setTemplateValueString(tinstance, "outerLoop.data2", "WOW");
+               addTemplateRow(tinstance, "outerLoop.innerLoop");
+               setTemplateValueString(tinstance, "outerLoop.innerLoop.camenty", "Number 1");
+               addTemplateRow(tinstance, "outerLoop.innerLoop");
+               setTemplateValueString(tinstance, "outerLoop.innerLoop.camenty", "Number 2");
+
+       addTemplateRow(tinstance, "outerLoop");
+       setTemplateValueString(tinstance, "outerLoop.data1", "ha3");
 
        template.printString = outfunc;
-       printTemplate( &template );
+       printTemplate( tinstance );
 
-       resetTemplate(&template);
+       tinstance = newTemplateInstance(&template, NULL);
 
-       setTemplateValueInt(&template, "ID", 23);
-       setTemplateValueUndefined(&template, "emptyID");
-       setTemplateValueInt(&template, "zeroid", 0);
-       addTemplateRow(&template, "outerLoop");
-       setTemplateValueString(&template, "outerLoop.data1", "ha1");
-       setTemplateValueInt(&template, "outerLoop.data1", 1234);
-       setTemplateValueString(&template, "outerLoop.data2", "FOO");
-       addTemplateRow(&template, "outerLoop.innerLoop");
-               setTemplateValueString(&template, "outerLoop.innerLoop.camenty", "Again 1");
+       setTemplateValueInt(tinstance, "ID", 23);
+       setTemplateValueUndefined(tinstance, "emptyID");
+       setTemplateValueInt(tinstance, "zeroid", 0);
+       addTemplateRow(tinstance, "outerLoop");
+       setTemplateValueString(tinstance, "outerLoop.data1", "ha1");
+       setTemplateValueInt(tinstance, "outerLoop.data1", 1234);
+       setTemplateValueString(tinstance, "outerLoop.data2", "FOO");
+       addTemplateRow(tinstance, "outerLoop.innerLoop");
+               setTemplateValueString(tinstance, "outerLoop.innerLoop.camenty", "Again 1");
 
        for(i=0;i<3;i++) {
-               addTemplateRow(&template,"selfLoop");
-               setTemplateValueInt(&template, "selfLoop.CNT", ++cnt);
-               setTemplateValueString(&template, "selfLoop.NODE", "outer");
+               addTemplateRow(tinstance,"selfLoop");
+               setTemplateValueInt(tinstance, "selfLoop.CNT", ++cnt);
+               setTemplateValueString(tinstance, "selfLoop.NODE", "outer");
 
                if (i<1) {
-                       addTemplateRow(&template,"selfLoop.oneloop");
-                       setTemplateValueInt(&template, "selfLoop.oneloop.CNT", ++cnt);
-                       setTemplateValueString(&template, "selfLoop.oneloop.NODE", "subloop1");
+                       addTemplateRow(tinstance,"selfLoop.oneloop");
+                       setTemplateValueInt(tinstance, "selfLoop.oneloop.CNT", ++cnt);
+                       setTemplateValueString(tinstance, "selfLoop.oneloop.NODE", "subloop1");
                }
                if (i<2) {
-                       addTemplateRow(&template,"selfLoop.oneloop");
-                       setTemplateValueInt(&template, "selfLoop.oneloop.CNT", ++cnt);
-                       setTemplateValueString(&template, "selfLoop.oneloop.NODE", "subloop2");
+                       addTemplateRow(tinstance,"selfLoop.oneloop");
+                       setTemplateValueInt(tinstance, "selfLoop.oneloop.CNT", ++cnt);
+                       setTemplateValueString(tinstance, "selfLoop.oneloop.NODE", "subloop2");
                }
 
-               addTemplateNestedLoop(&template, "selfLoop");
+               addTemplateNestedLoop(tinstance, "selfLoop");
        
                for(j=0;j<2;j++) {
-                       addTemplateRow(&template,"selfLoop");
-                       setTemplateValueInt(&template, "selfLoop.CNT", ++cnt);
-                       setTemplateValueString(&template, "selfLoop.NODE", "inner");
+                       addTemplateRow(tinstance,"selfLoop");
+                       setTemplateValueInt(tinstance, "selfLoop.CNT", ++cnt);
+                       setTemplateValueString(tinstance, "selfLoop.NODE", "inner");
                        if ( i==1 && j==0 ) {
-                               addTemplateRow(&template,"selfLoop.oneloop");
-                               setTemplateValueInt(&template, "selfLoop.oneloop.CNT", ++cnt);
-                               setTemplateValueString(&template, "selfLoop.oneloop.NODE", "subloop3");
+                               addTemplateRow(tinstance,"selfLoop.oneloop");
+                               setTemplateValueInt(tinstance, "selfLoop.oneloop.CNT", ++cnt);
+                               setTemplateValueString(tinstance, "selfLoop.oneloop.NODE", "subloop3");
                        }
                        if (i==2 && j==1) {
-                               addTemplateNestedLoop(&template, "selfLoop");
+                               addTemplateNestedLoop(tinstance, "selfLoop");
                                for(k=0;k<4;k++) {
-                                       addTemplateRow(&template,"selfLoop");
-                                       setTemplateValueInt(&template, "selfLoop.CNT", ++cnt);
-                                       setTemplateValueString(&template, "selfLoop.NODE", "innerst");
+                                       addTemplateRow(tinstance,"selfLoop");
+                                       setTemplateValueInt(tinstance, "selfLoop.CNT", ++cnt);
+                                       setTemplateValueString(tinstance, "selfLoop.NODE", "innerst");
                                        if ( k==2 ) {
-                                               addTemplateRow(&template,"selfLoop.oneloop");
-                                               setTemplateValueInt(&template, "selfLoop.oneloop.CNT", ++cnt);
-                                               setTemplateValueString(&template, "selfLoop.oneloop.NODE", "subloop4");
+                                               addTemplateRow(tinstance,"selfLoop.oneloop");
+                                               setTemplateValueInt(tinstance, "selfLoop.oneloop.CNT", ++cnt);
+                                               setTemplateValueString(tinstance, "selfLoop.oneloop.NODE", "subloop4");
                                        }
                                }
-                               returnTemplateNestedLoop(&template, "selfLoop");
+                               returnTemplateNestedLoop(tinstance, "selfLoop");
                        }
                }
        
 
-               returnTemplateNestedLoop(&template, "selfLoop");
+               returnTemplateNestedLoop(tinstance, "selfLoop");
        }
 
        fputs("================================================\n", stdout);
-       printTemplate( &template );
+       printTemplate( tinstance );
 
 
-       resetTemplate(&template);
        freeTemplate(&template);
 
        return 0;