1 /*
2  * Copyright (c) Tony Bybell 1999-2016.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  */
9 
10 
11 /* AIX may need this for alloca to work */
12 #if defined _AIX
13   #pragma alloca
14 #endif
15 
16 #include <config.h>
17 #include "globals.h"
18 #include "tree.h"
19 #include "vcd.h"
20 
21 enum TreeBuildTypes { MAKETREE_FLATTEN, MAKETREE_LEAF, MAKETREE_NODE };
22 
23 
24 #ifdef WAVE_USE_STRUCT_PACKING
talloc_2(size_t siz)25 struct tree *talloc_2(size_t siz)
26 {
27 if(GLOBALS->talloc_pool_base)
28 	{
29 	if((siz + GLOBALS->talloc_idx) <= WAVE_TALLOC_POOL_SIZE)
30 		{
31 		unsigned char *m = GLOBALS->talloc_pool_base + GLOBALS->talloc_idx;
32 		GLOBALS->talloc_idx += siz;
33 		return((struct tree *)m);
34 		}
35 	else
36 	if(siz >= WAVE_TALLOC_ALTREQ_SIZE)
37 		{
38 		return(calloc_2(1, siz));
39 		}
40 	}
41 
42 GLOBALS->talloc_pool_base = calloc_2(1, WAVE_TALLOC_POOL_SIZE);
43 GLOBALS->talloc_idx = 0;
44 return(talloc_2(siz));
45 }
46 #endif
47 
48 
49 /*
50  * init pointers needed for n-way tree
51  */
init_tree(void)52 void init_tree(void)
53 {
54 GLOBALS->module_tree_c_1=(char *)malloc_2(GLOBALS->longestname+1);
55 }
56 
57 
58 /*
59  * extract the next part of the name in the flattened
60  * hierarchy name.  return ptr to next name if it exists
61  * else NULL
62  */
get_module_name(const char * s)63 static const char *get_module_name(const char *s)
64 {
65 char ch;
66 char *pnt;
67 
68 pnt=GLOBALS->module_tree_c_1;
69 
70 for(;;)
71 	{
72 	ch=*(s++);
73 
74 	if(((ch==GLOBALS->hier_delimeter) || (ch == '|')) && (*s)) /* added && null check to allow possible . at end of name */
75 		{
76 		*(pnt)=0;
77 		GLOBALS->module_len_tree_c_1 = pnt - GLOBALS->module_tree_c_1;
78 		return(s);
79 		}
80 
81 	if(!(*(pnt++)=ch))
82 		{
83 		GLOBALS->module_len_tree_c_1 = pnt - GLOBALS->module_tree_c_1;
84 		return(NULL);	/* nothing left to extract */
85 		}
86 	}
87 }
88 
89 
90 /*
91  * generate unique hierarchy pointer faster that sprintf("%p")
92  * use 7-bit string to generate less characters
93  */
94 #ifdef _WAVE_HAVE_JUDY
gen_hier_string(char * dest,void * pnt)95 static int gen_hier_string(char *dest, void *pnt)
96 {
97 uintptr_t p = (uintptr_t)(pnt);
98 char *dest_copy = dest;
99 
100 while(p)
101 	{
102 	*(dest++) = (p & 0x7f) | 0x80;
103 	p >>= 7;
104 	}
105 *(dest++) = '.';
106 
107 return(dest - dest_copy);
108 }
109 #endif
110 
111 
112 /*
113  * decorated module cleanup (if judy active)
114  */
decorated_module_cleanup(void)115 int decorated_module_cleanup(void)
116 {
117 #ifdef _WAVE_HAVE_JUDY
118 if(GLOBALS->sym_tree)
119 	{
120 	JudySLFreeArray(&GLOBALS->sym_tree, PJE0);
121 	}
122 
123 if(GLOBALS->sym_tree_addresses)
124 	{
125 	int rcValue;
126 	Word_t Index = 0;
127 
128 	for (rcValue = Judy1First(GLOBALS->sym_tree_addresses, &Index, PJE0); rcValue != 0; rcValue = Judy1Next(GLOBALS->sym_tree_addresses, &Index, PJE0))
129         	{
130         	((struct tree *)Index)->children_in_gui = 0;
131 	        }
132 
133 	Judy1FreeArray(&GLOBALS->sym_tree_addresses, PJE0);
134 	}
135 
136 #endif
137 return(1);
138 }
139 
140 /*
141  * decorated module add
142  */
allocate_and_decorate_module_tree_node(unsigned char ttype,const char * scopename,const char * compname,uint32_t scopename_len,uint32_t compname_len,uint32_t t_stem,uint32_t t_istem)143 void allocate_and_decorate_module_tree_node(unsigned char ttype, const char *scopename, const char *compname, uint32_t scopename_len, uint32_t compname_len, uint32_t t_stem, uint32_t t_istem)
144 {
145 struct tree *t;
146 int mtyp = WAVE_T_WHICH_UNDEFINED_COMPNAME;
147 #ifdef _WAVE_HAVE_JUDY
148 char str[2048];
149 #endif
150 
151 if(compname && compname[0] && strcmp(scopename, compname))
152 	{
153 	int ix = add_to_comp_name_table(compname, compname_len);
154 	if(ix)
155 		{
156 		ix--;
157 		mtyp = WAVE_T_WHICH_COMPNAME_START - ix;
158 		}
159 	}
160 
161 if(GLOBALS->treeroot)
162 	{
163 	if(GLOBALS->mod_tree_parent)
164 		{
165 #ifdef _WAVE_HAVE_JUDY
166 		if(GLOBALS->mod_tree_parent->children_in_gui)
167 			{
168 			PPvoid_t PPValue;
169 			/* find with judy */
170 			int len = gen_hier_string(str, GLOBALS->mod_tree_parent);
171 			strcpy(str+len, scopename);
172 			PPValue = JudySLIns(&GLOBALS->sym_tree, (uint8_t *)str, PJE0);
173 			if(*PPValue)
174 				{
175 				GLOBALS->mod_tree_parent = *PPValue;
176 				return;
177 				}
178 
179 			t = talloc_2(sizeof(struct tree) + scopename_len + 1);
180 			*PPValue = t;
181 			goto t_allocated;
182 			}
183 			else
184 			{
185 			int dep = 0;
186 #endif
187 			t = GLOBALS->mod_tree_parent->child;
188 			while(t)
189 				{
190 				if(!strcmp(t->name, scopename))
191 					{
192 					GLOBALS->mod_tree_parent = t;
193 					return;
194 					}
195 				t = t->next;
196 #ifdef _WAVE_HAVE_JUDY
197 				dep++;
198 #endif
199 				}
200 
201 #ifdef _WAVE_HAVE_JUDY
202 			if(dep >= FST_TREE_SEARCH_NEXT_LIMIT)
203 				{
204 				PPvoid_t PPValue;
205 				int len = gen_hier_string(str, GLOBALS->mod_tree_parent);
206 				GLOBALS->mod_tree_parent->children_in_gui = 1; /* "borrowed" for tree build */
207 				t = GLOBALS->mod_tree_parent->child;
208 
209 				Judy1Set ((Pvoid_t)&GLOBALS->sym_tree_addresses, (Word_t)GLOBALS->mod_tree_parent, PJE0);
210 				/* assemble judy based on scopename + GLOBALS->mod_tree_parent pnt */
211 				while(t)
212 					{
213 					strcpy(str+len, t->name);
214 					PPValue = JudySLIns(&GLOBALS->sym_tree, (uint8_t *)str, PJE0);
215 					*PPValue = t;
216 
217 					t = t->next;
218 					}
219 
220 				strcpy(str+len, scopename);
221 				PPValue = JudySLIns(&GLOBALS->sym_tree, (uint8_t *)str, PJE0);
222 				t = talloc_2(sizeof(struct tree) + scopename_len + 1);
223 				*PPValue = t;
224 				goto t_allocated;
225 				}
226 			}
227 #endif
228 
229 		t = talloc_2(sizeof(struct tree) + scopename_len + 1);
230 #ifdef _WAVE_HAVE_JUDY
231 t_allocated:
232 #endif
233 		strcpy(t->name, scopename);
234 		t->kind = ttype;
235 		t->t_which = mtyp;
236 		t->t_stem = t_stem;
237 		t->t_istem = t_istem;
238 
239 		if(GLOBALS->mod_tree_parent->child)
240 			{
241 			t->next = GLOBALS->mod_tree_parent->child;
242 			}
243 		GLOBALS->mod_tree_parent->child = t;
244 		GLOBALS->mod_tree_parent = t;
245 		}
246 		else
247 		{
248 		t = GLOBALS->treeroot;
249 			while(t)
250 			{
251 			if(!strcmp(t->name, scopename))
252 				{
253 				GLOBALS->mod_tree_parent = t;
254 				return;
255 				}
256 			t = t->next;
257 			}
258 
259 		t = talloc_2(sizeof(struct tree) + scopename_len + 1);
260 		strcpy(t->name, scopename);
261 		t->kind = ttype;
262 		t->t_which = mtyp;
263 		t->t_stem = t_stem;
264 		t->t_istem = t_istem;
265 
266 		t->next = GLOBALS->treeroot;
267 		GLOBALS->mod_tree_parent = GLOBALS->treeroot = t;
268 		}
269 	}
270 	else
271 	{
272 	t = talloc_2(sizeof(struct tree) + scopename_len + 1);
273 	strcpy(t->name, scopename);
274 	t->kind = ttype;
275 	t->t_which = mtyp;
276 	t->t_stem = t_stem;
277 	t->t_istem = t_istem;
278 
279 	GLOBALS->mod_tree_parent = GLOBALS->treeroot = t;
280 	}
281 }
282 
283 
284 /*
285  * adds back netnames
286  */
treegraft(struct tree ** t)287 int treegraft(struct tree **t)
288 {
289 struct tree *tx = GLOBALS->terminals_tchain_tree_c_1;
290 struct tree *t2;
291 struct tree *par;
292 
293 while(tx)
294 	{
295 	t2 = tx->next;
296 
297 	par = tx->child;
298 	tx->child = NULL;
299 
300 	if(par)
301 		{
302 		if(par->child)
303 			{
304 			tx->next = par->child;
305 			par->child = tx;
306 			}
307 			else
308 			{
309 			par->child = tx;
310 			tx->next = NULL;
311 			}
312 		}
313 		else
314 		{
315 		if(*t)
316 			{
317 			tx->next = (*t)->next;
318 			(*t)->next = tx;
319 			}
320 			else
321 			{
322 			*t = tx;
323 			tx->next = NULL;
324 			}
325 		}
326 
327 	tx = t2;
328 	}
329 
330 return(1);
331 }
332 
333 
334 /*
335  * unswizzle extended names in tree
336  */
treenamefix_str(char * s)337 void treenamefix_str(char *s)
338 {
339 while(*s)
340 	{
341 	if(*s==VCDNAM_ESCAPE) *s=GLOBALS->hier_delimeter;
342 	s++;
343 	}
344 }
345 
treenamefix(struct tree * t)346 void treenamefix(struct tree *t)
347 {
348 struct tree *tnext;
349 if(t->child) treenamefix(t->child);
350 
351 tnext = t->next;
352 
353 while(tnext)
354 	{
355 	if(tnext->child) treenamefix(tnext->child);
356 	if(tnext->name) treenamefix_str(tnext->name);
357 	tnext=tnext->next;
358 	}
359 
360 if(t->name) treenamefix_str(t->name);
361 }
362 
363 
364 /*
365  * for debugging purposes only
366  */
treedebug(struct tree * t,char * s)367 void treedebug(struct tree *t, char *s)
368 {
369 while(t)
370 	{
371 	char *s2;
372 
373 	s2=(char *)malloc_2(strlen(s)+strlen(t->name)+2);
374 	strcpy(s2,s);
375 	strcat(s2,".");
376 	strcat(s2,t->name);
377 
378 	if(t->child)
379 		{
380 		treedebug(t->child, s2);
381 		}
382 
383 	if(t->t_which>=0) /* for when valid netnames like A.B.C, A.B.C.D exist (not legal excluding texsim) */
384 			/* otherwise this would be an 'else' */
385 		{
386 		printf("%3d) %s\n", t->t_which, s2);
387 		}
388 
389 	free_2(s2);
390 	t=t->next;
391 	}
392 }
393 
394 
maketree_nodes(GtkCTreeNode * subtree,struct tree * t2,GtkCTreeNode * sibling,int mode)395 static GtkCTreeNode *maketree_nodes(GtkCTreeNode *subtree, struct tree *t2, GtkCTreeNode *sibling, int mode)
396 {
397 char *tmp, *tmp2, *tmp3;
398 gchar *text [1];
399 GdkDrawable *pxm, *msk;
400 
401 if(t2->t_which >= 0)
402 	{
403         if(GLOBALS->facs[t2->t_which]->vec_root)
404         	{
405                 if(GLOBALS->autocoalesce)
406                 	{
407                         if(GLOBALS->facs[t2->t_which]->vec_root!=GLOBALS->facs[t2->t_which])
408                         	{
409 				return(NULL);
410                                 }
411 
412                         tmp2=makename_chain(GLOBALS->facs[t2->t_which]);
413                         tmp3=leastsig_hiername(tmp2);
414                         tmp=wave_alloca(strlen(tmp3)+4);
415                         strcpy(tmp,   "[] ");
416                         strcpy(tmp+3, tmp3);
417                         free_2(tmp2);
418                         }
419                         else
420                         {
421                         tmp=wave_alloca(strlen(t2->name)+4);
422                         strcpy(tmp,   "[] ");
423                         strcpy(tmp+3, t2->name);
424                         }
425 		}
426                 else
427                 {
428                 tmp=t2->name;
429                 }
430 	}
431         else
432         {
433 	if(t2->t_which == WAVE_T_WHICH_UNDEFINED_COMPNAME)
434 		{
435         	tmp=t2->name;
436 		}
437 		else
438 		{
439 		int thidx = -t2->t_which + WAVE_T_WHICH_COMPNAME_START;
440 		if((thidx >= 0) && (thidx < GLOBALS->comp_name_serial))
441 			{
442 			char *sc = GLOBALS->comp_name_idx[thidx];
443 			int tlen = strlen(t2->name) + 2 + 1 + strlen(sc) + 1 + 1;
444 			tmp = wave_alloca(tlen);
445 			if(!GLOBALS->is_vhdl_component_format)
446 				{
447 				sprintf(tmp, "%s  (%s)", t2->name, sc);
448 				}
449 			else
450 				{
451 				sprintf(tmp, "%s  : %s", t2->name, sc);
452 				}
453 			}
454 			else
455 			{
456 	        	tmp=t2->name;	/* should never get a value out of range here! */
457 			}
458 		}
459         }
460 
461 text[0]=tmp;
462 switch(mode)
463 	{
464 	case MAKETREE_FLATTEN:
465 		if(t2->child)
466 			{
467 		        sibling = gtk_ctree_insert_node (GLOBALS->ctree_main, subtree, sibling, text, 3,
468                 	                       NULL, NULL, NULL, NULL,
469                 	                       FALSE, FALSE);
470 			gtk_ctree_node_set_row_data(GLOBALS->ctree_main, sibling, t2);
471 			maketree(sibling, t2->child);
472 			}
473 			else
474 			{
475 		        sibling = gtk_ctree_insert_node (GLOBALS->ctree_main, subtree, sibling, text, 3,
476                 	                       NULL, NULL, NULL, NULL,
477                 	                       TRUE, FALSE);
478 			gtk_ctree_node_set_row_data(GLOBALS->ctree_main, sibling, t2);
479 			}
480 		break;
481 
482 	default:
483 		switch(t2->kind)
484 			{
485    			case TREE_VCD_ST_MODULE:	pxm = GLOBALS->hiericon_module_pixmap; msk = GLOBALS->hiericon_module_mask; break;
486    			case TREE_VCD_ST_TASK:		pxm = GLOBALS->hiericon_task_pixmap; msk = GLOBALS->hiericon_task_mask; break;
487    			case TREE_VCD_ST_FUNCTION:	pxm = GLOBALS->hiericon_function_pixmap; msk = GLOBALS->hiericon_function_mask; break;
488    			case TREE_VCD_ST_BEGIN:		pxm = GLOBALS->hiericon_begin_pixmap; msk = GLOBALS->hiericon_begin_mask; break;
489    			case TREE_VCD_ST_FORK:		pxm = GLOBALS->hiericon_fork_pixmap; msk = GLOBALS->hiericon_fork_mask; break;
490 			case TREE_VCD_ST_GENERATE:	pxm = GLOBALS->hiericon_generatefor_pixmap; msk = GLOBALS->hiericon_generatefor_mask; break; /* same as TREE_VHDL_ST_GENFOR */
491 			case TREE_VCD_ST_STRUCT:	pxm = GLOBALS->hiericon_block_pixmap; msk = GLOBALS->hiericon_block_mask; break; /* same as TREE_VHDL_ST_BLOCK */
492 			case TREE_VCD_ST_UNION:		pxm = GLOBALS->hiericon_instance_pixmap; msk = GLOBALS->hiericon_instance_mask; break; /* same as TREE_VHDL_ST_INSTANCE */
493 			case TREE_VCD_ST_CLASS:		pxm = GLOBALS->hiericon_class_pixmap; msk = GLOBALS->hiericon_class_mask; break;
494 			case TREE_VCD_ST_INTERFACE:	pxm = GLOBALS->hiericon_interface_pixmap; msk = GLOBALS->hiericon_interface_mask; break;
495 			case TREE_VCD_ST_PACKAGE:	pxm = GLOBALS->hiericon_svpackage_pixmap; msk = GLOBALS->hiericon_svpackage_mask; break;
496 			case TREE_VCD_ST_PROGRAM:	pxm = GLOBALS->hiericon_program_pixmap; msk = GLOBALS->hiericon_program_mask; break;
497 
498 			case TREE_VHDL_ST_DESIGN:	pxm = GLOBALS->hiericon_design_pixmap; msk = GLOBALS->hiericon_design_mask; break;
499 			case TREE_VHDL_ST_BLOCK:	pxm = GLOBALS->hiericon_block_pixmap; msk = GLOBALS->hiericon_block_mask; break;
500 			case TREE_VHDL_ST_GENIF:	pxm = GLOBALS->hiericon_generateif_pixmap; msk = GLOBALS->hiericon_generateif_mask; break;
501 			case TREE_VHDL_ST_GENFOR:	pxm = GLOBALS->hiericon_generatefor_pixmap; msk = GLOBALS->hiericon_generatefor_mask; break;
502 			case TREE_VHDL_ST_INSTANCE:	pxm = GLOBALS->hiericon_instance_pixmap; msk = GLOBALS->hiericon_instance_mask; break;
503 			case TREE_VHDL_ST_PACKAGE:	pxm = GLOBALS->hiericon_package_pixmap; msk = GLOBALS->hiericon_package_mask; break;
504 
505 			case TREE_VHDL_ST_SIGNAL:	pxm = GLOBALS->hiericon_signal_pixmap; msk = GLOBALS->hiericon_signal_mask; break;
506 			case TREE_VHDL_ST_PORTIN:	pxm = GLOBALS->hiericon_portin_pixmap; msk = GLOBALS->hiericon_portin_mask; break;
507 			case TREE_VHDL_ST_PORTOUT:	pxm = GLOBALS->hiericon_portout_pixmap; msk = GLOBALS->hiericon_portout_mask; break;
508 			case TREE_VHDL_ST_PORTINOUT:	pxm = GLOBALS->hiericon_portinout_pixmap; msk = GLOBALS->hiericon_portinout_mask; break;
509 			case TREE_VHDL_ST_BUFFER:	pxm = GLOBALS->hiericon_buffer_pixmap; msk = GLOBALS->hiericon_buffer_mask; break;
510 			case TREE_VHDL_ST_LINKAGE:	pxm = GLOBALS->hiericon_linkage_pixmap; msk = GLOBALS->hiericon_linkage_mask; break;
511 
512    			case TREE_VHDL_ST_ARCHITECTURE:	pxm = GLOBALS->hiericon_module_pixmap; msk = GLOBALS->hiericon_module_mask; break; /* same as TREE_VCD_ST_MODULE */
513    			case TREE_VHDL_ST_FUNCTION:	pxm = GLOBALS->hiericon_function_pixmap; msk = GLOBALS->hiericon_function_mask; break; /* same as TREE_VCD_ST_FUNCTION */
514    			case TREE_VHDL_ST_PROCESS:	pxm = GLOBALS->hiericon_task_pixmap; msk = GLOBALS->hiericon_task_mask; break; /* same as TREE_VCD_ST_TASK */
515 			case TREE_VHDL_ST_PROCEDURE:	pxm = GLOBALS->hiericon_class_pixmap; msk = GLOBALS->hiericon_class_mask; break; /* same as TREE_VCD_ST_CLASS */
516 			case TREE_VHDL_ST_RECORD:	pxm = GLOBALS->hiericon_record_pixmap; msk = GLOBALS->hiericon_record_mask; break;
517 			case TREE_VHDL_ST_GENERATE:	pxm = GLOBALS->hiericon_generate_pixmap; msk = GLOBALS->hiericon_generate_mask; break;
518 
519 			default:			pxm = msk = NULL; break;
520 			}
521 
522 	        sibling = gtk_ctree_insert_node (GLOBALS->ctree_main, subtree, sibling, text, 3,
523                	                       pxm, msk, pxm, msk,
524                	                       (mode==MAKETREE_LEAF), FALSE);
525 		gtk_ctree_node_set_row_data(GLOBALS->ctree_main, sibling, t2);
526 		break;
527 	}
528 
529 return(sibling);
530 }
531 
532 
533 /*
534  * return least significant member name of a hierarchy
535  * (used for tree and hier vec_root search hits)
536  */
leastsig_hiername(char * nam)537 char *leastsig_hiername(char *nam)
538 {
539 char *t, *pnt=NULL;
540 char ch;
541 
542 if(nam)
543 	{
544 	t=nam;
545 	while((ch=*(t++)))
546 		{
547 		if(ch==GLOBALS->hier_delimeter) pnt=t;
548 		}
549 	}
550 
551 return(pnt?pnt:nam);
552 }
553 
554 /**********************************/
555 /* Experimental treesorting code  */
556 /* (won't directly work with lxt2 */
557 /* because alias hier is after    */
558 /* fac hier so fix with partial   */
559 /* mergesort...)                  */
560 /**********************************/
561 
562 /*
563  * sort the hier tree..should be faster than
564  * moving numfacs longer strings around
565  */
566 
tree_qsort_cmp(const void * v1,const void * v2)567 static int tree_qsort_cmp(const void *v1, const void *v2)
568 {
569 struct tree *t1 = *(struct tree **)v1;
570 struct tree *t2 = *(struct tree **)v2;
571 
572 return(sigcmp(t2->name, t1->name));	/* because list must be in rvs */
573 }
574 
treesort_2(struct tree * t,struct tree * p,struct tree *** tm,int * tm_siz)575 static void treesort_2(struct tree *t, struct tree *p, struct tree ***tm, int *tm_siz)
576 {
577 struct tree *it;
578 struct tree **srt;
579 int cnt;
580 int i;
581 
582 if(t->next)
583 	{
584 	it = t;
585 	cnt = 0;
586 	do	{
587 		cnt++;
588 		it=it->next;
589 		} while(it);
590 
591 	if(cnt > *tm_siz)
592 		{
593 		*tm_siz = cnt;
594 		if(*tm) { free_2(*tm); }
595 		*tm = malloc_2((cnt+1) * sizeof(struct tree *));
596 		}
597 	srt = *tm;
598 
599 	for(i=0;i<cnt;i++)
600 		{
601 		srt[i] = t;
602 		t=t->next;
603 		}
604 	srt[i] = NULL;
605 
606 	qsort((void *)srt, cnt, sizeof(struct tree *), tree_qsort_cmp);
607 
608 	if(p)
609 		{
610 		p->child = srt[0];
611 		}
612 		else
613 		{
614 		GLOBALS->treeroot = srt[0];
615 		}
616 
617 	for(i=0;i<cnt;i++)
618 		{
619 		srt[i]->next = srt[i+1];
620 		}
621 
622 	it = srt[0];
623 	for(i=0;i<cnt;i++)
624 		{
625 		if(it->child)
626 			{
627 			treesort_2(it->child, it, tm, tm_siz);
628 			}
629 		it = it->next;
630 		}
631 	}
632 else if (t->child)
633 	{
634 	treesort_2(t->child, t, tm, tm_siz);
635 	}
636 }
637 
638 
treesort(struct tree * t,struct tree * p)639 void treesort(struct tree *t, struct tree *p)
640 {
641 struct tree **tm = NULL;
642 int tm_siz = 0;
643 
644 treesort_2(t, p, &tm, &tm_siz);
645 if(tm)
646 	{
647 	free_2(tm);
648 	}
649 
650 }
651 
652 
order_facs_from_treesort_2(struct tree * t)653 void order_facs_from_treesort_2(struct tree *t)
654 {
655 while(t)
656 	{
657 	if(t->child)
658 		{
659 		order_facs_from_treesort_2(t->child);
660 		}
661 
662 	if(t->t_which>=0) /* for when valid netnames like A.B.C, A.B.C.D exist (not legal excluding texsim) */
663 			/* otherwise this would be an 'else' */
664 		{
665 		GLOBALS->facs2_tree_c_1[GLOBALS->facs2_pos_tree_c_1] = GLOBALS->facs[t->t_which];
666 		t->t_which = GLOBALS->facs2_pos_tree_c_1--;
667 		}
668 
669 	t=t->next;
670 	}
671 }
672 
673 
order_facs_from_treesort(struct tree * t,void * v)674 void order_facs_from_treesort(struct tree *t, void *v)
675 {
676 struct symbol ***f = (struct symbol ***)v; /* eliminate compiler warning in tree.h as symbol.h refs tree.h */
677 
678 GLOBALS->facs2_tree_c_1=(struct symbol **)malloc_2(GLOBALS->numfacs*sizeof(struct symbol *));
679 GLOBALS->facs2_pos_tree_c_1 = GLOBALS->numfacs-1;
680 order_facs_from_treesort_2(t);
681 
682 if(GLOBALS->facs2_pos_tree_c_1>=0)
683 	{
684 	fprintf(stderr, "Internal Error: GLOBALS->facs2_pos_tree_c_1 = %d\n",GLOBALS->facs2_pos_tree_c_1);
685 	fprintf(stderr, "[This is usually the result of multiply defined facilities such as a hierarchy name also being used as a signal at the same level of scope.]\n");
686 	exit(255);
687 	}
688 
689 free_2(*f);
690 *f = GLOBALS->facs2_tree_c_1;
691 GLOBALS->facs2_tree_c_1 = NULL;
692 }
693 
694 
build_tree_from_name(const char * s,int which)695 void build_tree_from_name(const char *s, int which)
696 {
697 struct tree *t, *nt;
698 struct tree *tchain = NULL, *tchain_iter;
699 struct tree *prevt;
700 #ifdef _WAVE_HAVE_JUDY
701 PPvoid_t PPValue = NULL;
702 char str[2048];
703 #endif
704 
705 if(s==NULL || !s[0]) return;
706 
707 t = GLOBALS->treeroot;
708 
709 if(t)
710 	{
711 	prevt = NULL;
712 	while(s)
713 		{
714 rs:		s=get_module_name(s);
715 
716 		if(s && t && !strcmp(t->name, GLOBALS->module_tree_c_1)) /* ajb 300616 added "s &&" to cover case where we can have hierarchy + final name are same, see A.B.C.D notes elsewhere in this file */
717 			{
718 			prevt = t;
719 			t = t->child;
720 			continue;
721 			}
722 
723 #ifdef _WAVE_HAVE_JUDY
724 rescan:
725 		if(prevt && prevt->children_in_gui)
726 			{
727 			/* find with judy */
728 			int len = gen_hier_string(str, prevt);
729 			strcpy(str+len, GLOBALS->module_tree_c_1);
730 			PPValue = JudySLIns(&GLOBALS->sym_tree, (uint8_t *)str, PJE0);
731 			if(*PPValue)
732 				{
733 				t = *PPValue;
734 				prevt = t;
735 				t = t->child;
736 				continue;
737 				}
738 
739 			goto construct;
740 			}
741 #endif
742 
743 		tchain = tchain_iter = t;
744 		if(s && t)
745 			{
746 #ifdef _WAVE_HAVE_JUDY
747 			int dep = 0;
748 #endif
749 		      	nt = t->next;
750 		      	while(nt)
751 				{
752 				if(nt && !strcmp(nt->name, GLOBALS->module_tree_c_1))
753 					{
754 					/* move to front to speed up next compare if in same hier during build */
755 					if(prevt)
756 						{
757 						tchain_iter->next = nt->next;
758 						nt->next = tchain;
759 						prevt->child = nt;
760 						}
761 
762 					prevt = nt;
763 					t = nt->child;
764 					goto rs;
765 					}
766 
767 				tchain_iter = nt;
768 				nt = nt->next;
769 #ifdef _WAVE_HAVE_JUDY
770 				dep++;
771 #endif
772 				}
773 
774 #ifdef _WAVE_HAVE_JUDY
775 			if(prevt && (dep >= FST_TREE_SEARCH_NEXT_LIMIT))
776 				{
777 				int len = gen_hier_string(str, prevt);
778 				prevt->children_in_gui = 1; /* "borrowed" for tree build */
779 				t = prevt->child;
780 
781 				Judy1Set ((Pvoid_t)&GLOBALS->sym_tree_addresses, (Word_t)prevt, PJE0);
782 				/* assemble judy based on scopename + prevt pnt */
783 				while(t)
784 					{
785 					strcpy(str+len, t->name);
786 					PPValue = JudySLIns(&GLOBALS->sym_tree, (uint8_t *)str, PJE0);
787 					*PPValue = t;
788 
789 					t = t->next;
790 					}
791 
792 				goto rescan; /* this level of hier is built, now do insert */
793 				}
794 #endif
795 			}
796 
797 #ifdef _WAVE_HAVE_JUDY
798 construct:
799 #endif
800 		nt=(struct tree *)talloc_2(sizeof(struct tree)+GLOBALS->module_len_tree_c_1 + 1);
801 		memcpy(nt->name, GLOBALS->module_tree_c_1, GLOBALS->module_len_tree_c_1);
802 
803 		if(s)
804 			{
805 			nt->t_which = WAVE_T_WHICH_UNDEFINED_COMPNAME;
806 
807 #ifdef _WAVE_HAVE_JUDY
808 			if(prevt && prevt->children_in_gui)
809 				{
810 				*PPValue = nt;
811 				}
812 #endif
813 
814 			if(prevt)				/* make first in chain */
815 				{
816 				nt->next = prevt->child;
817 				prevt->child = nt;
818 				}
819 				else				/* make second in chain as it's toplevel */
820 				{
821 				nt->next = tchain->next;
822 				tchain->next = nt;
823 				}
824 			}
825 			else
826 			{
827 			nt->child = prevt;			/* parent */
828 			nt->t_which = which;
829 			nt->next = GLOBALS->terminals_tchain_tree_c_1;
830 			GLOBALS->terminals_tchain_tree_c_1 = nt;
831 			return;
832 			}
833 
834 		/* blindly clone fac from next part of hier on down */
835 		t = nt;
836 		while(s)
837 			{
838 			s=get_module_name(s);
839 
840 			nt=(struct tree *)talloc_2(sizeof(struct tree)+GLOBALS->module_len_tree_c_1 + 1);
841 			memcpy(nt->name, GLOBALS->module_tree_c_1, GLOBALS->module_len_tree_c_1);
842 
843 			if(s)
844 				{
845 				nt->t_which = WAVE_T_WHICH_UNDEFINED_COMPNAME;
846 				t->child = nt;
847 				t = nt;
848 				}
849 				else
850 				{
851 				nt->child = t;			/* parent */
852 				nt->t_which = which;
853 				nt->next = GLOBALS->terminals_tchain_tree_c_1;
854 				GLOBALS->terminals_tchain_tree_c_1 = nt;
855 				}
856 			}
857 		}
858 	}
859 else
860 	{
861 	/* blindly create first fac in the tree (only ever called once) */
862 	while(s)
863 		{
864 		s=get_module_name(s);
865 
866 		nt=(struct tree *)talloc_2(sizeof(struct tree)+GLOBALS->module_len_tree_c_1 + 1);
867 		memcpy(nt->name, GLOBALS->module_tree_c_1, GLOBALS->module_len_tree_c_1);
868 
869 		if(!s) nt->t_which=which; else nt->t_which = WAVE_T_WHICH_UNDEFINED_COMPNAME;
870 
871 		if((GLOBALS->treeroot)&&(t)) /* scan-build : && t should be unnecessary to avoid null pointer deref, but add defensively */
872 			{
873 			t->child = nt;
874 			t = nt;
875 			}
876 			else
877 			{
878 			GLOBALS->treeroot = t = nt;
879 			}
880 		}
881 	}
882 }
883 
884 
885 /* ######################## */
886 /* ## compatibility code ## */
887 /* ######################## */
888 
889 /*
890  * tree widgets differ between GTK2 and GTK1 so we need two different
891  * maketree() routines
892  */
893 #if WAVE_USE_GTK2
894 
895 /*
896  * GTK2: build the tree.
897  */
maketree2(GtkCTreeNode * subtree,struct tree * t,int depth,GtkCTreeNode * graft)898 void maketree2(GtkCTreeNode *subtree, struct tree *t, int depth, GtkCTreeNode *graft)
899 {
900 GtkCTreeNode *sibling=NULL, *sibling_test;
901 struct tree *t2;
902 
903 #ifndef WAVE_DISABLE_FAST_TREE
904 if(depth > 1) return;
905 #endif
906 
907 /*
908  * TG reworked treesearch widget so there is no need to
909  * process anything other than nodes.  Leaves are handled
910  * in the filtered list below the node expand/contract
911  * tree
912  */
913 t2=t;
914 while(t2)
915 	{
916 #ifndef WAVE_DISABLE_FAST_TREE
917 	if(depth < 1)
918 #endif
919 		{
920 		t2->children_in_gui = 1;
921 		}
922 
923 	if(t2->child)
924 		{
925                 int blacklist = 0;
926 
927                 if(GLOBALS->exclhiermask)
928                         {
929                         uint64_t exclone = 1;
930                         if((exclone << t2->kind) & GLOBALS->exclhiermask) blacklist = 1;
931                         }
932 
933                 if(GLOBALS->exclinstname)
934                         {
935                         JRB str = jrb_find_str(GLOBALS->exclinstname, t2->name);
936                         if(str) blacklist = 1;
937                         }
938 
939                 if(GLOBALS->exclcompname)
940                         {
941                         int thidx = -t2->t_which + WAVE_T_WHICH_COMPNAME_START;
942                         char *sc = ((thidx >= 0) && (thidx < GLOBALS->comp_name_serial)) ? GLOBALS->comp_name_idx[thidx] : t2->name;
943 
944                         JRB str = jrb_find_str(GLOBALS->exclcompname, sc);
945                         if(str) blacklist = 1;
946                         }
947 
948 		if(!blacklist)
949 			{
950 			if(!graft)
951 				{
952 				sibling_test=maketree_nodes(subtree, t2, sibling, MAKETREE_NODE);
953 				}
954 			else
955 				{
956 				sibling_test = graft;
957 				}
958 			if(sibling_test)
959 				{
960 				GLOBALS->any_tree_node = sibling_test;
961 				maketree2(sibling=sibling_test, t2->child, depth + 1, NULL);
962 				}
963 			}
964 		}
965 
966 	if(graft) break;
967 	t2=t2->next;
968 	}
969 }
970 
971 
maketree(GtkCTreeNode * subtree,struct tree * t)972 void maketree(GtkCTreeNode *subtree, struct tree *t)
973 {
974 maketree2(subtree, t, 0, NULL);
975 }
976 
977 #else
978 
979 /*
980  * GTK1: build the tree.
981  */
maketree(GtkCTreeNode * subtree,struct tree * t)982 void maketree(GtkCTreeNode *subtree, struct tree *t)
983 {
984 GtkCTreeNode *sibling=NULL, *sibling_test;
985 struct tree *t2;
986 
987 if(!GLOBALS->hier_grouping)
988 	{
989 	t2=t;
990 	while(t2)
991 		{
992 		sibling_test=maketree_nodes(subtree, t2, sibling, MAKETREE_FLATTEN);
993 		sibling=sibling_test?sibling_test:sibling;
994 		t2=t2->next;
995 		}
996 	}
997 	else
998 	{
999 	t2=t;
1000 	while(t2)
1001 		{
1002 		if(!t2->child)
1003 			{
1004 			sibling_test=maketree_nodes(subtree, t2, sibling, MAKETREE_LEAF);
1005 			if(sibling_test)
1006 				{
1007 				maketree(sibling=sibling_test, t2->child);
1008 				}
1009 			}
1010 
1011 		t2=t2->next;
1012 		}
1013 
1014 	t2=t;
1015 	while(t2)
1016 		{
1017 		if(t2->child)
1018 			{
1019 			sibling_test=maketree_nodes(subtree, t2, sibling, MAKETREE_NODE);
1020 			if(sibling_test)
1021 				{
1022 				maketree(sibling=sibling_test, t2->child);
1023 				}
1024 			}
1025 
1026 		t2=t2->next;
1027 		}
1028 	}
1029 }
1030 
1031 #endif
1032 
1033 
1034 /*
1035  * SST Exclusion filtering for XXX_maketree2() above
1036  */
1037 #define SST_EXCL_MESS "SSTEXCL | "
1038 
1039 enum sst_excl_mode
1040 {
1041 SST_EXCL_NONE,
1042 SST_EXCL_HIER,
1043 SST_EXCL_COMP,
1044 SST_EXCL_INST
1045 };
1046 
sst_exclusion_loader(void)1047 void sst_exclusion_loader(void)
1048 {
1049 JRB str;
1050 Jval jv;
1051 
1052 int dummy = 0;
1053 
1054 if(GLOBALS->sst_exclude_filename)
1055 	{
1056 	FILE *f = fopen(GLOBALS->sst_exclude_filename, "rb");
1057 	int exclmode = SST_EXCL_NONE;
1058 	uint64_t exclhier = 0;
1059 	uint64_t exclone = 1;
1060 
1061 	if(!f)
1062 		{
1063 		fprintf(stderr, SST_EXCL_MESS"Could not open '%s' SST exclusion file!\n", GLOBALS->sst_exclude_filename);
1064 		fprintf(stderr, SST_EXCL_MESS);
1065 		perror("Why");
1066 		return;
1067 		}
1068 
1069 	fprintf(stderr, SST_EXCL_MESS"Processing '%s'.\n", GLOBALS->sst_exclude_filename);
1070 
1071 	while(!feof(f))
1072 		{
1073 		char *iline = fgetmalloc(f);
1074 		if(iline)
1075 			{
1076 			char *p = iline;
1077 			char *e;
1078 
1079 			while (*p)
1080 				{
1081 				if(isspace(*p)) p++; else break;
1082 				}
1083 
1084 			e = p;
1085 			while (*e)
1086 				{
1087 				if(isspace(*e)) { *e = 0; break; }
1088 				e++;
1089 				}
1090 
1091 			switch (*p)
1092 				{
1093 				case '#': break;
1094 				case '/': break;
1095 
1096 				case '[':
1097 					if(!strcmp(p, "[hiertype]")) 	  { exclmode = SST_EXCL_HIER; }
1098 					else if(!strcmp(p, "[compname]")) { exclmode = SST_EXCL_COMP; }
1099 					else if(!strcmp(p, "[instname]")) { exclmode = SST_EXCL_INST; }
1100 					else                              { exclmode = SST_EXCL_NONE; }
1101 					break;
1102 
1103 				default:
1104 					switch(exclmode)
1105 						{
1106 						case SST_EXCL_HIER: /* this if/else chain is good enough for an init script */
1107 							if(!strcmp(p, "VCD_ST_MODULE")) { exclhier |= exclone << TREE_VCD_ST_MODULE; }
1108 							else if(!strcmp(p, "VCD_ST_TASK")) { exclhier |= exclone << TREE_VCD_ST_TASK; }
1109 							else if(!strcmp(p, "VCD_ST_FUNCTION")) { exclhier |= exclone << TREE_VCD_ST_FUNCTION; }
1110 							else if(!strcmp(p, "VCD_ST_BEGIN")) { exclhier |= exclone << TREE_VCD_ST_BEGIN; }
1111 							else if(!strcmp(p, "VCD_ST_FORK")) { exclhier |= exclone << TREE_VCD_ST_FORK; }
1112 							else if(!strcmp(p, "VCD_ST_GENERATE")) { exclhier |= exclone << TREE_VCD_ST_GENERATE; }
1113 							else if(!strcmp(p, "VCD_ST_STRUCT")) { exclhier |= exclone << TREE_VCD_ST_STRUCT; }
1114 							else if(!strcmp(p, "VCD_ST_UNION")) { exclhier |= exclone << TREE_VCD_ST_UNION; }
1115 							else if(!strcmp(p, "VCD_ST_CLASS")) { exclhier |= exclone << TREE_VCD_ST_CLASS; }
1116 							else if(!strcmp(p, "VCD_ST_INTERFACE")) { exclhier |= exclone << TREE_VCD_ST_INTERFACE; }
1117 							else if(!strcmp(p, "VCD_ST_PACKAGE")) { exclhier |= exclone << TREE_VCD_ST_PACKAGE; }
1118 							else if(!strcmp(p, "VCD_ST_PROGRAM")) { exclhier |= exclone << TREE_VCD_ST_PROGRAM; }
1119 							else if(!strcmp(p, "VHDL_ST_DESIGN")) { exclhier |= exclone << TREE_VHDL_ST_DESIGN; }
1120 							else if(!strcmp(p, "VHDL_ST_BLOCK")) { exclhier |= exclone << TREE_VHDL_ST_BLOCK; }
1121 							else if(!strcmp(p, "VHDL_ST_GENIF")) { exclhier |= exclone << TREE_VHDL_ST_GENIF; }
1122 							else if(!strcmp(p, "VHDL_ST_GENFOR")) { exclhier |= exclone << TREE_VHDL_ST_GENFOR; }
1123 							else if(!strcmp(p, "VHDL_ST_INSTANCE")) { exclhier |= exclone << TREE_VHDL_ST_INSTANCE; }
1124 							else if(!strcmp(p, "VHDL_ST_PACKAGE")) { exclhier |= exclone << TREE_VHDL_ST_PACKAGE; }
1125 
1126 							else if(!strcmp(p, "VHDL_ST_SIGNAL")) { exclhier |= exclone << TREE_VHDL_ST_SIGNAL; }
1127 							else if(!strcmp(p, "VHDL_ST_PORTIN")) { exclhier |= exclone << TREE_VHDL_ST_PORTIN; }
1128 							else if(!strcmp(p, "VHDL_ST_PORTOUT")) { exclhier |= exclone << TREE_VHDL_ST_PORTOUT; }
1129 							else if(!strcmp(p, "VHDL_ST_PORTINOUT")) { exclhier |= exclone << TREE_VHDL_ST_PORTINOUT; }
1130 							else if(!strcmp(p, "VHDL_ST_BUFFER")) { exclhier |= exclone << TREE_VHDL_ST_BUFFER; }
1131 							else if(!strcmp(p, "VHDL_ST_LINKAGE")) { exclhier |= exclone << TREE_VHDL_ST_LINKAGE; }
1132 
1133 							else if(!strcmp(p, "VHDL_ST_ARCHITECTURE")) { exclhier |= exclone << TREE_VHDL_ST_ARCHITECTURE; }
1134 							else if(!strcmp(p, "VHDL_ST_FUNCTION")) { exclhier |= exclone << TREE_VHDL_ST_FUNCTION; }
1135 							else if(!strcmp(p, "VHDL_ST_PROCEDURE")) { exclhier |= exclone << TREE_VHDL_ST_PROCEDURE; }
1136 							else if(!strcmp(p, "VHDL_ST_RECORD")) { exclhier |= exclone << TREE_VHDL_ST_RECORD; }
1137 							else if(!strcmp(p, "VHDL_ST_PROCESS")) { exclhier |= exclone << TREE_VHDL_ST_PROCESS; }
1138 							else if(!strcmp(p, "VHDL_ST_GENERATE")) { exclhier |= exclone << TREE_VHDL_ST_GENERATE; }
1139 							break;
1140 
1141 						case SST_EXCL_COMP:
1142 							if(!GLOBALS->exclcompname) { GLOBALS->exclcompname = make_jrb(); }
1143 							str = jrb_find_str(GLOBALS->exclcompname, p);
1144 							jv.i = dummy++;
1145 							if(!str) jrb_insert_str(GLOBALS->exclcompname, strdup_2(p), jv);
1146 							break;
1147 
1148 						case SST_EXCL_INST:
1149 							if(!GLOBALS->exclinstname) { GLOBALS->exclinstname = make_jrb(); }
1150 							str = jrb_find_str(GLOBALS->exclinstname, p);
1151 							jv.i = dummy++;
1152 							if(!str) jrb_insert_str(GLOBALS->exclinstname, strdup_2(p), jv);
1153 							break;
1154 
1155 						default:	break;
1156 						}
1157 					break;
1158 				}
1159 
1160 			free_2(iline);
1161 			}
1162 
1163 		GLOBALS->exclhiermask |= exclhier;
1164 		}
1165 
1166 	fclose(f);
1167 	}
1168 
1169 }
1170