Exemplo n.º 1
0
// Removes one element from the dictionary
bool
AVLDictionary::removeElement(KeyType key)
{
	if (debug)
	{
		printf("------------------------------------\n");
		printf("removeElement(\"%s\")\n",  key);
		printf("---------- Before -----------------\n");
		printNode("", root, 0);
	}

	AVLNode *node;
	node = findNode(key);
	
	if (node == NULL)
	{
     	return false;
    }
   
	if (node->left == NULL && node->right == NULL)
	{
		if ( node == node->parent->left)
		{
			node->parent->left = NULL;
		}
		else
		{
			node->parent->right = NULL;
		}

		AVLNode *m;
		m = node->parent;
		
		while(m != NULL)
		{
			int maxheight = 0;
			if(m->left != NULL)
			{
				maxheight = m->left->height;
			}
			if (m->right != NULL && maxheight < m->right->height)
			{
				maxheight = m->right->height;
			}
			m->height = maxheight +1;
			m = m->parent;
		}

		restructure(node->parent);

		delete node;
    }
	else if (node->left == NULL)
	{
	    AVLNode temp;
   	
     	temp.height = node->height;
     	strcpy((char*)temp.key, node->key);
     	temp.data = node->data;
      
     	node->height = node->right->height;
     	strcpy((char*)node->key, node->right->key);
     	node->data = node->right->data;
 
     	node->right->height = temp.height;
     	strcpy((char*)node->right->key, temp.key);
     	node->right->data = temp.data;
   
     	delete node->right;
   
     	node->right = NULL;   
   
     	AVLNode *m = node->parent;
     	while(m != NULL)
		{
     		int maxheight = 0;
     		if(m->left != NULL)
			{
     			maxheight = m->left->height;
     		}
     		if (m->right != NULL && maxheight < m->right->height)
			{
     			maxheight = m->right->height;
     		}
     		m->height = maxheight +1;
     		m = m->parent;
   
     	}
   
     	restructure(node);
    }
	else if (node->right == NULL)
	{
     	AVLNode temp;
   
     	temp.height = node->height;
     	strcpy((char*)temp.key, node->key);
     	temp.data = node->data;
 
     	node->height = node->left->height;
     	strcpy((char*)node->key, node->left->key);
     	node->data = node->left->data;
   
     	node->left->height = temp.height;
     	strcpy((char*)node->left->key, temp.key);
     	node->left->data = temp.data;
   
     	delete node->left;
   
     	node->left = NULL;   	
   
     	AVLNode *m;
		m = node->parent;
		
     	while(m != NULL)
		{
     		int maxheight = 0;
     		if( m->left != NULL)
			{
     			maxheight = m->left->height;
     		}
     		if (m->right != NULL && maxheight < m->right->height)
			{
     			maxheight = m->right->height;
     		}
     		m->height = maxheight +1;
     		m = m->parent;
   
     	}
   
     	restructure(node);
    }
	else
	{
		AVLNode *replacement;   
		replacement = node->left;
		
     	if (replacement->right == NULL)
		{
     		replacement = node->right;
     		while(replacement->left != NULL)
			{
     			replacement = replacement->left;
     		}
     	}
		else
		{
			while (replacement->right != NULL)
			{
     			replacement = replacement->right;
     		}
   
     	}
		
		AVLNode temp;
       
		temp.height = node->height;
     	strcpy((char*)temp.key, node->key);
     	temp.data = node->data;
   
     	node->height = replacement->height;
     	strcpy((char*)node->key, replacement->key);
     	node->data = replacement->data;
 	
     	replacement->height = temp.height;
     	strcpy((char*)replacement->key, temp.key);
     	replacement->data = temp.data;
   	
     	AVLNode *n;
		n = replacement->parent;
		
     	if (n != NULL)
		{
			if (replacement == n->left)
			{
     			n->left = NULL;   
     			delete replacement;
     		}
			else
			{
     			n->right = NULL;
     			delete replacement;
     		}
   
			AVLNode *m = n;
			while(m != NULL)
			{
				int maxheight = 0;
				if(m->left != NULL)
				{
					maxheight = m->left->height;
				}
				if (m->right != NULL && maxheight < m->right->height)
				{
					maxheight = m->right->height;
				}
				m->height = maxheight +1;
				m = m->parent;   
			}
	   
			restructure(n);
		}
	}
	
	nElements--;
	
	if (debug)
	{
		printf("---------- After -----------------\n");
		printNode("", root, 0);

		checkRecursive(root);
	}
	
	return true;
}
Exemplo n.º 2
0
// Test the split function
bool testBuild(){
    // Test the stopping criterion (#p=7, k=8).
    bool result = true;

    int N = 7;
    int k = 8;

    value_type x[7] = {12,45,34,90,34,23,56};
    value_type y[7] = {16,82,72,2,45,89,52};
    value_type mass[7] = {1, 2, 3, 4, 5, 6, 7};

    value_type xsorted[7];
    value_type ysorted[7];
    value_type mass_sorted[7];

    // Allocate the tree array containing all the nodes
    int maxNodes = (int) std::min((float)8 * N / k, (float)pow(4, depthtree));
    Node* tree = new Node[maxNodes];

    build(x, y, mass, N, k, xsorted, ysorted, mass_sorted, tree, depthtree);

    // Test the resulting tree
    if (tree[0].child_id != -1) {
        std::cout << "Test of stopping criterion failed, the root node is not a leaf node." << std::endl;
        std::cout << "root.child_id = " << tree[0].child_id << std::endl;
        result = false;
    } else {
        std::cout << "Root node is an empty node => The test for the stopping criterion passed." << std::endl;
    }


    // Test building the tree for k=2
    N=14;
    k=2;

    // Create new particles
    value_type x2[14] = {12,45,34,90,34,23,56,3,76,54,32,56,45,90};
    value_type y2[14] = {16,82,72,2,45,89,52,54,12,12,12,43,2,89};
    value_type mass2[14] = {1, 0.2, 3, 12, 5, 6, 3, 13, 9, 2, 11, 12, 3, 14};

    // Allocate arrays for sorted particles
    value_type xsorted2[14];
    value_type ysorted2[14];
    value_type mass_sorted2[14];

    // Compute new maxNodes for treesize
    int maxNodes2 = (int) std::min((float)8 * N / k, (float)pow(4, depthtree));

    Node* tree2 = new Node[maxNodes2];

    std::cout << "Testing the build() function for a tree with N=14, k=2 and depth=16." << std::endl;
    build(x2, y2, mass2, N, k, xsorted2, ysorted2, mass_sorted2, tree2, depthtree);

    // Test the resulting tree
    for (int i = 0; i < maxNodes2; ++i) {
        printNode(tree2[i]);
    }

    if (result) {
        std::cout << "Check the created nodes to validate the function." << std::endl;
    }

    delete[] tree;
    delete[] tree2;
    return result;
}
Exemplo n.º 3
0
// Add a record to the dictionary. Returns false if key already exists
bool
AVLDictionary::addRecord( KeyType key, DataType record)
{
	if (debug)
	{
		printf("------------------------------------\n");
		printf("addRecord(\"%s\",%d)\n",  key, record);
		printf("---------- Before -----------------\n");
		printNode("", root, 0);
	}
	
	AVLNode *n;
	n = new AVLNode();
	
    n->key = key;
    n->data = record;
    n->height = 1;
    n->left = NULL;
    n->right = NULL;
    n->parent = NULL;

    if(root == NULL)
	{
        root = n;
		nElements++;
		
        return true;
    }

    AVLNode *curr;
	curr = root;
	
    AVLNode *prev;
	prev = NULL;
	
    while(curr != NULL)
	{
        prev = curr;
        if (strcmp(key, curr->key) < 0)
		{
            curr = curr->left;
        }
        else if (strcmp(key, curr->key) > 0)
		{
            curr = curr->right;
        }
        else
		{
            curr->data = record;
            return false;
        }
    }

    if (strcmp(key, prev->key) < 0)
	{
        prev->left = n;
    }
    else
	{
        prev->right = n;
    }

    n->parent = prev;

    AVLNode *m;
	m = n->parent;
	
    while(m != NULL)
	{
        int maxheight = 0;
        if(m->left != NULL)
            maxheight = m->left->height;
        if(m->right != NULL && maxheight < m->right->height)
            maxheight = m->right->height;
        m->height = 1+maxheight;
        m = m->parent;
    }

	if (debug)
	{
		printf("---------- Before Restructure -----------------\n");
		printNode("", root, 0);
	}
	
	restructure(n);

	if (debug)
	{
		checkRecursive(root);
		
		printf("---------- After Restructure -----------------\n");
		printNode("", root, 0);
	}
	
	nElements++;
		
	return true;
}
Exemplo n.º 4
0
void MyList::printNode(shared_ptr<Node> node)
{
    if (!node) return;
    printNode(node->pNext);
    cout << node->value << ' ' ;
}
Exemplo n.º 5
0
std::ostream& operator<<(std::ostream & out, const Node & n) {
  return printNode(out, 0, &n, nullptr);
}
Exemplo n.º 6
0
void
AVLDictionary::print()
{
	printNode("ROOT", root, 0);
}
Exemplo n.º 7
0
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PropertiesSet::print()
{
  cout << size() << endl;
  printNode(myRoot);  // FIXME - print out internal properties as well
}
Exemplo n.º 8
0
void AVL::print(PrintKeyFunc func) const{

  printNode(d_top_p,func);

}
Exemplo n.º 9
0
void printTree(Tree tree) {
  printNode(*tree,0);
}
Exemplo n.º 10
0
SEXP printNode(hpdRFnode *tree, int depth, int max_depth, SEXP classes)
{
#define tab     for(int i = 0; i < depth; i++) printf("\t")
  
  if(depth > max_depth)
    {
      tab;
	printf("Ommitting subtree\n");
	return R_NilValue;
    }
  
    double prediction = tree->prediction;
    tab;
    int index = (int) prediction;
    if(classes != R_NilValue && TYPEOF(classes) == STRSXP && 
       index >= 0 && index < length(classes))
      printf("<prediction> %s </prediction>\n",
	     CHAR(STRING_ELT(classes,(int)prediction)));
    else
      printf("<prediction> %f </prediction>\n", prediction);
    
    tab;
    printf("<deviance> %f </deviance>\n", tree->deviance);
    tab;
    printf("<complexity> %f </complexity>\n", tree->complexity);

    
    double* split_criteria = tree->split_criteria;
    int split_var=tree->split_variable;
    if(split_criteria != NULL)
      {
	tab;
	printf("<split_criteria> ");
	for(int i = 0; i < tree->split_criteria_length; i++)
	  printf("%f ",split_criteria[i]);
	printf("</split_criteria>\n");
	tab;
	printf("<split variable> %d </split variable>\n", split_var);
      }

    if(tree->additional_info)
      {

	tab;
	printf("leaf_id: %d\n", tree->additional_info->leafID);
	tab;
	printf("num_obs: %d\n", tree->additional_info->num_obs);

	
	tab;
	printf("indices: ");
	for(int i = 0; i < tree->additional_info->num_obs; i++)
	  printf("%d ", tree->additional_info->indices[i]);
	printf("\n");
	/*
	tab;
	printf("weights: ");
	for(int i = 0; i < tree->additional_info->num_obs; i++)
	  printf("%f ", tree->additional_info->weights[i]);
	printf("\n");
	*/
      }
    
    if(tree->left != NULL)
      {
	tab;
	printf("<Left Child Node>\n");
	printNode(tree->left, 
		  depth+1,max_depth,classes);
	tab;
	printf("</Left Child Node>\n");
      }
    if(tree->right != NULL)
      {
	tab;
	printf("<Right Child Node>\n");
	printNode(tree->right, 
		  depth+1,max_depth,classes);
	tab;
	printf("</Right Child Node>\n");
      }
    
    return R_NilValue;
  }
