case ConstNode:
case VariableNode:
case TextNode:
+ case NestNode:
break;
default:
tlog(TL_CRIT|TL_EXIT, "unknown node type: %d", (*node)->type);
* copy special flags to support new inform loopParentNode
*/
pdata->flags |= flags & TND__SPECIALMASK;
-
- if ( flags & ( TND___FIRST | TND___LAST | TND___ODD | TND___EVEN ) )
- pdata->type = valueBool;
- else if ( flags & (TND___COUNTER | TND___SIZE) )
- pdata->type = valueInt;
- else
- pdata->type = valuePointer;
+ pdata->type = valuePointer;
loopParentNode->nodeData.loop.listVarValues =
GListPush( loopParentNode->nodeData.loop.listVarValues, pdata );
SFSAdd(&tmpl->variables, &in);
- if ( loopParentNode )
+ if ( loopParentNode ) {
loopParentNode->nodeData.loop.childrenLoop =
GListPush( loopParentNode->nodeData.loop.childrenLoop, node );
+ if ( loopParentNode->nodeData.loop.selfNode )
+ loopParentNode->nodeData.loop.selfNode->nodeData.nest.childrenLoopAfterSelf =
+ GListPush( loopParentNode->nodeData.loop.selfNode->nodeData.nest.childrenLoopAfterSelf, node );
+ }
+
return 0;
}
if ( addLoop( tmpl, node, loopParentNode ) )
return 1;
break;
+ case NestNode:
+ node->nodeData.nest.loop = loopParentNode;
+ if ( loopParentNode ) {
+ if ( loopParentNode->nodeData.loop.selfNode )
+ tlog(TL_WARN,"Loop '%s' has duplicated nested call", node->nodeData.loop.varName);
+ else
+ loopParentNode->nodeData.loop.selfNode = node;
+ } else
+ tlog(TL_WARN,"SELF tag without loop");
+ break;
case ConditionNode:
if ( compileTree(tmpl, node->nodeData.condition.expressionNode, loopParentNode) )
return 1;
switch (node->type) {
case LoopNode:
freeNode( node->nodeData.loop.bodyNode );
+ freeNode( node->nodeData.loop.selfNode );
GListFree( node->nodeData.loop.childrenLoop );
GListFree( node->nodeData.loop.listVarValues );
freeNode( GLCELL_DATA(cell) );
GListFree( node->nodeData.expression.argsNode );
break;
+ case NestNode:
+ GListFree( node->nodeData.nest.childrenLoopAfterSelf );
+ break;
case VariableNode:
case IncludeNode:
case TextNode:
static void
newLoopInstance( Template tmpl, TemplateNode node ) {
+ LoopInstance upper = NULL;
+
+ if ( node->nodeData.loop.currentInstance )
+ upper = node->nodeData.loop.currentInstance->upperInstance;
+
+ node->nodeData.loop.currentInstance =
+ mc0alloc(tmpl->templateContext, sizeof(LoopInstanceData) );
+ node->nodeData.loop.currentInstance->upperInstance = upper;
+
node->nodeData.loop.listInstance = GListPush(
node->nodeData.loop.listInstance,
- mc0alloc(tmpl->templateContext, sizeof(LoopInstanceData) ) );
+ node->nodeData.loop.currentInstance );
+
+ node->nodeData.loop.lastRow = NULL;
}
int
-addTemplateRow( Template tmpl, char * key ) {
+addTemplateRow( Template tmpl, char * key) {
TemplateNode *pnode, node;
char *lkey = strlower(mcstrdup(tmpl->templateContext, key));
GListCell *cell;
- VariableValue varvals;
int i=0, nvar;
- LoopInstance instance;
+ LoopRow rowData;
pnode = SFSFindData(&tmpl->variables, lkey, 0);
mcfree(lkey);
GListForeach( cell, node->nodeData.loop.childrenLoop )
newLoopInstance( tmpl, GLCELL_DATA(cell) );
- varvals = mcalloc( tmpl->templateContext, sizeof(VariableValueData) * nvar );
+ node->nodeData.loop.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);
- vv->value.ptrValue = varvals + i;
- varvals[i].flags = 0;
+ vv->value.ptrValue = rowData->varvals + i;
+ rowData->varvals[i].flags = 0;
i++;
}
- instance = GLCELL_DATA(GLIST_TAIL(node->nodeData.loop.listInstance));
+ node->nodeData.loop.currentInstance->nrow++;
+ node->nodeData.loop.currentInstance->rowValues =
+ GListPush( node->nodeData.loop.currentInstance->rowValues, rowData );
+
+ return TVAR_OK;
+}
+
+int
+addTemplateNestedLoop( Template tmpl, char * key) {
+ TemplateNode *pnode, node;
+ char *lkey = strlower(mcstrdup(tmpl->templateContext, key));
+ GListCell *cell;
+
+ pnode = SFSFindData(&tmpl->variables, lkey, 0);
+ mcfree(lkey);
+
+ if ( pnode == NULL )
+ return TVAR_NOTFOUND;
+
+ node = *pnode;
+
+ if ( node->type != LoopNode || node->nodeData.loop.selfNode == 0 )
+ return TVAR_FORBIDDEN;
+
+ if ( GLIST_LENGTH(node->nodeData.loop.listInstance) == 0 || node->nodeData.loop.lastRow == NULL )
+ return TVAR_NOROW;
+
+ GListForeach( cell, node->nodeData.loop.childrenLoop )
+ ((TemplateNode)GLCELL_DATA(cell))->nodeData.loop.lastRow = NULL;
+
+ node->nodeData.loop.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;
+
+ return TVAR_OK;
+}
+
+int
+returnTemplateNestedLoop( Template tmpl, char * key) {
+ TemplateNode *pnode, node;
+ char *lkey = strlower(mcstrdup(tmpl->templateContext, key));
+ GListCell *cell;
+
+ pnode = SFSFindData(&tmpl->variables, lkey, 0);
+ mcfree(lkey);
+
+ if ( pnode == NULL )
+ return TVAR_NOTFOUND;
- instance->nrow++;
- instance->rowValues = GListPush( instance->rowValues, varvals );
+ node = *pnode;
+
+ if ( node->type != LoopNode || node->nodeData.loop.selfNode == 0 )
+ return TVAR_FORBIDDEN;
+
+ if ( GLIST_LENGTH(node->nodeData.loop.listInstance) == 0 )
+ return TVAR_NOROW;
+
+ if ( node->nodeData.loop.currentInstance == NULL )
+ return TVAR_NOROW;
+
+ GListForeach( cell, node->nodeData.loop.childrenLoop )
+ ((TemplateNode)GLCELL_DATA(cell))->nodeData.loop.lastRow = NULL;
+
+ node->nodeData.loop.currentInstance = node->nodeData.loop.currentInstance->upperInstance;
+ node->nodeData.loop.lastRow = NULL;
return TVAR_OK;
+
}
static VariableValueData storage;
case ConditionNode:
case CollectionNode:
case PrintNode:
+ case NestNode:
tlog(TL_CRIT|TL_EXIT, "Unexpected node type: %d", node->type);
break;
default:
}
static void
-printNode( Template tmpl, TemplateNode node ) {
- GListCell *cell;
+printNode( Template tmpl, TemplateNode node, LoopInstance loopInstance ) {
+ GListCell *cell;
VariableValue value;
+ int i;
if (!node)
return;
switch (node->type) {
case LoopNode:
{
- GListCell *cell = GListShift( node->nodeData.loop.listInstance );
+ GListCell *cell;
LoopInstance instance;
- int i;
- if ( cell == NULL )
- return;
+ if ( loopInstance ) {
+ instance = loopInstance;
+ } else {
+ cell = GListShift( node->nodeData.loop.listInstance );
+ if ( cell == NULL )
+ return;
- instance = GLCELL_DATA(cell);
- GListFreeCell( node->nodeData.loop.listInstance, cell );
+ instance = GLCELL_DATA(cell);
+ GListFreeCell( node->nodeData.loop.listInstance, cell );
+ }
for(i=0; i<instance->nrow;i++) {
- VariableValue varvals;
+ LoopRow rowData;
int j = 0;
+ VariableValue realValue;
cell = GListShift( instance->rowValues );
- varvals = GLCELL_DATA(cell);
+ rowData = GLCELL_DATA(cell);
GListFreeCell( instance->rowValues, cell );
GListForeach( cell, node->nodeData.loop.listVarValues ) {
value = (VariableValue)GLCELL_DATA(cell);
+ tassert( value->type == valuePointer );
+ realValue = value->value.ptrValue = rowData->varvals+j;
+
if ( value->flags & TND___FIRST ) {
+ realValue->type = valueInt;
if ( i==0 ) {
- value->flags |= TND_DEFINED;
- value->value.intValue = 1;
+ realValue->flags |= TND_DEFINED;
+ realValue->value.intValue = 1;
} else {
- value->flags &= ~TND_DEFINED;
- value->value.intValue = 0;
+ realValue->flags &= ~TND_DEFINED;
+ realValue->value.intValue = 0;
}
} else if ( value->flags & TND___LAST ) {
+ realValue->type = valueInt;
if ( i==instance->nrow - 1 ) {
- value->flags |= TND_DEFINED;
- value->value.intValue = 1;
+ realValue->flags |= TND_DEFINED;
+ realValue->value.intValue = 1;
} else {
- value->flags &= ~TND_DEFINED;
- value->value.intValue = 0;
+ realValue->flags &= ~TND_DEFINED;
+ realValue->value.intValue = 0;
}
} else if ( value->flags & TND___COUNTER ) {
- value->flags |= TND_DEFINED;
- value->value.intValue = i+1;
+ realValue->type = valueInt;
+ realValue->flags |= TND_DEFINED;
+ realValue->value.intValue = i+1;
} else if ( value->flags & TND___SIZE ) {
- value->flags |= TND_DEFINED;
- value->value.intValue = instance->nrow;
+ realValue->type = valueInt;
+ realValue->flags |= TND_DEFINED;
+ realValue->value.intValue = instance->nrow;
} else if ( value->flags & TND___ODD ) {
- value->flags |= TND_DEFINED;
- value->value.boolValue = (i%2) ? 0 : 1 ;
+ realValue->type = valueBool;
+ realValue->flags |= TND_DEFINED;
+ realValue->value.boolValue = (i%2) ? 0 : 1 ;
} else if ( value->flags & TND___EVEN ) {
- value->flags |= TND_DEFINED;
- value->value.boolValue = (i%2) ? 1 : 0 ;
- } else {
- tassert( value->type == valuePointer );
- value->value.ptrValue = varvals+j;
+ realValue->type = valueBool;
+ realValue->flags |= TND_DEFINED;
+ realValue->value.boolValue = (i%2) ? 1 : 0 ;
}
j++;
}
- printNode( tmpl, node->nodeData.loop.bodyNode );
+
+ if ( node->nodeData.loop.selfNode )
+ node->nodeData.loop.selfNode->nodeData.nest.savedRowData = rowData;
+
+ printNode( tmpl, node->nodeData.loop.bodyNode, NULL );
}
GListFree( instance->rowValues );
}
break;
+ case NestNode:
+ if ( node->nodeData.nest.loop && node->nodeData.nest.savedRowData ) {
+ LoopRow savedRowData = node->nodeData.nest.savedRowData; /* save current row */
+ LoopInstance *savedChildrenInstance = NULL;
+
+ /*
+ * Save child's instances for current loop
+ */
+ if ( GLIST_LENGTH(node->nodeData.nest.childrenLoopAfterSelf) ) {
+ savedChildrenInstance = mcalloc(tmpl->templateContext, sizeof(LoopInstance) *
+ GLIST_LENGTH(node->nodeData.nest.childrenLoopAfterSelf));
+
+ i=0;
+ GListForeach( cell, node->nodeData.nest.childrenLoopAfterSelf) {
+ TemplateNode chld = GLCELL_DATA(cell);
+ GListCell *cellInstance = GListShift( chld->nodeData.loop.listInstance );
+
+ if ( cellInstance == NULL )
+ savedChildrenInstance[i++] = NULL;
+ else {
+ savedChildrenInstance[i++] = GLCELL_DATA(cellInstance);
+ GListFreeCell( chld->nodeData.loop.listInstance, cellInstance );
+ }
+ }
+ }
+
+ printNode( tmpl, node->nodeData.nest.loop, savedRowData->nestedInstance );
+
+ /*
+ * Restore saved datas
+ */
+ i=0;
+ GListForeach( cell, node->nodeData.nest.loop->nodeData.loop.listVarValues ) {
+ ((VariableValue)GLCELL_DATA(cell))->value.ptrValue = savedRowData->varvals + i;
+ i++;
+ }
+
+ if ( GLIST_LENGTH(node->nodeData.nest.childrenLoopAfterSelf) ) {
+ i=0;
+ GListForeach( cell, node->nodeData.nest.childrenLoopAfterSelf) {
+ TemplateNode chld = GLCELL_DATA(cell);
+
+ if ( savedChildrenInstance[i] )
+ GListUnshift( chld->nodeData.loop.listInstance, savedChildrenInstance[i]);
+ i++;
+ }
+ }
+ }
+ break;
case ConditionNode:
value = executeExpression( tmpl, node->nodeData.condition.expressionNode );
if ( isVariable(value) )
- printNode( tmpl, node->nodeData.condition.ifNode );
+ printNode( tmpl, node->nodeData.condition.ifNode, loopInstance );
else
- printNode( tmpl, node->nodeData.condition.elseNode );
+ printNode( tmpl, node->nodeData.condition.elseNode, loopInstance );
break;
case CollectionNode:
GListForeach( cell, node->nodeData.children )
- printNode( tmpl, (TemplateNode)GLCELL_DATA(cell) );
+ printNode( tmpl, (TemplateNode)GLCELL_DATA(cell), loopInstance );
break;
case PrintNode:
value = executeExpression( tmpl, node->nodeData.condition.expressionNode );
if (!tmpl->printString)
return 1;
- printNode(tmpl, tmpl->tree);
+ printNode(tmpl, tmpl->tree, NULL);
return 0;
}
case ConstNode:
printf("ConstNode\n");
break;
+ case NestNode:
+ printf("NestNode\n");
+ break;
default:
tlog(TL_CRIT|TL_EXIT, "unknown node type: %d", node->type);
}
MemoryContext *base;
char *name = NULL;
TemplateData template;
- int i;
+ int i,j,k;
+ int cnt=0;
executeFunctionDescData funcs[] = {
{"callcounter", 0, localCounter},
{NULL,0,NULL}
addTemplateRow(&template, "outerLoop.innerLoop");
setTemplateValueString(&template, "outerLoop.innerLoop.camenty", "Again 1");
+ for(i=0;i<3;i++) {
+ addTemplateRow(&template,"selfLoop");
+ setTemplateValueInt(&template, "selfLoop.CNT", ++cnt);
+ setTemplateValueString(&template, "selfLoop.NODE", "outer");
+
+ if (i<1) {
+ addTemplateRow(&template,"selfLoop.oneloop");
+ setTemplateValueInt(&template, "selfLoop.oneloop.CNT", ++cnt);
+ setTemplateValueString(&template, "selfLoop.oneloop.NODE", "subloop1");
+ }
+ if (i<2) {
+ addTemplateRow(&template,"selfLoop.oneloop");
+ setTemplateValueInt(&template, "selfLoop.oneloop.CNT", ++cnt);
+ setTemplateValueString(&template, "selfLoop.oneloop.NODE", "subloop2");
+ }
+
+ addTemplateNestedLoop(&template, "selfLoop");
+
+ for(j=0;j<2;j++) {
+ addTemplateRow(&template,"selfLoop");
+ setTemplateValueInt(&template, "selfLoop.CNT", ++cnt);
+ setTemplateValueString(&template, "selfLoop.NODE", "inner");
+ if ( i==1 && j==0 ) {
+ addTemplateRow(&template,"selfLoop.oneloop");
+ setTemplateValueInt(&template, "selfLoop.oneloop.CNT", ++cnt);
+ setTemplateValueString(&template, "selfLoop.oneloop.NODE", "subloop3");
+ }
+ if (i==2 && j==1) {
+ addTemplateNestedLoop(&template, "selfLoop");
+ for(k=0;k<4;k++) {
+ addTemplateRow(&template,"selfLoop");
+ setTemplateValueInt(&template, "selfLoop.CNT", ++cnt);
+ setTemplateValueString(&template, "selfLoop.NODE", "innerst");
+ if ( k==2 ) {
+ addTemplateRow(&template,"selfLoop.oneloop");
+ setTemplateValueInt(&template, "selfLoop.oneloop.CNT", ++cnt);
+ setTemplateValueString(&template, "selfLoop.oneloop.NODE", "subloop4");
+ }
+ }
+ returnTemplateNestedLoop(&template, "selfLoop");
+ }
+ }
+
+
+ returnTemplateNestedLoop(&template, "selfLoop");
+ }
+
fputs("================================================\n", stdout);
printTemplate( &template );
+
resetTemplate(&template);
freeTemplate(&template);