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