void
printNode(int id) {
  printNode(aid(id));
}
Exemplo n.º 12
0
void ShinyPrintANode(char* output, const ShinyNode *a_node, const ShinyNode *a_root) {
	float fTicksToPc = 100.0f / a_root->data.childTicks.avg;
	output = printNode(output, a_node, fTicksToPc);
	(*output++) = '\0';
}
Exemplo n.º 13
0
static void
printAdtree (adtree_t* adtreePtr)
{
    printNode(adtreePtr->rootNodePtr);
}
Exemplo n.º 14
0
int main()
{
    Index IndexManager;
    index_node_t insertNode[10], res;
    insertNode[0].value = "1100012957";
    insertNode[0].offset = 16;
    insertNode[1].value = "1100012950";
    insertNode[1].offset = 0;
    insertNode[2].value = "1100099999";
    insertNode[2].offset = 8;

    attr_t attr;
    attr.name = "学号";
    attr.isPrimary = true;
    attr.length = 8;
    attr.type = INT;

    condition_tree_t *cNode = new condition_tree_t;
    cNode->leftOperand = "学号";

    // 建立索引
    cout << "---建立索引:" << endl;
    IndexManager.createIndex("Persons", "学号", attr);
    cout << endl;

    // 插入索引项
    cout << "---插入索引项:" << endl;
    IndexManager.insertIndex("Persons", "学号", insertNode[0]);
    IndexManager.insertIndex("Persons", "学号", insertNode[1]);
    IndexManager.insertIndex("Persons", "学号", insertNode[2]);
    cout << endl;

    IndexManager.debugPrint("Persons", "学号");

    // 查找索引项
    cout << "---查找索引项:" << endl;

    cNode->opName = EQ;
    cNode->rightOperand = "1100012957";
    IndexManager.selectIndex("Persons", cNode, &res);
    printNode(&res);

    cNode->opName = NE;
    cNode->rightOperand = "1100012957";
    IndexManager.selectIndex("Persons", cNode, &res);
    printNode(&res);

    cNode->opName = GT;
    cNode->rightOperand = "1100012957";
    IndexManager.selectIndex("Persons", cNode, &res);
    printNode(&res);

    cNode->opName = LT;
    cNode->rightOperand = "1100099999";
    IndexManager.selectIndex("Persons", cNode, &res);
    printNode(&res);

    cNode->opName = GTE;
    cNode->rightOperand = "1100012957";
    IndexManager.selectIndex("Persons", cNode, &res);
    printNode(&res);

    cNode->opName = LTE;
    cNode->rightOperand = "1100012957";
    IndexManager.selectIndex("Persons", cNode, &res);
    printNode(&res);
    cout << endl;

    // 删除索引项
    cout << "---删除索引项:" << endl;
    IndexManager.deleteIndex("Persons", "学号", "1100012957");
    cout << endl;

    // 更新索引项
    cout << "---更新索引项:" << endl;
    IndexManager.updateIndex("Persons", "学号", "1100099999", "1100199999");
    cout << endl;

    IndexManager.debugPrint("Persons", "学号");

    // 查找索引项
    cout << "---查找索引项:" << endl;
    cNode->opName = GTE;
    cNode->rightOperand = "1100012949";
    IndexManager.selectIndex("Persons", cNode, &res);
    printNode(&res);
    cout << endl;

    // 恢复一条索引
    IndexManager.insertIndex("Persons", "学号", insertNode[2]);
    
    IndexManager.debugPrint("Persons", "学号");

    // OR 合并索引列表
    index_node_t ORres, ORres1, ORres2;
    cout << "---OR 合并索引列表:" << endl;

    cNode->opName = GTE;
    cNode->rightOperand = "1100012999";
    IndexManager.selectIndex("Persons", cNode, &ORres);
    printNode(&ORres);

    cNode->opName = LTE;
    cNode->rightOperand = "1100012950";
    IndexManager.selectIndex("Persons", cNode, &ORres1);
    printNode(&ORres1);

    index_node_t **tmp = new index_node_t * [2];
    tmp[0] = &ORres;
    tmp[1] = &ORres1; 
    IndexManager.mergeIndexOR(tmp, 2, &ORres2);
    printNode(&ORres2);
    delete [] tmp;
    cout << endl;

    // 恢复一条索引
    IndexManager.updateIndex("Persons", "学号", "1100012950", "1100012957");

    // AND 合并索引列表
    index_node_t ANDres, ANDres1, ANDres2;
    cout << "---AND 合并索引列表:" << endl;

    cNode->opName = GTE;
    cNode->rightOperand = "1100012957";
    IndexManager.selectIndex("Persons", cNode, &ANDres);
    printNode(&ANDres);

    cNode->opName = EQ;
    cNode->rightOperand = "1100012957";
    IndexManager.selectIndex("Persons", cNode, &ANDres1);
    printNode(&ANDres1);

    tmp = new index_node_t * [2];
    tmp[0] = &ANDres;
    tmp[1] = &ANDres1; 
    IndexManager.mergeIndexAND(tmp, 2, &ANDres2);
    printNode(&ANDres2);
    delete [] tmp;
    cout << endl;

    // 尝试搜索具有相同关键码的多个索引项
    index_node_t selRes;
    cout << "---搜索具有相同关键码的多个索引项:" << endl;
    IndexManager.insertIndex("Persons", "学号", insertNode[2]);
    IndexManager.insertIndex("Persons", "学号", insertNode[2]);
    IndexManager.insertIndex("Persons", "学号", insertNode[2]);

    cNode->opName = EQ;
    cNode->rightOperand = "1100099999";
    IndexManager.selectIndex("Persons", cNode, &selRes);
    printNode(&selRes);

    // 删除一条索引后再搜索
    IndexManager.deleteIndex("Persons", "学号", "1100099999");

    IndexManager.debugPrint("Persons", "学号");

    cNode->opName = GT;
    cNode->rightOperand = "1100012956";
    IndexManager.selectIndex("Persons", cNode, &selRes);
    printNode(&selRes);
    cout << endl;

    // 更新索引项
    cout << "---更新索引项:" << endl;
    IndexManager.updateIndex("Persons", "学号", "1100099999", "1100199999");
    cout << endl;

    IndexManager.debugPrint("Persons", "学号");

    return 0;
}
Exemplo n.º 15
0
void recursivePrintNode(Node * node){
    printNode(node);
    for(unsigned int i = 0; i < node->size; i++){
        recursivePrintNode(node->children[i]);
    }
}
Exemplo n.º 16
0
// Tree printing
void FlatUCBMod::printTree(int turnCounter, int player, Node* rootNodePtr, int moveHistorySize, int sims)
{
	std::string fileName = std::to_string(turnCounter) + "_" + std::to_string(player) + "_" + std::to_string(moveHistorySize) + "_" + std::to_string(sims) + "uctTree.gv";
	remove(fileName.c_str());
	std::ofstream file;
	file.open(fileName, std::ios::app);
	std::string text = "digraph ucttree{\r\n size = \"10000000000!, 1000000000\";\r\n ratio = \"expand\";\r\n node[color = lightblue2, style = filled];";
	file << text << std::endl;
	printNode(rootNodePtr, file);
	text = "\r\n }";
	file << text << std::endl;
	file.close();


	std::ofstream file2;
	file2.open("treeDepth.txt", std::ios::app);

	int turnsCount[50];
	for (int i = 0; i < 50; i++)
		turnsCount[i] = 0;

	for (int i = 0; i < handedOutNodes; i++)
	{
		turnsCount[nodeAllocationPtr[i].currentState.turnCounter]++;
	}

	file2 << "Handedoutnodes:" + std::to_string(handedOutNodes) << std::endl;
	for (int i = 0; i < 50; i++)
		file2 << "Turn" + std::to_string(i) + ": " + std::to_string(turnsCount[i]) << std::endl;

	file2.close();


	std::ofstream file3;
	fileName = std::to_string(turnCounter) + "_" + std::to_string(moveHistorySize) + "strategy.gv";
	remove(fileName.c_str());
	file3.open(fileName, std::ios::app);
	text = "digraph strategy{\r\n size = \"10000000000!, 1000000000\";\r\n ratio = \"expand\";\r\n node[color = lightblue2, style = filled];";
	file3 << text << std::endl;

	Node* currentNode = rootNodePtr;
	while (currentNode->childrenPtrs.size() > 0)
	{
		text = "";

		// Find best child
		Node* currentBest = currentNode->childrenPtrs[0];
		for (std::vector<Node*>::iterator iterator = currentNode->childrenPtrs.begin(); iterator != currentNode->childrenPtrs.end(); ++iterator)
		{
			if ((*iterator)->visited > currentBest->visited)
				currentBest = (*iterator);
		}

		// Print self and best child


		// Append *tchu tchu*
		text += "\"";

		// Append id
		text += std::to_string(currentNode->id);

		// Append self
		text += " Type:" + std::to_string(currentNode->opt.type);
		text += CardManager::cardLookup[currentNode->opt.absoluteCardId].name;

		for (int index = 0; index < INSUPPLY; index++)
		{
			int cardsOfType = currentNode->currentState.playerStates[currentNode->playerPlaying].hand[index];
			if (cardsOfType > 0)
			{
				text += " " + CardManager::cardLookupByIndex[index].name + ":" + std::to_string(cardsOfType);
			}
		}

		// Append visited
		text += " Vis:" + std::to_string(currentNode->visited);

		// Append value
		text += " Val:" + std::to_string(currentNode->value);

		// Append currentplayer
		text += " Player:" + std::to_string(currentNode->playerPlaying);

		// Append turnCounter
		text += " Turn:" + std::to_string(currentNode->currentState.turnCounter);

		// Append *tchu tchu*
		text += "\"";

		// Append the arrow
		text += " -> ";

		// Append *tchu tchu*
		text += "\"";

		// Append child id
		text += std::to_string(currentBest->id);

		// Append child text
		text += " Type:" + std::to_string(currentBest->opt.type);
		text += CardManager::cardLookup[currentBest->opt.absoluteCardId].name;

		for (int index = 0; index < INSUPPLY; index++)
		{
			int cardsOfType = currentBest->currentState.playerStates[currentBest->playerPlaying].hand[index];
			if (cardsOfType > 0)
			{
				text += " " + CardManager::cardLookupByIndex[index].name + ":" + std::to_string(cardsOfType);
			}
		}

		// Append child visited
		text += " Vis:" + std::to_string(currentBest->visited);

		// Append child value
		text += " Val:" + std::to_string(currentBest->value);

		// Append child currentplayer
		text += " Player:" + std::to_string(currentBest->playerPlaying);

		// Append child turnCounter
		text += " Turn:" + std::to_string(currentBest->currentState.turnCounter);

		// Append *tchu tchu*
		text += "\";";

		text += "\r\n";



		file3 << text << std::endl;
		currentNode = currentBest;
	}

	text = "\r\n }";
	file3 << text << std::endl;
	file3.close();

}
Exemplo n.º 17
0
 void printTree(){
     std::cout << amount << " nodes in the tree" << std::endl;
     printNode(root);
 }
