Codebase list gtkwave / upstream/1.3.34 src / tree.c
upstream/1.3.34

Tree @upstream/1.3.34 (Download .tar.gz)

tree.c @upstream/1.3.34raw · history · blame

/* 
 * Copyright (c) Tony Bybell 1999-2001.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 */

#include "tree.h"
#include "vcd.h"

struct tree *treeroot=NULL;
static char *module=NULL;

char hier_delimeter='.';		/* default is dot unless aet is 
					   selected, then it's slash */
char hier_was_explicitly_set=0;

char alt_hier_delimeter=0x00;		/* for vcds with both [hierarchies or .] and / -- used in vcd only */

extern GtkCTree *ctree_main;

enum TreeBuildTypes { MAKETREE_FLATTEN, MAKETREE_LEAF, MAKETREE_NODE };


/*
 * init pointers needed for n-way tree
 */
void init_tree(void)
{
treeroot=(struct tree *)calloc_2(1,sizeof(struct tree));
module=(char *)malloc_2(longestname+1);
}


/*
 * extract the next part of the name in the flattened
 * hierarchy name.  return ptr to next name if it exists
 * else NULL
 */
static char *get_module_name(char *s)
{
char ch;
char *pnt;

pnt=module;

for(;;)
	{
	ch=*s;

	if(ch==hier_delimeter) 
		{
		*(pnt)=0;	
		s++;
		return(s);		
		}
	if(!ch)
		{
		*(pnt)=0;
		return(NULL);	/* nothing left to extract */		
		}

	s++;
	*(pnt++)=ch;
	}
}


/*
 * build the tree.  to keep the logic simple, we have
 * dead leaves at the ends.
 */
void build_tree_from_name(char *s, int which)
{
struct tree *t;

if(s==NULL) return;
if(!strlen(s)) return;

t=treeroot;
while(s)
	{
	s=get_module_name(s);

	if(!t->name)
		{
		char *newname;
		struct tree *t2;

		newname=(char *)malloc_2(strlen(module)+1);
		strcpy(newname,module);
		t->name=newname;		
		if(!s) t->which=which; else t->which=-1;

		t2=(struct tree *)calloc_2(1,sizeof(struct tree));
		t->child=t2;			
		t2->parent=t;
		t=t2;

		continue;
		}

	if(!strcmp(t->name, module)) 
		{
		t=t->child;
		continue;
		}
		else
		{	
		struct tree *t2, *t3;
		char *newname;

		newname=(char *)malloc_2(strlen(module)+1);
		strcpy(newname,module);
		t2=(struct tree *)calloc_2(1,sizeof(struct tree));
		memcpy(t2, t, sizeof(struct tree));

		t->name=newname;
		t->next=t2;
		if(!s) t->which=which; else t->which=-1;

		t3=(struct tree *)calloc_2(1,sizeof(struct tree));
		t->child=t3;
		t3->parent=t;
		t=t3;		

		continue;
		}
	}
}


/*
 * remove dead leaves from the tree
 */
int treeprune(struct tree *t)
{
while(t)
	{
	if(t->name)
		{
		if(t->child)
			{
			if(!(treeprune(t->child)))
				{
				t->child=NULL; /* remove empty leaf */
				}
			}
		}
		else
		{
		free_2(t);		       /* free empty leaf */
		return(0);
		}

	t=t->next;
	}
return(1);
}


/*
 * for debugging purposes only
 */
void treedebug(struct tree *t, char *s)
{
while(t)
	{
	char *s2;

	s2=(char *)malloc_2(strlen(s)+strlen(t->name)+2);
	strcpy(s2,s);
	strcat(s2,".");
	strcat(s2,t->name);
	
	if(t->child)
		{
		treedebug(t->child, s2);
		}
		else
		{
		printf("%d) %s\n", t->which, s2);
		}

	free_2(s2);
	t=t->next;
	}
}


static GtkCTreeNode *maketree_nodes(GtkCTreeNode *subtree, struct tree *t2, GtkCTreeNode *sibling, int mode)
{
GtkWidget *titem;
GtkWidget *added;
char *tmp, *tmp2, *tmp3;
gchar *text [1];

if(t2->which!=-1)
	{
        if(facs[t2->which]->vec_root)
        	{
                if(autocoalesce)
                	{
                        if(facs[t2->which]->vec_root!=facs[t2->which])
                        	{
				return(NULL);
                                }

                        tmp2=makename_chain(facs[t2->which]);
                        tmp3=leastsig_hiername(tmp2);
                        tmp=wave_alloca(strlen(tmp3)+4);
                        strcpy(tmp,   "[] ");
                        strcpy(tmp+3, tmp3);
                        free_2(tmp2);
                        }
                        else
                        {
                        tmp=wave_alloca(strlen(t2->name)+4);
                        strcpy(tmp,   "[] ");
                        strcpy(tmp+3, t2->name);
                        }
		}
                else
                {
                tmp=t2->name;
                }
	}
        else
        {
        tmp=t2->name;
        }

text[0]=tmp;
switch(mode)
	{
	case MAKETREE_FLATTEN:
		if(t2->child)
			{
		        sibling = gtk_ctree_insert_node (ctree_main, subtree, sibling, text, 3,
                	                       NULL, NULL, NULL, NULL,
                	                       FALSE, FALSE);
			gtk_ctree_node_set_row_data(ctree_main, sibling, t2);
			maketree(sibling, t2->child);
			}
			else
			{
		        sibling = gtk_ctree_insert_node (ctree_main, subtree, sibling, text, 3,
                	                       NULL, NULL, NULL, NULL,
                	                       TRUE, FALSE);
			gtk_ctree_node_set_row_data(ctree_main, sibling, t2);
			}
		break;

	default:
	        sibling = gtk_ctree_insert_node (ctree_main, subtree, sibling, text, 3,
               	                       NULL, NULL, NULL, NULL,
               	                       (mode==MAKETREE_LEAF), FALSE);
		gtk_ctree_node_set_row_data(ctree_main, sibling, t2);
		break;
	}

return(sibling);
}


void maketree(GtkCTreeNode *subtree, struct tree *t)
{
GtkCTreeNode *sibling=NULL, *sibling_test;
struct tree *t2;

if(!hier_grouping)
	{
	t2=t;
	while(t2)
		{
		sibling_test=maketree_nodes(subtree, t2, sibling, MAKETREE_FLATTEN);	
		sibling=sibling_test?sibling_test:sibling;
		t2=t2->next;
		}
	}
	else
	{
	t2=t;
	while(t2)
		{
		if(!t2->child)
			{
			sibling_test=maketree_nodes(subtree, t2, sibling, MAKETREE_LEAF);
			if(sibling_test)
				{
				maketree(sibling=sibling_test, t2->child);
				}
			}
	
		t2=t2->next;
		}

	t2=t;
	while(t2)
		{
		if(t2->child)
			{
			sibling_test=maketree_nodes(subtree, t2, sibling, MAKETREE_NODE);
			if(sibling_test)
				{
				maketree(sibling=sibling_test, t2->child);
				}
			}
	
		t2=t2->next;
		}
	}
}


/*
 * return least significant member name of a hierarchy
 * (used for tree and hier vec_root search hits)
 */
char *leastsig_hiername(char *nam)
{
char *t, *pnt=NULL;
char ch;

if(nam)
	{
	t=nam;
	while(ch=*(t++))
		{
		if(ch==hier_delimeter) pnt=t;
		}
	}

return(pnt?pnt:nam);
}