Exemplo n.º 18
0
void FlatUCBMod::printNode(Node* nodePtr, std::ofstream& file)
{
	nodePtr->printSelf(file);
	for (std::vector<Node*>::iterator it = nodePtr->childrenPtrs.begin(); it != nodePtr->childrenPtrs.end(); ++it)
		printNode(*it, file);
}
Exemplo n.º 19
0
void printTree(struct BSTree *tree) {
	 if (tree == 0) return;	 
	 printNode(tree->root);	 
}
Exemplo n.º 20
0
// pCFG_FWDataflow::runAnalysis invokes runAnalysis_pCFG
// Walks the pCFG to create dot representation
// Annotations used to match send/recv calls, process set names
// Transfer functions are only used to determine
//     1. NextState for a processSet
//     2. to block a particular processSet
//     3. Split a process set based on rank dependent condition
bool pCFGIterator::runAnalysis_pCFG(const Function& func, NodeState* state, pCFG_Checkpoint* chkpt)
{
    std::cout << "CLIENT RUN ANALYSIS PCFG\n";
    string indent="";
    DataflowNode funcCFGStart = cfgUtils::getFuncStartCFG(func.get_definition());
    DataflowNode funcCFGEnd = cfgUtils::getFuncEndCFG(func.get_definition());

    ostringstream funcNameAsString;
    funcNameAsString << "Function " << func.get_name().getString() << "()";   
    if(pCFGIteratorDebugLevel >= 1) {
        Dbg::enterFunc(funcNameAsString.str());
        Dbg::dbg << indent << "Entering : " << funcNameAsString.str() << endl;
    }

    // current pCFG node
    pCFGNode curNode;

    // currently active
    set<unsigned int> activePSets;
    // currently blocked
    set<unsigned int> blockedPSets;
    // currently resumed from blocked
    // skip transfer function
    set<unsigned int> releasedPSets;

    // psets requiring merge
    set<unsigned int> mergePSets;

    // end sets
    set<unsigned int> endPSets;

    // Not restarting from a checkpoint
    // start with single process set
    // initialize to start from top of function
    if(chkpt == NULL) {
        vector<DataflowNode> initDFNodes;
        initDFNodes.push_back(funcCFGStart);
        curNode.init(initDFNodes);
        activePSets.insert(0);

        // set up dot properties for initial node
        curNode.set_id(1);
//        curNode.set_dot_attr("blue");
        curNode.set_dot_attr(0);
        nodeouts << curNode.toDot() << endl;
        npcfgnodes = 1;
    }
    // restarting from chkpt
    else {
        curNode = chkpt->n;
        activePSets = chkpt->activePSets;
        blockedPSets = chkpt->blockedPSets;
        releasedPSets = chkpt->releasedPSets;
        Dbg::dbg << indent << "RESTARTING FROM CHKPT " << chkpt->str(indent+"    ") << endl;
    }

    // bool shouldMatch = false;
    bool movedPSet = false;

    // outer-loop
    // apply dataflow on all process sets
    // match send/recv when all process sets are blocked
    do
    {
        bool modified = false;

        // move until every pset is blocked
        // perform send/recv matching after this loop

        while(activePSets.size() > 0)
        {
            int curPSet;
            // The current process set is the next active one or the process set that 
            // performed the split from which we're restarting 
            // (the latter special condition is only needed to keep the output more readable)
            if(chkpt==NULL) {
                // pick in canonical order
                curPSet = *(activePSets.begin());
            }
            else {
                curPSet = chkpt->splitPSet;
            }

            printSubGraphInit(curPSet);
                                
            // If we're restarting, we don't need the checkpoint any more
            if(chkpt) {
                delete chkpt;
                chkpt = NULL;
            }
            // process the curPset until it is blocked
            while(1) {
                pair<set<pCFGNode>::iterator, bool> insertReturn = visitedPCFGNodes.insert(curNode);
                //bool firstTimeVisit = insertReturn.second;        // may be required

                // dataflow node corresponding to this pset
                const DataflowNode& dfNode = curNode.getCurNode(curPSet);
                // SgNode *sgn = dfNode.getNode();

                // get the state corresponding to this analysis
                // lattice information above/below
                // NodeState* state = pCFGState::getNodeState(func, curNode, this);
                // ROSE_ASSERT(state != NULL);
                NodeState* state = NULL;
                
                // We may need state information to decide if merge,split or blocked required
                //vector<Lattice*>& dfInfoAbove = state->getLatticeAboveMod (this);
                //vector<Lattice*>& dfInfoBelow = state->getLatticeBelowMod (this);

                // create descendant pcfg node
                // initalization happens as the analysis progresses
                // TODO: Use annotations to decide if the nod should be created
                pCFGNode descNode(curNode);

                //TODO: Check if need to merge
                // merge => two psets at same dataflow node &  same status
                // update modified =

                // if we resume from blocked state
                // 
                if(releasedPSets.erase(curPSet) > 0) {
                    descNode.advanceOut(curPSet);
                    descNode.set_id(++npcfgnodes);
//                    descNode.set_dot_attr("blue");
                    descNode.set_dot_attr(curPSet);                    
                    if(movedPSet) {
                        // do not update ancestor as it was set earlier for this pset
                        // reset the flag
                        movedPSet = false;                            
                    }
                    else {
                        descNode.updateAncsNode(curPSet, curNode);
                    }
                    modified = true;
                    //TODO: update lattice
                    //TODO: update modified if update lattice changes state
                }
                // regular pset
                // apply transfer function
                else {
                    // -------------------------------------------------------------------------
                    // Overwrite the Lattices below this node with the lattices above this node.
                    // The transfer function will then operate on these Lattices to produce the
                    // correct state below this node.
                                        
                    // The new information below this pCFGNode. Initially a copy of the above information
                    vector<Lattice*> dfInfoNewBelow;                                        
                                       
                    // Initialize dfInfoNewBelow to be the copy of the information above this node.
                    //    It will then get pushed through the transfer function before being unioned 
                    //    with and widened into the information below this node.
                    // for(vector<Lattice*>::const_iterator itA=dfInfoAbove.begin(); itA != dfInfoAbove.end(); itA++)
                    // {
                    //     if(pCFGIteratorDebugLevel >= 1) {
                    //         Dbg::dbg << indent << "    Pre-Transfer Above: Lattice "<<j<<": \n    "<<(*itA)->str("        ")<<endl;
                    //     }
                    //     dfInfoNewBelow.push_back((*itA)->copy());
                    // }

                    bool isSplitPSet = false;
                    bool isSplitPNode = false;
                    bool isBlockPSet = false;
                    bool isDeadPSet = false;
                    bool isMergePSet = false;

                    //TODO: Apply transfer function
                    //TODO: update modified as a result of transfer

                    // Transfer function determines values for above bool variables
                    // <<<<<<<<<<< TRANSFER FUNCTION >>>>>>>>>>>>

                    vector<DataflowNode> splitPSetNodes;
                    modified = transfer(descNode, curPSet, func, *state, dfInfoNewBelow,
                                        isDeadPSet, isSplitPSet, splitPSetNodes, isSplitPNode, isBlockPSet, isMergePSet);

                    if(curNode.getCurNode(curPSet) == funcCFGEnd) {
                        // break
                        // move curPSet from active to end set
                        movePSet(curPSet, endPSets, activePSets);
                        break;
                    }

                    if(isDeadPSet) {
                        // Cannot be in this node
                        // stop progress
                        return false;
                    }
                    // if the analysis needs to split
                    // condition independent of 
                    else if(isSplitPNode) {

                    }
                    //NOTE:descNode should be updated by transfer function
                    else if(isSplitPSet) {
                        modified = true;
                        performPSetSplit(curPSet, curNode, descNode, splitPSetNodes, activePSets);
                        
                        // set dot properties
                        descNode.set_id(++npcfgnodes);
//                        descNode.set_dot_attr("red");
                        descNode.set_dot_attr(curPSet);
                    }
                    // if curPSet wants to block
                    else if(isBlockPSet) {
                        movePSet(curPSet, blockedPSets, activePSets);
                        if(!movedPSet) {
                            curNode.updateAncsNode(curPSet, curNode);
                        }
                        else {
                            movedPSet = false;
                        }
                        movedPSet = true;
                        printSubGraphEnd();
                        break;
                    }
                    else if(isMergePSet) {                        
                        movePSet(curPSet, mergePSets, activePSets);
                        if(!movedPSet) {
                            curNode.updateAncsNode(curPSet, curNode);
                        }
                        else {
                            movedPSet = false;
                        }
                        movedPSet = true;                       
                        printSubGraphEnd();
                        break;
                    }
                    else {
                        Dbg::dbg << indent << descNode.str() <<"\n";
                        descNode.advanceOut(curPSet);                        
                        if(movedPSet) {
                            // do not update ancestor as it was set earlier for this pset
                            // reset the flag
                            movedPSet = false;                            
                        }
                        else {
                            descNode.updateAncsNode(curPSet, curNode);
                        }
                        // set dot propeties
                        descNode.set_id(++npcfgnodes);
//                        descNode.set_dot_attr("blue");
                        descNode.set_dot_attr(curPSet);
                        modified = true;
                    }
                    // <<<<<<<<<<< TRANSFER FUNCTION >>>>>>>>>>>>
                }// end else                               

                if(modified) {
                    //TODO: propagate state if required
                    // print dot node, dot edge
                    // make the edge from curnode to descnode
                    // print next transition for pretty printing
                    printNode(descNode);
                    printEdge(descNode.getCurAncsNode(curPSet), descNode);
                    curNode = descNode;
                    modified = false;
                }
                // this processSet is blocked
                //NOTE: modified = false -> fixpoint reached
                else {
                    return true;
                }                
                
            } // end of while(1) -> curPset is blocked or reached end of function
                        
            //movedPSet = true;
        } // end of while(activePsets.size > 0) -> all psets are blocked or require merge

        // All process sets at this point are either blocked or requires merge
        //TODO: need some asserts on total number of process sets here
        //TODO: handle different merge points
        if(mergePSets.size() > 1) {
            // return true;
            // we need to merge all process sets in mergepsets
            // pick the first pset from the mergePSets
            // this will be the activepset in the next node
            unsigned int activepset = *(mergePSets.begin());
            DataflowNode curDfNode = curNode.getCurNode(activepset); // make a copy
            vector<DataflowNode> initDF;
            initDF.push_back(curDfNode);

            pCFGNode descNode(initDF);

            // dot properties
            descNode.set_id(++npcfgnodes);
//            descNode.set_dot_attr("green");
            descNode.set_dot_attr(activepset);

            printNode(descNode);

            // draw edges from all nodes to this descNode
            for(set<unsigned int>::iterator i = mergePSets.begin(); i != mergePSets.end(); i++) {
                printEdge(curNode.getCurAncsNode(*i), descNode);
            }            
            descNode.updateAncsNode(activepset, descNode);

            // set the transition
            curNode = descNode;

            
            // mark visited
            visitedPCFGNodes.insert(descNode);
            
            releasedPSets.insert(activepset);
            activePSets.insert(activepset);
            mergePSets.clear();
            // we dont want to process blocked yet
        }


        //<<<<<< MatchSendRecv >>>>>>>>>
        //TODO: Determine next descNode based on match
        //TODO: Activate all non-split psets
        
        else if(blockedPSets.size() > 0) {
            // if blocked at funcCFGEnd, then don't execute
            // match send recv
            set<unsigned int> sendPSets;
            set<unsigned int> recvPSets;
            // cout << curNode.str() << endl;
            filterSendRecv(curNode, blockedPSets, sendPSets, recvPSets);
            ROSE_ASSERT(sendPSets.size() + recvPSets.size() == blockedPSets.size());

            bool matched = matchSendRecv(curNode, sendPSets, recvPSets, blockedPSets, activePSets, releasedPSets);
            if(matched) {
                cout << "MATCH...\n";
            }
        }            
        //<<<<<< MatchSendRecv >>>>>>>>>

    } while(activePSets.size() > 0); // end of do-while
    
    //TODO: Check if all pSets are at funcCFGEnd
    //TODO: Create chkpts if not present
    //TODO: split(set<chkpts>)     // inserts new chkpts to set of already existing chkpts
    // runAnalysis() takes care of starting from the chkpt
    // All process sets are blocked and they cannot be unblocked via send-receive matching.
        
    // Check if this state was reached because all process sets are at the end of the application 
    int curPSet=0;
    for(vector<DataflowNode>::const_iterator it=curNode.getPSetDFNodes().begin(); 
        it!=curNode.getPSetDFNodes().end(); it++, curPSet++)
    {
        // If some process set is not at the end of this function
        if(*it != funcCFGEnd)
        {
            // Dbg::dbg << indent << "WARNING: in un-releaseable state process set "<<curPSet<<" is not at function end! Instead, n.pSetDFNodes["<<curPSet<<"]="<<(*it).str()<<endl;
            //ROSE_ASSERT(0);
            // Checkpoint this analysis. We may return to it later and discover that not all these process states
            // are actually possible.
            if(analysisDebugLevel>=1) 
                Dbg::dbg << indent << "@@@ Shelving this blocked partition for now.\n";
            set<pCFG_Checkpoint*> chkpt;
            chkpt.insert(new pCFG_Checkpoint(curNode, func, state, activePSets, blockedPSets));
            split(chkpt);
        }
    }
        
    // At this point the analysis has reached the end of the function and does not need to propagate
    // any dataflow further down this function's pCFG. We will now return without creating a checkpoint.
        
    if(analysisDebugLevel>=1) Dbg::exitFunc(funcNameAsString.str());
    printSubGraphEnd();
        
    return true;
}
Exemplo n.º 21
0
void MyList::printListReverse()
{
    if (!head) return;
    printNode(head);
    cout << endl;
}
Exemplo n.º 22
0
Arquivo: xmp.cpp Projeto: dtbinh/dviz
    int XmpParser::decode(      XmpData&     xmpData,
                          const std::string& xmpPacket)
    { try {
        xmpData.clear();
        if (xmpPacket.empty()) return 0;

        if (!initialize()) {
#ifndef SUPPRESS_WARNINGS
            std::cerr << "XMP Toolkit initialization failed.\n";
#endif
            return 2;
        }

        SXMPMeta meta(xmpPacket.data(), static_cast<XMP_StringLen>(xmpPacket.size()));
        SXMPIterator iter(meta);
        std::string schemaNs, propPath, propValue;
        XMP_OptionBits opt;
        while (iter.Next(&schemaNs, &propPath, &propValue, &opt)) {
#ifdef DEBUG
            printNode(schemaNs, propPath, propValue, opt);
#endif
            if (XMP_PropIsAlias(opt)) {
                throw Error(47, schemaNs, propPath, propValue);
                continue;
            }
            if (XMP_NodeIsSchema(opt)) {
                // Register unknown namespaces with Exiv2
                // (Namespaces are automatically registered with the XMP Toolkit)
                if (XmpProperties::prefix(schemaNs).empty()) {
                    std::string prefix;
                    bool ret = meta.GetNamespacePrefix(schemaNs.c_str(), &prefix);
                    if (!ret) throw Error(45, schemaNs);
                    prefix = prefix.substr(0, prefix.size() - 1);
                    XmpProperties::registerNs(schemaNs, prefix);
                }
                continue;
            }
            XmpKey::AutoPtr key = makeXmpKey(schemaNs, propPath);
            if (XMP_ArrayIsAltText(opt)) {
                // Read Lang Alt property
                LangAltValue::AutoPtr val(new LangAltValue);
                XMP_Index count = meta.CountArrayItems(schemaNs.c_str(), propPath.c_str());
                while (count-- > 0) {
                    // Get the text
                    bool haveNext = iter.Next(&schemaNs, &propPath, &propValue, &opt);
#ifdef DEBUG
                    printNode(schemaNs, propPath, propValue, opt);
#endif
                    if (   !haveNext
                        || !XMP_PropIsSimple(opt)
                        || !XMP_PropHasLang(opt)) {
                        throw Error(41, propPath, opt);
                    }
                    const std::string text = propValue;
                    // Get the language qualifier
                    haveNext = iter.Next(&schemaNs, &propPath, &propValue, &opt);
#ifdef DEBUG
                    printNode(schemaNs, propPath, propValue, opt);
#endif
                    if (   !haveNext
                        || !XMP_PropIsSimple(opt)
                        || !XMP_PropIsQualifier(opt)
                        || propPath.substr(propPath.size() - 8, 8) != "xml:lang") {
                        throw Error(42, propPath, opt);
                    }
                    val->value_[propValue] = text;
                }
                xmpData.add(*key.get(), val.get());
                continue;
            }
            if (    XMP_PropIsArray(opt)
                && !XMP_PropHasQualifiers(opt)
                && !XMP_ArrayIsAltText(opt)) {
                // Check if all elements are simple
                bool simpleArray = true;
                SXMPIterator aIter(meta, schemaNs.c_str(), propPath.c_str());
                std::string aSchemaNs, aPropPath, aPropValue;
                XMP_OptionBits aOpt;
                while (aIter.Next(&aSchemaNs, &aPropPath, &aPropValue, &aOpt)) {
                    if (propPath == aPropPath) continue;
                    if (   !XMP_PropIsSimple(aOpt)
                        ||  XMP_PropHasQualifiers(aOpt)
                        ||  XMP_PropIsQualifier(aOpt)
                        ||  XMP_NodeIsSchema(aOpt)
                        ||  XMP_PropIsAlias(aOpt)) {
                        simpleArray = false;
                        break;
                    }
                }
                if (simpleArray) {
                    // Read the array into an XmpArrayValue
                    XmpArrayValue::AutoPtr val(new XmpArrayValue(arrayValueTypeId(opt)));
                    XMP_Index count = meta.CountArrayItems(schemaNs.c_str(), propPath.c_str());
                    while (count-- > 0) {
                        iter.Next(&schemaNs, &propPath, &propValue, &opt);
#ifdef DEBUG
                        printNode(schemaNs, propPath, propValue, opt);
#endif
                        val->read(propValue);
                    }
                    xmpData.add(*key.get(), val.get());
                    continue;
                }
            }
            XmpTextValue::AutoPtr val(new XmpTextValue);
            if (   XMP_PropIsStruct(opt)
                || XMP_PropIsArray(opt)) {
                // Create a metadatum with only XMP options
                val->setXmpArrayType(xmpArrayType(opt));
                val->setXmpStruct(xmpStruct(opt));
                xmpData.add(*key.get(), val.get());
                continue;
            }
            if (   XMP_PropIsSimple(opt)
                || XMP_PropIsQualifier(opt)) {
                val->read(propValue);
                xmpData.add(*key.get(), val.get());
                continue;
            }
            // Don't let any node go by unnoticed
            throw Error(39, key->key(), opt);
        } // iterate through all XMP nodes

        return 0;
    }
    catch (const XMP_Error& e) {
#ifndef SUPPRESS_WARNINGS
        std::cerr << Error(40, e.GetID(), e.GetErrMsg()) << "\n";
#endif
        xmpData.clear();
        return 3;
    }} // XmpParser::decode
Exemplo n.º 23
0
int settingsMenu(Engine* engine)
{
	int ret = 0;
	int selectNum = 0;
	int targetIndex = 0;
	char* name = (char*)malloc(sizeof(char) * 100);
	char* desc = (char*)malloc(sizeof(char) * 400);
	PlaceList targetList;
	printf(" [] Settings\r\n");
	printf("   1. Add place\r\n");
	printf("   2. Modify place\r\n");
	printf("   3. Remove place\r\n");
	printf("   4. Back to main menu\r\n");
	printf(" [] input : ");
	scanf("	 %d", &selectNum);
	clearEnter();
	system("printf '\033\143'");
	switch (selectNum)
	{
	case 1:
		printf(" [Add] Name : ");
		fgets(name, 100, stdin);
		name[strlen(name)-1] = '\0';
		printf(" [Add] Description : ");
		fgets(desc, 400, stdin);
		desc[strlen(desc)-1] = '\0';
		targetList.mName = name;
		targetList.mDesc = desc;
		engine->addPlace(targetList);
		printNode(engine->mPlaceListHead);
		break;
	case 2:
		printf(" [Modify] Target index : ");
		scanf("%d", &targetIndex);
		clearEnter();
		printf(" [Modify] Name : ");
		fgets(name, 100, stdin);
		name[strlen(name)-1] = '\0';
		printf(" [Modify] Description : ");
		fgets(desc, 400, stdin);
		desc[strlen(desc)-1] = '\0';
		targetList.mName = name;
		targetList.mDesc = desc;
		engine->modifyPlace(targetIndex, targetList);
		printNode(engine->mPlaceListHead);
		break;
	case 3:
		printf(" [Delete] Target index : ");
		scanf("%d", &targetIndex);
		clearEnter();
		engine->removePlace(targetIndex);
		printNode(engine->mPlaceListHead);
		break;
	case 4:
		if(name){ free(name); name = NULL;}
		if(desc){ free(desc); desc = NULL;}
		ret = 2;
		break;
	default:
		if(name){ free(name); name = NULL;}
		if(desc){ free(desc); desc = NULL;}
		printf("\r\n");
		printf(" [] Invalid number\r\n");
		break;
	}
	printf("\n");
	return ret;
}
Exemplo n.º 24
0
Arquivo: xmp.cpp Projeto: dtbinh/dviz
    int XmpParser::encode(      std::string& xmpPacket,
                          const XmpData&     xmpData,
                                uint16_t     formatFlags,
                                uint32_t     padding)
    { try {
        if (xmpData.empty()) {
            xmpPacket.clear();
            return 0;
        }

        if (!initialize()) {
#ifndef SUPPRESS_WARNINGS
            std::cerr << "XMP Toolkit initialization failed.\n";
#endif
            return 2;
        }

        SXMPMeta meta;
        for (XmpData::const_iterator i = xmpData.begin(); i != xmpData.end(); ++i) {
            const std::string ns = XmpProperties::ns(i->groupName());
            XMP_OptionBits options = 0;

            if (i->typeId() == langAlt) {
                // Encode Lang Alt property
                const LangAltValue* la = dynamic_cast<const LangAltValue*>(&i->value());
                if (la == 0) throw Error(43, i->key());
                int idx = 1;
                // write the default first
                LangAltValue::ValueType::const_iterator k = la->value_.find("x-default");
                if (k != la->value_.end()) {
#ifdef DEBUG
                    printNode(ns, i->tagName(), k->second, 0);
#endif
                    meta.AppendArrayItem(ns.c_str(), i->tagName().c_str(), kXMP_PropArrayIsAlternate, k->second.c_str());
                    const std::string item = i->tagName() + "[" + toString(idx++) + "]";
                    meta.SetQualifier(ns.c_str(), item.c_str(), kXMP_NS_XML, "lang", k->first.c_str());
                }
                for (k = la->value_.begin(); k != la->value_.end(); ++k) {
                    if (k->first == "x-default") continue;
#ifdef DEBUG
                    printNode(ns, i->tagName(), k->second, 0);
#endif
                    meta.AppendArrayItem(ns.c_str(), i->tagName().c_str(), kXMP_PropArrayIsAlternate, k->second.c_str());
                    const std::string item = i->tagName() + "[" + toString(idx++) + "]";
                    meta.SetQualifier(ns.c_str(), item.c_str(), kXMP_NS_XML, "lang", k->first.c_str());
                }
                continue;
            }
            // Todo: Xmpdatum should have an XmpValue, not a Value
            const XmpValue* val = dynamic_cast<const XmpValue*>(&i->value());
            assert(val);
            options =   xmpArrayOptionBits(val->xmpArrayType())
                      | xmpArrayOptionBits(val->xmpStruct());
            if (   i->typeId() == xmpBag
                || i->typeId() == xmpSeq
                || i->typeId() == xmpAlt) {
#ifdef DEBUG
                printNode(ns, i->tagName(), "", options);
#endif
                meta.SetProperty(ns.c_str(), i->tagName().c_str(), 0, options);
                for (int idx = 0; idx < i->count(); ++idx) {
                    const std::string item = i->tagName() + "[" + toString(idx + 1) + "]";
#ifdef DEBUG
                    printNode(ns, item, i->toString(idx), 0);
#endif
                    meta.SetProperty(ns.c_str(), item.c_str(), i->toString(idx).c_str());
                }
                continue;
            }
            if (i->typeId() == xmpText) {
                if (i->count() == 0) {
#ifdef DEBUG
                    printNode(ns, i->tagName(), "", options);
#endif
                    meta.SetProperty(ns.c_str(), i->tagName().c_str(), 0, options);
                }
                else {
#ifdef DEBUG
                    printNode(ns, i->tagName(), i->toString(0), options);
#endif
                    meta.SetProperty(ns.c_str(), i->tagName().c_str(), i->toString(0).c_str(), options);
                }
                continue;
            }
            // Don't let any Xmpdatum go by unnoticed
            throw Error(38, i->tagName(), TypeInfo::typeName(i->typeId()));
        }
        std::string tmpPacket;
        meta.SerializeToBuffer(&tmpPacket, xmpFormatOptionBits(static_cast<XmpFormatFlags>(formatFlags)), padding); // throws
        xmpPacket = tmpPacket;

        return 0;
    }
    catch (const XMP_Error& e) {
#ifndef SUPPRESS_WARNINGS
        std::cerr << Error(40, e.GetID(), e.GetErrMsg()) << "\n";
#endif
        return 3;
    }} // XmpParser::decode
Exemplo n.º 25
0
void printTree(struct rbt *tree)
{
	printNode(tree, tree->root);
	puts("--------------------");
}
Exemplo n.º 26
0
static int
printGroupBody(D4printer* out, NCD4node* node, int depth)
{
    int ret = NC_NOERR;
    int i,ngroups,nvars,ntypes,ndims,nattrs;

    ngroups = nclistlength(node->groups);
    nvars = nclistlength(node->vars);
    ntypes = nclistlength(node->types);
    ndims = nclistlength(node->dims);
    nattrs = nclistlength(node->attributes);

    if(ndims > 0) {
	INDENT(depth);
	CAT("<Dimensions>\n");
	depth++;
	for(i=0;i<nclistlength(node->dims);i++) {
	    NCD4node* dim = (NCD4node*)nclistget(node->dims,i);
	    printNode(out,dim,depth);
	    CAT("\n");
	}
	depth--;
	INDENT(depth);
	CAT("</Dimensions>\n");
    }
    if(ntypes > 0) {
	INDENT(depth);
	CAT("<Types>\n");
	depth++;
	for(i=0;i<nclistlength(node->types);i++) {
	    NCD4node* type = (NCD4node*)nclistget(node->types,i);
	    if(type->subsort <= NC_MAX_ATOMIC_TYPE) continue;
	    printNode(out,type,depth);
	    CAT("\n");
	}
	depth--;
	INDENT(depth);
	CAT("</Types>\n");
    }
    if(nvars > 0) {
	INDENT(depth);
	CAT("<Variables>\n");
	depth++;
	for(i=0;i<nclistlength(node->vars);i++) {
	    NCD4node* var = (NCD4node*)nclistget(node->vars,i);
	    printNode(out,var,depth);
	}
	depth--;
	INDENT(depth);
	CAT("</Variables>\n");
    }
    if(nattrs > 0) {
	for(i=0;i<nclistlength(node->attributes);i++) {
	    NCD4node* attr = (NCD4node*)nclistget(node->attributes,i);
	    printAttribute(out,attr,depth);
	    CAT("\n");
	}
    }
    if(ngroups > 0) {
	INDENT(depth);
	CAT("<Groups>\n");
	depth++;
	for(i=0;i<nclistlength(node->groups);i++) {
	    NCD4node* g = (NCD4node*)nclistget(node->groups,i);
	    printNode(out,g,depth);
	    CAT("\n");
	}
	depth--;
	INDENT(depth);
	CAT("</Groups>\n");
    }
    return THROW(ret);
}