1 /*
2  * Copyright (c) Tony Bybell 1999-2017.
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 /*
12  * vcd.c 			23jan99ajb
13  * evcd parts 			29jun99ajb
14  * profiler optimizations 	15jul99ajb
15  * more profiler optimizations	25jan00ajb
16  * finsim parameter fix		26jan00ajb
17  * vector rechaining code	03apr00ajb
18  * multiple var section code	06apr00ajb
19  * fix for duplicate nets	19dec00ajb
20  * support for alt hier seps	23dec00ajb
21  * fix for rcs identifiers	16jan01ajb
22  * coredump fix for bad VCD	04apr02ajb
23  * min/maxid speedup            27feb03ajb
24  * bugfix on min/maxid speedup  06jul03ajb
25  * escaped hier modification    20feb06ajb
26  * added real_parameter vartype 04aug06ajb
27  * added in/out port vartype    31jan07ajb
28  * use gperf for port vartypes  19feb07ajb
29  * MTI SV implicit-var fix      05apr07ajb
30  * MTI SV len=0 is real var     05apr07ajb
31  * Backtracking fix             16oct18ajb
32  */
33 
34 /* AIX may need this for alloca to work */
35 #if defined _AIX
36   #pragma alloca
37 #endif
38 
39 #include <config.h>
40 #include "globals.h"
41 #include "vcd.h"
42 #include "hierpack.h"
43 
44 #undef VCD_BSEARCH_IS_PERFECT		/* bsearch is imperfect under linux, but OK under AIX */
45 
46 static void add_histent(TimeType time, struct Node *n, char ch, int regadd, char *vector);
47 static void add_tail_histents(void);
48 static void vcd_build_symbols(void);
49 static void vcd_cleanup(void);
50 static void evcd_strcpy(char *dst, char *src);
51 
52 /******************************************************************/
53 
malform_eof_fix(void)54 static void malform_eof_fix(void)
55 {
56 if(feof(GLOBALS->vcd_handle_vcd_c_1))
57         {
58         memset(GLOBALS->vcdbuf_vcd_c_1, ' ', VCD_BSIZ);
59         GLOBALS->vst_vcd_c_1=GLOBALS->vend_vcd_c_1;
60         }
61 }
62 
63 /**/
64 
strcpy_vcdalt(char * too,char * from,char delim)65 void strcpy_vcdalt(char *too, char *from, char delim)
66 {
67 char ch;
68 
69 do
70 	{
71 	ch=*(from++);
72 	if(ch==delim)
73 		{
74 		ch=GLOBALS->hier_delimeter;
75 		}
76 	} while((*(too++)=ch));
77 }
78 
79 
strcpy_delimfix(char * too,char * from)80 int strcpy_delimfix(char *too, char *from)
81 {
82 char ch;
83 int found = 0;
84 
85 do
86 	{
87 	ch=*(from++);
88 	if(ch==GLOBALS->hier_delimeter)
89 		{
90 		ch=VCDNAM_ESCAPE;
91 		found = 1;
92 		}
93 	} while((*(too++)=ch));
94 
95 if(found) GLOBALS->escaped_names_found_vcd_c_1 = found;
96 
97 return(found);
98 }
99 
100 /******************************************************************/
101 
102 
103 /******************************************************************/
104 
105 enum Tokens   { T_VAR, T_END, T_SCOPE, T_UPSCOPE,
106 		T_COMMENT, T_DATE, T_DUMPALL, T_DUMPOFF, T_DUMPON,
107 		T_DUMPVARS, T_ENDDEFINITIONS,
108 		T_DUMPPORTS, T_DUMPPORTSOFF, T_DUMPPORTSON, T_DUMPPORTSALL,
109 		T_TIMESCALE, T_VERSION, T_VCDCLOSE, T_TIMEZERO,
110 		T_EOF, T_STRING, T_UNKNOWN_KEY };
111 
112 static char *tokens[]={ "var", "end", "scope", "upscope",
113                  "comment", "date", "dumpall", "dumpoff", "dumpon",
114                  "dumpvars", "enddefinitions",
115                  "dumpports", "dumpportsoff", "dumpportson", "dumpportsall",
116                  "timescale", "version", "vcdclose", "timezero",
117                  "", "", "" };
118 
119 #define NUM_TOKENS 19
120 
121 
122 #define T_GET tok=get_token();if((tok==T_END)||(tok==T_EOF))break;
123 
124 /******************************************************************/
125 
126 
127 
128 /******************************************************************/
129 
130 /*
131  * histent structs are NEVER freed so this is OK..
132  * (we are allocating as many entries that fit in 64k minus the size of the two
133  * bookkeeping void* pointers found in the malloc_2/free_2 routines in
134  * debug.c--unless Judy, then can dispense with pointer subtraction)
135  */
136 #ifdef _WAVE_HAVE_JUDY
137 #define VCD_HISTENT_GRANULARITY ( (64*1024) / sizeof(HistEnt) )
138 #else
139 #define VCD_HISTENT_GRANULARITY ( ( (64*1024)-(2*sizeof(void *)) ) / sizeof(HistEnt) )
140 #endif
141 
histent_calloc(void)142 struct HistEnt *histent_calloc(void)
143 {
144 if(GLOBALS->he_curr_vcd_c_1==GLOBALS->he_fini_vcd_c_1)
145 	{
146 	GLOBALS->he_curr_vcd_c_1=(struct HistEnt *)calloc_2(VCD_HISTENT_GRANULARITY, sizeof(struct HistEnt));
147 	GLOBALS->he_fini_vcd_c_1=GLOBALS->he_curr_vcd_c_1+VCD_HISTENT_GRANULARITY;
148 	}
149 
150 return(GLOBALS->he_curr_vcd_c_1++);
151 }
152 
153 /******************************************************************/
154 
155 
156 /******************************************************************/
157 
158 
vcdid_hash(char * s,int len)159 static unsigned int vcdid_hash(char *s, int len)
160 {
161 unsigned int val=0;
162 int i;
163 
164 s+=(len-1);
165 
166 for(i=0;i<len;i++)
167         {
168         val *= 94;
169         val += (((unsigned char)*s) - 32);
170         s--;
171         }
172 
173 return(val);
174 }
175 
176 /******************************************************************/
177 
178 /*
179  * bsearch compare
180  */
vcdsymbsearchcompare(const void * s1,const void * s2)181 static int vcdsymbsearchcompare(const void *s1, const void *s2)
182 {
183 char *v1;
184 struct vcdsymbol *v2;
185 
186 v1=(char *)s1;
187 v2=*((struct vcdsymbol **)s2);
188 
189 return(strcmp(v1, v2->id));
190 }
191 
192 
193 /*
194  * actual bsearch
195  */
bsearch_vcd(char * key,int len)196 static struct vcdsymbol *bsearch_vcd(char *key, int len)
197 {
198 struct vcdsymbol **v;
199 struct vcdsymbol *t;
200 
201 if(GLOBALS->indexed_vcd_c_1)
202         {
203         unsigned int hsh = vcdid_hash(key, len);
204         if((hsh>=GLOBALS->vcd_minid_vcd_c_1)&&(hsh<=GLOBALS->vcd_maxid_vcd_c_1))
205                 {
206                 return(GLOBALS->indexed_vcd_c_1[hsh-GLOBALS->vcd_minid_vcd_c_1]);
207                 }
208 
209 	return(NULL);
210         }
211 
212 if(GLOBALS->sorted_vcd_c_1)
213 	{
214 	v=(struct vcdsymbol **)bsearch(key, GLOBALS->sorted_vcd_c_1, GLOBALS->numsyms_vcd_c_1,
215 		sizeof(struct vcdsymbol *), vcdsymbsearchcompare);
216 
217 	if(v)
218 		{
219 		#ifndef VCD_BSEARCH_IS_PERFECT
220 			for(;;)
221 				{
222 				t=*v;
223 
224 				if((v==GLOBALS->sorted_vcd_c_1)||(strcmp((*(--v))->id, key)))
225 					{
226 					return(t);
227 					}
228 				}
229 		#else
230 			return(*v);
231 		#endif
232 		}
233 		else
234 		{
235 		return(NULL);
236 		}
237 	}
238 	else
239 	{
240 	if(!GLOBALS->err_vcd_c_1)
241 		{
242 		fprintf(stderr, "Near byte %d, VCD search table NULL..is this a VCD file?\n", (int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)));
243 		GLOBALS->err_vcd_c_1=1;
244 		}
245 	return(NULL);
246 	}
247 }
248 
249 
250 /*
251  * sort on vcdsymbol pointers
252  */
vcdsymcompare(const void * s1,const void * s2)253 static int vcdsymcompare(const void *s1, const void *s2)
254 {
255 struct vcdsymbol *v1, *v2;
256 
257 v1=*((struct vcdsymbol **)s1);
258 v2=*((struct vcdsymbol **)s2);
259 
260 return(strcmp(v1->id, v2->id));
261 }
262 
263 
264 /*
265  * create sorted (by id) table
266  */
create_sorted_table(void)267 static void create_sorted_table(void)
268 {
269 struct vcdsymbol *v;
270 struct vcdsymbol **pnt;
271 unsigned int vcd_distance;
272 
273 if(GLOBALS->sorted_vcd_c_1)
274 	{
275 	free_2(GLOBALS->sorted_vcd_c_1);	/* this means we saw a 2nd enddefinition chunk! */
276 	GLOBALS->sorted_vcd_c_1=NULL;
277 	}
278 
279 if(GLOBALS->indexed_vcd_c_1)
280 	{
281 	free_2(GLOBALS->indexed_vcd_c_1);
282 	GLOBALS->indexed_vcd_c_1=NULL;
283 	}
284 
285 if(GLOBALS->numsyms_vcd_c_1)
286 	{
287         vcd_distance = GLOBALS->vcd_maxid_vcd_c_1 - GLOBALS->vcd_minid_vcd_c_1 + 1;
288 
289         if((vcd_distance <= VCD_INDEXSIZ)||(!GLOBALS->vcd_hash_kill))
290                 {
291                 GLOBALS->indexed_vcd_c_1 = (struct vcdsymbol **)calloc_2(vcd_distance, sizeof(struct vcdsymbol *));
292 
293 		/* printf("%d symbols span ID range of %d, using indexing...\n", GLOBALS->numsyms_vcd_c_1, vcd_distance); */
294 
295                 v=GLOBALS->vcdsymroot_vcd_c_1;
296                 while(v)
297                         {
298                         if(!GLOBALS->indexed_vcd_c_1[v->nid - GLOBALS->vcd_minid_vcd_c_1]) GLOBALS->indexed_vcd_c_1[v->nid - GLOBALS->vcd_minid_vcd_c_1] = v;
299                         v=v->next;
300                         }
301                 }
302                 else
303 		{
304 		pnt=GLOBALS->sorted_vcd_c_1=(struct vcdsymbol **)calloc_2(GLOBALS->numsyms_vcd_c_1, sizeof(struct vcdsymbol *));
305 		v=GLOBALS->vcdsymroot_vcd_c_1;
306 		while(v)
307 			{
308 			*(pnt++)=v;
309 			v=v->next;
310 			}
311 
312 		qsort(GLOBALS->sorted_vcd_c_1, GLOBALS->numsyms_vcd_c_1, sizeof(struct vcdsymbol *), vcdsymcompare);
313 		}
314 	}
315 }
316 
317 /******************************************************************/
318 
319 /*
320  * single char get inlined/optimized
321  */
getch_alloc(void)322 static void getch_alloc(void)
323 {
324 GLOBALS->vend_vcd_c_1=GLOBALS->vst_vcd_c_1=GLOBALS->vcdbuf_vcd_c_1=(char *)calloc_2(1,VCD_BSIZ);
325 }
326 
getch_free(void)327 static void getch_free(void)
328 {
329 free_2(GLOBALS->vcdbuf_vcd_c_1);
330 GLOBALS->vcdbuf_vcd_c_1=GLOBALS->vst_vcd_c_1=GLOBALS->vend_vcd_c_1=NULL;
331 }
332 
333 
334 
getch_fetch(void)335 static int getch_fetch(void)
336 {
337 size_t rd;
338 
339 errno = 0;
340 if(feof(GLOBALS->vcd_handle_vcd_c_1)) return(-1);
341 
342 GLOBALS->vcdbyteno_vcd_c_1+=(GLOBALS->vend_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1);
343 rd=fread(GLOBALS->vcdbuf_vcd_c_1, sizeof(char), VCD_BSIZ, GLOBALS->vcd_handle_vcd_c_1);
344 GLOBALS->vend_vcd_c_1=(GLOBALS->vst_vcd_c_1=GLOBALS->vcdbuf_vcd_c_1)+rd;
345 
346 if((!rd)||(errno)) return(-1);
347 
348 if(GLOBALS->vcd_fsiz_vcd_c_1)
349 	{
350 	splash_sync(GLOBALS->vcdbyteno_vcd_c_1, GLOBALS->vcd_fsiz_vcd_c_1); /* gnome 2.18 seems to set errno so splash moved here... */
351 	}
352 
353 return((int)(*GLOBALS->vst_vcd_c_1));
354 }
355 
356 
getch(void)357 static inline signed char getch(void) {
358   signed char ch = ((GLOBALS->vst_vcd_c_1!=GLOBALS->vend_vcd_c_1)?((int)(*GLOBALS->vst_vcd_c_1)):(getch_fetch()));
359   GLOBALS->vst_vcd_c_1++;
360   return(ch);
361 }
362 
getch_peek(void)363 static inline signed char getch_peek(void) {
364   signed char ch = ((GLOBALS->vst_vcd_c_1!=GLOBALS->vend_vcd_c_1)?((int)(*GLOBALS->vst_vcd_c_1)):(getch_fetch()));
365   /* no increment */
366   return(ch);
367 }
368 
369 
370 
getch_patched(void)371 static int getch_patched(void)
372 {
373 char ch;
374 
375 ch=*GLOBALS->vsplitcurr_vcd_c_1;
376 if(!ch)
377 	{
378 	return(-1);
379 	}
380 	else
381 	{
382 	GLOBALS->vsplitcurr_vcd_c_1++;
383 	return((int)ch);
384 	}
385 }
386 
387 /*
388  * simple tokenizer
389  */
get_token(void)390 static int get_token(void)
391 {
392 int ch;
393 int i, len=0;
394 int is_string=0;
395 char *yyshadow;
396 
397 for(;;)
398 	{
399 	ch=getch();
400 	if(ch<0) return(T_EOF);
401 	if(ch<=' ') continue;	/* val<=' ' is a quick whitespace check      */
402 	break;			/* (take advantage of fact that vcd is text) */
403 	}
404 if(ch=='$')
405 	{
406 	GLOBALS->yytext_vcd_c_1[len++]=ch;
407 	for(;;)
408 		{
409 		ch=getch();
410 		if(ch<0) return(T_EOF);
411 		if(ch<=' ') continue;
412 		break;
413 		}
414 	}
415 	else
416 	{
417 	is_string=1;
418 	}
419 
420 for(GLOBALS->yytext_vcd_c_1[len++]=ch;;GLOBALS->yytext_vcd_c_1[len++]=ch)
421 	{
422 	if(len==GLOBALS->T_MAX_STR_vcd_c_1)
423 		{
424 		GLOBALS->yytext_vcd_c_1=(char *)realloc_2(GLOBALS->yytext_vcd_c_1, (GLOBALS->T_MAX_STR_vcd_c_1=GLOBALS->T_MAX_STR_vcd_c_1*2)+1);
425 		}
426 	ch=getch();
427 	if(ch<=' ') break;
428 	}
429 GLOBALS->yytext_vcd_c_1[len]=0;	/* terminator */
430 
431 if(is_string)
432 	{
433 	GLOBALS->yylen_vcd_c_1=len;
434 	return(T_STRING);
435 	}
436 
437 yyshadow=GLOBALS->yytext_vcd_c_1;
438 do
439 {
440 yyshadow++;
441 for(i=0;i<NUM_TOKENS;i++)
442 	{
443 	if(!strcmp(yyshadow,tokens[i]))
444 		{
445 		return(i);
446 		}
447 	}
448 
449 } while(*yyshadow=='$'); /* fix for RCS ids in version strings */
450 
451 return(T_UNKNOWN_KEY);
452 }
453 
454 
get_vartoken_patched(int match_kw)455 static int get_vartoken_patched(int match_kw)
456 {
457 int ch;
458 int len=0;
459 
460 if(!GLOBALS->var_prevch_vcd_c_1)
461 	{
462 	for(;;)
463 		{
464 		ch=getch_patched();
465 		if(ch<0) { free_2(GLOBALS->varsplit_vcd_c_1); GLOBALS->varsplit_vcd_c_1=NULL; return(V_END); }
466 		if((ch==' ')||(ch=='\t')||(ch=='\n')||(ch=='\r')) continue;
467 		break;
468 		}
469 	}
470 	else
471 	{
472 	ch=GLOBALS->var_prevch_vcd_c_1;
473 	GLOBALS->var_prevch_vcd_c_1=0;
474 	}
475 
476 if(ch=='[') return(V_LB);
477 if(ch==':') return(V_COLON);
478 if(ch==']') return(V_RB);
479 
480 for(GLOBALS->yytext_vcd_c_1[len++]=ch;;GLOBALS->yytext_vcd_c_1[len++]=ch)
481 	{
482 	if(len==GLOBALS->T_MAX_STR_vcd_c_1)
483 		{
484 		GLOBALS->yytext_vcd_c_1=(char *)realloc_2(GLOBALS->yytext_vcd_c_1, (GLOBALS->T_MAX_STR_vcd_c_1=GLOBALS->T_MAX_STR_vcd_c_1*2)+1);
485 		}
486 	ch=getch_patched();
487 	if(ch<0) { free_2(GLOBALS->varsplit_vcd_c_1); GLOBALS->varsplit_vcd_c_1=NULL; break; }
488 	if((ch==':')||(ch==']'))
489 		{
490 		GLOBALS->var_prevch_vcd_c_1=ch;
491 		break;
492 		}
493 	}
494 GLOBALS->yytext_vcd_c_1[len]=0;	/* terminator */
495 
496 if(match_kw)
497 	{
498 	int vt = vcd_keyword_code(GLOBALS->yytext_vcd_c_1, len);
499 	if(vt != V_STRING)
500 		{
501 		if(ch<0) { free_2(GLOBALS->varsplit_vcd_c_1); GLOBALS->varsplit_vcd_c_1=NULL; }
502 		return(vt);
503 		}
504 	}
505 
506 GLOBALS->yylen_vcd_c_1=len;
507 if(ch<0) { free_2(GLOBALS->varsplit_vcd_c_1); GLOBALS->varsplit_vcd_c_1=NULL; }
508 return(V_STRING);
509 }
510 
get_vartoken(int match_kw)511 static int get_vartoken(int match_kw)
512 {
513 int ch;
514 int len=0;
515 
516 if(GLOBALS->varsplit_vcd_c_1)
517 	{
518 	int rc=get_vartoken_patched(match_kw);
519 	if(rc!=V_END) return(rc);
520 	GLOBALS->var_prevch_vcd_c_1=0;
521 	}
522 
523 if(!GLOBALS->var_prevch_vcd_c_1)
524 	{
525 	for(;;)
526 		{
527 		ch=getch();
528 		if(ch<0) return(V_END);
529 		if((ch==' ')||(ch=='\t')||(ch=='\n')||(ch=='\r')) continue;
530 		break;
531 		}
532 	}
533 	else
534 	{
535 	ch=GLOBALS->var_prevch_vcd_c_1;
536 	GLOBALS->var_prevch_vcd_c_1=0;
537 	}
538 
539 if(ch=='[') return(V_LB);
540 if(ch==':') return(V_COLON);
541 if(ch==']') return(V_RB);
542 
543 if(ch=='#')     /* for MTI System Verilog '$var reg 64 >w #implicit-var###VarElem:ram_di[0.0] [63:0] $end' style declarations */
544         {       /* debussy simply escapes until the space */
545         GLOBALS->yytext_vcd_c_1[len++]= '\\';
546         }
547 
548 for(GLOBALS->yytext_vcd_c_1[len++]=ch;;GLOBALS->yytext_vcd_c_1[len++]=ch)
549 	{
550 	if(len==GLOBALS->T_MAX_STR_vcd_c_1)
551 		{
552 		GLOBALS->yytext_vcd_c_1=(char *)realloc_2(GLOBALS->yytext_vcd_c_1, (GLOBALS->T_MAX_STR_vcd_c_1=GLOBALS->T_MAX_STR_vcd_c_1*2)+1);
553 		}
554 
555         ch=getch();
556         if(ch==' ')
557                 {
558                 if(match_kw) break;
559                 if(getch_peek() == '[')
560                         {
561                         ch = getch();
562                         GLOBALS->varsplit_vcd_c_1=GLOBALS->yytext_vcd_c_1+len;  /* keep looping so we get the *last* one */
563                         continue;
564                         }
565                 }
566 
567 	if((ch==' ')||(ch=='\t')||(ch=='\n')||(ch=='\r')||(ch<0)) break;
568 	if((ch=='[')&&(GLOBALS->yytext_vcd_c_1[0]!='\\'))
569 		{
570 		GLOBALS->varsplit_vcd_c_1=GLOBALS->yytext_vcd_c_1+len;		/* keep looping so we get the *last* one */
571 		}
572 	else
573 	if(((ch==':')||(ch==']'))&&(!GLOBALS->varsplit_vcd_c_1)&&(GLOBALS->yytext_vcd_c_1[0]!='\\'))
574 		{
575 		GLOBALS->var_prevch_vcd_c_1=ch;
576 		break;
577 		}
578 	}
579 GLOBALS->yytext_vcd_c_1[len]=0;	/* absolute terminator */
580 if((GLOBALS->varsplit_vcd_c_1)&&(GLOBALS->yytext_vcd_c_1[len-1]==']'))
581 	{
582 	char *vst;
583 	vst=malloc_2(strlen(GLOBALS->varsplit_vcd_c_1)+1);
584 	strcpy(vst, GLOBALS->varsplit_vcd_c_1);
585 
586 	*GLOBALS->varsplit_vcd_c_1=0x00;		/* zero out var name at the left bracket */
587 	len=GLOBALS->varsplit_vcd_c_1-GLOBALS->yytext_vcd_c_1;
588 
589 	GLOBALS->varsplit_vcd_c_1=GLOBALS->vsplitcurr_vcd_c_1=vst;
590 	GLOBALS->var_prevch_vcd_c_1=0;
591 	}
592 	else
593 	{
594 	GLOBALS->varsplit_vcd_c_1=NULL;
595 	}
596 
597 if(match_kw)
598 	{
599 	int vt = vcd_keyword_code(GLOBALS->yytext_vcd_c_1, len);
600 	if(vt != V_STRING)
601 		{
602 		return(vt);
603 		}
604 	}
605 
606 GLOBALS->yylen_vcd_c_1=len;
607 return(V_STRING);
608 }
609 
get_strtoken(void)610 static int get_strtoken(void)
611 {
612 int ch;
613 int len=0;
614 
615 if(!GLOBALS->var_prevch_vcd_c_1)
616       {
617       for(;;)
618               {
619               ch=getch();
620               if(ch<0) return(V_END);
621               if((ch==' ')||(ch=='\t')||(ch=='\n')||(ch=='\r')) continue;
622               break;
623               }
624       }
625       else
626       {
627       ch=GLOBALS->var_prevch_vcd_c_1;
628       GLOBALS->var_prevch_vcd_c_1=0;
629       }
630 
631 for(GLOBALS->yytext_vcd_c_1[len++]=ch;;GLOBALS->yytext_vcd_c_1[len++]=ch)
632       {
633 	if(len==GLOBALS->T_MAX_STR_vcd_c_1)
634 		{
635 		GLOBALS->yytext_vcd_c_1=(char *)realloc_2(GLOBALS->yytext_vcd_c_1, (GLOBALS->T_MAX_STR_vcd_c_1=GLOBALS->T_MAX_STR_vcd_c_1*2)+1);
636 		}
637       ch=getch();
638       if((ch==' ')||(ch=='\t')||(ch=='\n')||(ch=='\r')||(ch<0)) break;
639       }
640 GLOBALS->yytext_vcd_c_1[len]=0;        /* terminator */
641 
642 GLOBALS->yylen_vcd_c_1=len;
643 return(V_STRING);
644 }
645 
sync_end(char * hdr)646 static void sync_end(char *hdr)
647 {
648 int tok;
649 
650 if(hdr) { DEBUG(fprintf(stderr,"%s",hdr)); }
651 for(;;)
652 	{
653 	tok=get_token();
654 	if((tok==T_END)||(tok==T_EOF)) break;
655 	if(hdr) { DEBUG(fprintf(stderr," %s",GLOBALS->yytext_vcd_c_1)); }
656 	}
657 if(hdr) { DEBUG(fprintf(stderr,"\n")); }
658 }
659 
version_sync_end(char * hdr)660 static int version_sync_end(char *hdr)
661 {
662 int tok;
663 int rc = 0;
664 
665 if(hdr) { DEBUG(fprintf(stderr,"%s",hdr)); }
666 for(;;)
667 	{
668 	tok=get_token();
669 	if((tok==T_END)||(tok==T_EOF)) break;
670 	if(hdr) { DEBUG(fprintf(stderr," %s",GLOBALS->yytext_vcd_c_1)); }
671         if(strstr(GLOBALS->yytext_vcd_c_1, "Icarus"))   /* turn off autocoalesce for Icarus */
672                 {
673                 GLOBALS->autocoalesce = 0;
674 		rc = 1;
675                 }
676 	}
677 if(hdr) { DEBUG(fprintf(stderr,"\n")); }
678 return(rc);
679 }
680 
build_slisthier(void)681 char *build_slisthier(void)
682 {
683 struct slist *s;
684 int len=0;
685 
686 if(GLOBALS->slisthier)
687 	{
688         free_2(GLOBALS->slisthier);
689         }
690 
691 if(!GLOBALS->slistroot)
692 	{
693 	GLOBALS->slisthier_len=0;
694 	GLOBALS->slisthier=(char *)malloc_2(1);
695 	*GLOBALS->slisthier=0;
696 	return(GLOBALS->slisthier);
697 	}
698 
699 s=GLOBALS->slistroot; len=0;
700 while(s)
701 	{
702 	len+=s->len+(s->next?1:0);
703 	s=s->next;
704 	}
705 
706 GLOBALS->slisthier=(char *)malloc_2((GLOBALS->slisthier_len=len)+1);
707 s=GLOBALS->slistroot; len=0;
708 while(s)
709 	{
710 	strcpy(GLOBALS->slisthier+len,s->str);
711 	len+=s->len;
712 	if(s->next)
713 		{
714 		strcpy(GLOBALS->slisthier+len,GLOBALS->vcd_hier_delimeter);
715 		len++;
716 		}
717 	s=s->next;
718 	}
719 
720 return(GLOBALS->slisthier);
721 }
722 
723 
append_vcd_slisthier(char * str)724 void append_vcd_slisthier(char *str)
725 {
726 struct slist *s;
727 s=(struct slist *)calloc_2(1,sizeof(struct slist));
728 s->len=strlen(str);
729 s->str=(char *)malloc_2(s->len+1);
730 strcpy(s->str,str);
731 
732 if(GLOBALS->slistcurr)
733 	{
734 	GLOBALS->slistcurr->next=s;
735 	GLOBALS->slistcurr=s;
736 	}
737 	else
738 	{
739 	GLOBALS->slistcurr=GLOBALS->slistroot=s;
740 	}
741 
742 build_slisthier();
743 DEBUG(fprintf(stderr, "SCOPE: %s\n",GLOBALS->slisthier));
744 }
745 
746 
parse_valuechange(void)747 static void parse_valuechange(void)
748 {
749 struct vcdsymbol *v;
750 char *vector;
751 int vlen;
752 
753 switch(GLOBALS->yytext_vcd_c_1[0])
754 	{
755 	case '0':
756 	case '1':
757 	case 'x': case 'X':
758 	case 'z': case 'Z':
759 	case 'h': case 'H':
760 	case 'u': case 'U':
761 	case 'w': case 'W':
762 	case 'l': case 'L':
763 	case '-':
764 		if(GLOBALS->yylen_vcd_c_1>1)
765 			{
766 			v=bsearch_vcd(GLOBALS->yytext_vcd_c_1+1, GLOBALS->yylen_vcd_c_1-1);
767 			if(!v)
768 				{
769 				fprintf(stderr,"Near byte %d, Unknown VCD identifier: '%s'\n",(int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)),GLOBALS->yytext_vcd_c_1+1);
770 				malform_eof_fix();
771 				}
772 				else
773 				{
774 				v->value[0]=GLOBALS->yytext_vcd_c_1[0];
775 				DEBUG(fprintf(stderr,"%s = '%c'\n",v->name,v->value[0]));
776 				add_histent(GLOBALS->current_time_vcd_c_1,v->narray[0],v->value[0],1, NULL);
777 				}
778 			}
779 			else
780 			{
781 			fprintf(stderr,"Near byte %d, Malformed VCD identifier\n", (int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)));
782 			malform_eof_fix();
783 			}
784 		break;
785 
786 	case 'b':
787 	case 'B':
788 		{
789 		/* extract binary number then.. */
790 		vector=malloc_2(GLOBALS->yylen_cache_vcd_c_1=GLOBALS->yylen_vcd_c_1);
791 		strcpy(vector,GLOBALS->yytext_vcd_c_1+1);
792 		vlen=GLOBALS->yylen_vcd_c_1-1;
793 
794 		get_strtoken();
795 		v=bsearch_vcd(GLOBALS->yytext_vcd_c_1, GLOBALS->yylen_vcd_c_1);
796 		if(!v)
797 			{
798 			fprintf(stderr,"Near byte %d, Unknown identifier: '%s'\n",(int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)), GLOBALS->yytext_vcd_c_1);
799 			free_2(vector);
800 			malform_eof_fix();
801 			}
802 			else
803 			{
804 			if ((v->vartype==V_REAL)||(v->vartype==V_STRINGTYPE)||((GLOBALS->convert_to_reals)&&((v->vartype==V_INTEGER)||(v->vartype==V_PARAMETER))))
805 				{
806 				double *d;
807 				char *pnt;
808 				char ch;
809 				TimeType k=0;
810 
811 				pnt=vector;
812 				while((ch=*(pnt++))) { k=(k<<1)|((ch=='1')?1:0); }
813 				free_2(vector);
814 
815 				d=malloc_2(sizeof(double));
816 				*d=(double)k;
817 
818 				if(!v)
819 					{
820 					fprintf(stderr,"Near byte %d, Unknown identifier: '%s'\n",(int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)), GLOBALS->yytext_vcd_c_1);
821 					free_2(d);
822 					malform_eof_fix();
823 					}
824 					else
825 					{
826 					add_histent(GLOBALS->current_time_vcd_c_1, v->narray[0],'g',1,(char *)d);
827 					}
828 				break;
829 				}
830 
831 			if(vlen<v->size) 	/* fill in left part */
832 				{
833 				char extend;
834 				int i, fill;
835 
836 				extend=(vector[0]=='1')?'0':vector[0];
837 
838 				fill=v->size-vlen;
839 				for(i=0;i<fill;i++)
840 					{
841 					v->value[i]=extend;
842 					}
843 				strcpy(v->value+fill,vector);
844 				}
845 			else if(vlen==v->size) 	/* straight copy */
846 				{
847 				strcpy(v->value,vector);
848 				}
849 			else			/* too big, so copy only right half */
850 				{
851 				int skip;
852 
853 				skip=vlen-v->size;
854 				strcpy(v->value,vector+skip);
855 				}
856 			DEBUG(fprintf(stderr,"%s = '%s'\n",v->name, v->value));
857 
858 			if((v->size==1)||(!GLOBALS->atomic_vectors))
859 				{
860 				int i;
861 				for(i=0;i<v->size;i++)
862 					{
863 					add_histent(GLOBALS->current_time_vcd_c_1, v->narray[i],v->value[i],1, NULL);
864 					}
865 				free_2(vector);
866 				}
867 				else
868 				{
869 				if(GLOBALS->yylen_cache_vcd_c_1!=(v->size+1))
870 					{
871 					free_2(vector);
872 					vector=malloc_2(v->size+1);
873 					}
874 				strcpy(vector,v->value);
875 				add_histent(GLOBALS->current_time_vcd_c_1, v->narray[0],0,1,vector);
876 				}
877 
878 			}
879 		break;
880 		}
881 
882 	case 'p':
883 		/* extract port dump value.. */
884 		vector=malloc_2(GLOBALS->yylen_cache_vcd_c_1=GLOBALS->yylen_vcd_c_1);
885 		strcpy(vector,GLOBALS->yytext_vcd_c_1+1);
886 		vlen=GLOBALS->yylen_vcd_c_1-1;
887 
888 		get_strtoken();	/* throw away 0_strength_component */
889 		get_strtoken(); /* throw away 0_strength_component */
890 		get_strtoken(); /* this is the id                  */
891 		v=bsearch_vcd(GLOBALS->yytext_vcd_c_1, GLOBALS->yylen_vcd_c_1);
892 		if(!v)
893 			{
894 			fprintf(stderr,"Near byte %d, Unknown identifier: '%s'\n",(int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)), GLOBALS->yytext_vcd_c_1);
895 			free_2(vector);
896 			malform_eof_fix();
897 			}
898 			else
899 			{
900 			if ((v->vartype==V_REAL)||(v->vartype==V_STRINGTYPE)||((GLOBALS->convert_to_reals)&&((v->vartype==V_INTEGER)||(v->vartype==V_PARAMETER))))
901 				{
902 				double *d;
903 				char *pnt;
904 				char ch;
905 				TimeType k=0;
906 
907 				pnt=vector;
908 				while((ch=*(pnt++))) { k=(k<<1)|((ch=='1')?1:0); }
909 				free_2(vector);
910 
911 				d=malloc_2(sizeof(double));
912 				*d=(double)k;
913 
914 				if(!v)
915 					{
916 					fprintf(stderr,"Near byte %d, Unknown identifier: '%s'\n",(int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)), GLOBALS->yytext_vcd_c_1);
917 					free_2(d);
918 					malform_eof_fix();
919 					}
920 					else
921 					{
922 					add_histent(GLOBALS->current_time_vcd_c_1, v->narray[0],'g',1,(char *)d);
923 					}
924 				break;
925 				}
926 
927 			if(vlen<v->size) 	/* fill in left part */
928 				{
929 				char extend;
930 				int i, fill;
931 
932 				extend='0';
933 
934 				fill=v->size-vlen;
935 				for(i=0;i<fill;i++)
936 					{
937 					v->value[i]=extend;
938 					}
939 				evcd_strcpy(v->value+fill,vector);
940 				}
941 			else if(vlen==v->size) 	/* straight copy */
942 				{
943 				evcd_strcpy(v->value,vector);
944 				}
945 			else			/* too big, so copy only right half */
946 				{
947 				int skip;
948 
949 				skip=vlen-v->size;
950 				evcd_strcpy(v->value,vector+skip);
951 				}
952 			DEBUG(fprintf(stderr,"%s = '%s'\n",v->name, v->value));
953 
954 			if((v->size==1)||(!GLOBALS->atomic_vectors))
955 				{
956 				int i;
957 				for(i=0;i<v->size;i++)
958 					{
959 					add_histent(GLOBALS->current_time_vcd_c_1, v->narray[i],v->value[i],1, NULL);
960 					}
961 				free_2(vector);
962 				}
963 				else
964 				{
965 				if(GLOBALS->yylen_cache_vcd_c_1<v->size)
966 					{
967 					free_2(vector);
968 					vector=malloc_2(v->size+1);
969 					}
970 				strcpy(vector,v->value);
971 				add_histent(GLOBALS->current_time_vcd_c_1, v->narray[0],0,1,vector);
972 				}
973 			}
974 		break;
975 
976 
977 	case 'r':
978 	case 'R':
979 		{
980 		double *d;
981 
982 		d=malloc_2(sizeof(double));
983 		sscanf(GLOBALS->yytext_vcd_c_1+1,"%lg",d);
984 
985 		get_strtoken();
986 		v=bsearch_vcd(GLOBALS->yytext_vcd_c_1, GLOBALS->yylen_vcd_c_1);
987 		if(!v)
988 			{
989 			fprintf(stderr,"Near byte %d, Unknown identifier: '%s'\n",(int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)), GLOBALS->yytext_vcd_c_1);
990 			free_2(d);
991 			malform_eof_fix();
992 			}
993 			else
994 			{
995 			add_histent(GLOBALS->current_time_vcd_c_1, v->narray[0],'g',1,(char *)d);
996 			}
997 
998 		break;
999 		}
1000 
1001 #ifndef STRICT_VCD_ONLY
1002 	case 's':
1003 	case 'S':
1004 		{
1005 		char *d;
1006 
1007 		d=(char *)malloc_2(GLOBALS->yylen_vcd_c_1);
1008 		vlen = fstUtilityEscToBin((unsigned char *)d, (unsigned char *)(GLOBALS->yytext_vcd_c_1+1), GLOBALS->yylen_vcd_c_1); /* includes 0 term */
1009 		if(vlen != GLOBALS->yylen_vcd_c_1)
1010 			{
1011 			d = realloc_2(d, vlen);
1012 			}
1013 
1014 		get_strtoken();
1015 		v=bsearch_vcd(GLOBALS->yytext_vcd_c_1, GLOBALS->yylen_vcd_c_1);
1016 		if(!v)
1017 			{
1018 			fprintf(stderr,"Near byte %d, Unknown identifier: '%s'\n",(int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)), GLOBALS->yytext_vcd_c_1);
1019 			free_2(d);
1020 			malform_eof_fix();
1021 			}
1022 			else
1023 			{
1024 			add_histent(GLOBALS->current_time_vcd_c_1, v->narray[0],'s',1,(char *)d);
1025 			}
1026 
1027 		break;
1028 		}
1029 #endif
1030 	}
1031 
1032 }
1033 
1034 
evcd_strcpy(char * dst,char * src)1035 static void evcd_strcpy(char *dst, char *src)
1036 {
1037 static const char *evcd="DUNZduLHXTlh01?FAaBbCcf";
1038 static const char  *vcd="01xz0101xz0101xzxxxxxxz";
1039 
1040 char ch;
1041 int i;
1042 
1043 while((ch=*src))
1044 	{
1045 	for(i=0;i<23;i++)
1046 		{
1047 		if(evcd[i]==ch)
1048 			{
1049 			*dst=vcd[i];
1050 			break;
1051 			}
1052 		}
1053 	if(i==23) *dst='x';
1054 
1055 	src++;
1056 	dst++;
1057 	}
1058 
1059 *dst=0;	/* null terminate destination */
1060 }
1061 
1062 
vcd_parse(void)1063 static void vcd_parse(void)
1064 {
1065 int tok;
1066 unsigned char ttype;
1067 int disable_autocoalesce = 0;
1068 
1069 for(;;)
1070 	{
1071 	switch(get_token())
1072 		{
1073 		case T_COMMENT:
1074 			sync_end("COMMENT:");
1075 			break;
1076 		case T_DATE:
1077 			sync_end("DATE:");
1078 			break;
1079 		case T_VERSION:
1080 			disable_autocoalesce = version_sync_end("VERSION:");
1081 			break;
1082                 case T_TIMEZERO:
1083                         {
1084                         int vtok=get_token();
1085                         if((vtok==T_END)||(vtok==T_EOF)) break;
1086                         GLOBALS->global_time_offset=atoi_64(GLOBALS->yytext_vcd_c_1);
1087 
1088                         DEBUG(fprintf(stderr,"TIMEZERO: "TTFormat"\n",GLOBALS->global_time_offset));
1089                         sync_end(NULL);
1090                         }
1091                         break;
1092 		case T_TIMESCALE:
1093 			{
1094 			int vtok;
1095 			int i;
1096 			char prefix=' ';
1097 
1098 			vtok=get_token();
1099 			if((vtok==T_END)||(vtok==T_EOF)) break;
1100 			fractional_timescale_fix(GLOBALS->yytext_vcd_c_1);
1101 			GLOBALS->time_scale=atoi_64(GLOBALS->yytext_vcd_c_1);
1102 			if(!GLOBALS->time_scale) GLOBALS->time_scale=1;
1103 			for(i=0;i<GLOBALS->yylen_vcd_c_1;i++)
1104 				{
1105 				if((GLOBALS->yytext_vcd_c_1[i]<'0')||(GLOBALS->yytext_vcd_c_1[i]>'9'))
1106 					{
1107 					prefix=GLOBALS->yytext_vcd_c_1[i];
1108 					break;
1109 					}
1110 				}
1111 			if(prefix==' ')
1112 				{
1113 				vtok=get_token();
1114 				if((vtok==T_END)||(vtok==T_EOF)) break;
1115 				prefix=GLOBALS->yytext_vcd_c_1[0];
1116 				}
1117 			switch(prefix)
1118 				{
1119 				case ' ':
1120 				case 'm':
1121 				case 'u':
1122 				case 'n':
1123 				case 'p':
1124 				case 'f':
1125 				case 'a':
1126 				case 'z':
1127 					GLOBALS->time_dimension=prefix;
1128 					break;
1129 				case 's':
1130 					GLOBALS->time_dimension=' ';
1131 					break;
1132 				default:	/* unknown */
1133 					GLOBALS->time_dimension='n';
1134 					break;
1135 				}
1136 
1137 			DEBUG(fprintf(stderr,"TIMESCALE: "TTFormat" %cs\n",GLOBALS->time_scale, GLOBALS->time_dimension));
1138 			sync_end(NULL);
1139 			}
1140 			break;
1141 		case T_SCOPE:
1142 			T_GET;
1143                                 {
1144                                 switch(GLOBALS->yytext_vcd_c_1[0])
1145                                         {
1146                                         case 'm':       ttype = TREE_VCD_ST_MODULE; break;
1147                                         case 't':       ttype = TREE_VCD_ST_TASK; break;
1148                                         case 'f':       ttype = (GLOBALS->yytext_vcd_c_1[1] == 'u') ? TREE_VCD_ST_FUNCTION : TREE_VCD_ST_FORK; break;
1149                                         case 'b':       ttype = TREE_VCD_ST_BEGIN; break;
1150 					case 'g':	ttype = TREE_VCD_ST_GENERATE; break;
1151 					case 's':	ttype = TREE_VCD_ST_STRUCT; break;
1152 					case 'u':	ttype = TREE_VCD_ST_UNION; break;
1153 					case 'c':	ttype = TREE_VCD_ST_CLASS; break;
1154 					case 'i':	ttype = TREE_VCD_ST_INTERFACE; break;
1155 					case 'p':	ttype = (GLOBALS->yytext_vcd_c_1[1] == 'r') ? TREE_VCD_ST_PROGRAM : TREE_VCD_ST_PACKAGE; break;
1156 
1157                                         case 'v':       {
1158                                                         char *vht = GLOBALS->yytext_vcd_c_1;
1159                                                         if(!strncmp(vht, "vhdl_", 5))
1160                                                                 {
1161                                                                 switch(vht[5])
1162                                                                         {
1163                                                                         case 'a':       ttype = TREE_VHDL_ST_ARCHITECTURE; break;
1164                                                                         case 'r':       ttype = TREE_VHDL_ST_RECORD; break;
1165                                                                         case 'b':       ttype = TREE_VHDL_ST_BLOCK; break;
1166                                                                         case 'g':       ttype = TREE_VHDL_ST_GENERATE; break;
1167                                                                         case 'i':       ttype = TREE_VHDL_ST_GENIF; break;
1168                                                                         case 'f':       ttype = (vht[6] == 'u') ? TREE_VHDL_ST_FUNCTION : TREE_VHDL_ST_GENFOR; break;
1169 		                                                        case 'p':       ttype = (!strncmp(vht+6, "roces", 5)) ? TREE_VHDL_ST_PROCESS: TREE_VHDL_ST_PROCEDURE; break;
1170                                                                         default:        ttype = TREE_UNKNOWN; break;
1171                                                                         }
1172                                                                 }
1173                                                                 else
1174                                                                 {
1175                                                                 ttype = TREE_UNKNOWN;
1176                                                                 }
1177                                                         }
1178                                                         break;
1179 
1180                                         default:        ttype = TREE_UNKNOWN;
1181                                                         break;
1182                                         }
1183                                 }
1184 
1185 			T_GET;
1186 			if(tok==T_STRING)
1187 				{
1188 				struct slist *s;
1189 				s=(struct slist *)calloc_2(1,sizeof(struct slist));
1190 				s->len=GLOBALS->yylen_vcd_c_1;
1191 				s->str=(char *)malloc_2(GLOBALS->yylen_vcd_c_1+1);
1192 				strcpy(s->str, GLOBALS->yytext_vcd_c_1);
1193 				s->mod_tree_parent = GLOBALS->mod_tree_parent;
1194 
1195 				allocate_and_decorate_module_tree_node(ttype, GLOBALS->yytext_vcd_c_1, NULL, GLOBALS->yylen_vcd_c_1, 0, 0, 0);
1196 
1197 				if(GLOBALS->slistcurr)
1198 					{
1199 					GLOBALS->slistcurr->next=s;
1200 					GLOBALS->slistcurr=s;
1201 					}
1202 					else
1203 					{
1204 					GLOBALS->slistcurr=GLOBALS->slistroot=s;
1205 					}
1206 
1207 				build_slisthier();
1208 				DEBUG(fprintf(stderr, "SCOPE: %s\n",GLOBALS->slisthier));
1209 				}
1210 			sync_end(NULL);
1211 			break;
1212 		case T_UPSCOPE:
1213 			if(GLOBALS->slistroot)
1214 				{
1215 				struct slist *s;
1216 
1217 				GLOBALS->mod_tree_parent = GLOBALS->slistcurr->mod_tree_parent;
1218 				s=GLOBALS->slistroot;
1219 				if(!s->next)
1220 					{
1221 					free_2(s->str);
1222 					free_2(s);
1223 					GLOBALS->slistroot=GLOBALS->slistcurr=NULL;
1224 					}
1225 				else
1226 				for(;;)
1227 					{
1228 					if(!s->next->next)
1229 						{
1230 						free_2(s->next->str);
1231 						free_2(s->next);
1232 						s->next=NULL;
1233 						GLOBALS->slistcurr=s;
1234 						break;
1235 						}
1236 					s=s->next;
1237 					}
1238 				build_slisthier();
1239 				DEBUG(fprintf(stderr, "SCOPE: %s\n",GLOBALS->slisthier));
1240 				}
1241 				else
1242 				{
1243 				GLOBALS->mod_tree_parent = NULL;
1244 				}
1245 			sync_end(NULL);
1246 			break;
1247 		case T_VAR:
1248 			if((GLOBALS->header_over_vcd_c_1)&&(0))
1249 			{
1250 			fprintf(stderr,"$VAR encountered after $ENDDEFINITIONS near byte %d.  VCD is malformed, exiting.\n",
1251 				(int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)));
1252 			vcd_exit(255);
1253 			}
1254 			else
1255 			{
1256 			int vtok;
1257 			struct vcdsymbol *v=NULL;
1258 
1259 			GLOBALS->var_prevch_vcd_c_1=0;
1260 
1261 			if(GLOBALS->varsplit_vcd_c_1)
1262 				{
1263 				free_2(GLOBALS->varsplit_vcd_c_1);
1264 				GLOBALS->varsplit_vcd_c_1=NULL;
1265 				}
1266 			vtok=get_vartoken(1);
1267 			if(vtok>V_STRINGTYPE) goto bail;
1268 
1269 			v=(struct vcdsymbol *)calloc_2(1,sizeof(struct vcdsymbol));
1270 			v->vartype=vtok;
1271 			v->msi=v->lsi=GLOBALS->vcd_explicit_zero_subscripts; /* indicate [un]subscripted status */
1272 
1273 			if(vtok==V_PORT)
1274 				{
1275 				vtok=get_vartoken(1);
1276 				if(vtok==V_STRING)
1277 					{
1278 					v->size=atoi_64(GLOBALS->yytext_vcd_c_1);
1279 					if(!v->size) v->size=1;
1280 					}
1281 					else
1282 					if(vtok==V_LB)
1283 					{
1284 					vtok=get_vartoken(1);
1285 					if(vtok==V_END) goto err;
1286 					if(vtok!=V_STRING) goto err;
1287 					v->msi=atoi_64(GLOBALS->yytext_vcd_c_1);
1288 					vtok=get_vartoken(0);
1289 					if(vtok==V_RB)
1290 						{
1291 						v->lsi=v->msi;
1292 						v->size=1;
1293 						}
1294 						else
1295 						{
1296 						if(vtok!=V_COLON) goto err;
1297 						vtok=get_vartoken(0);
1298 						if(vtok!=V_STRING) goto err;
1299 						v->lsi=atoi_64(GLOBALS->yytext_vcd_c_1);
1300 						vtok=get_vartoken(0);
1301 						if(vtok!=V_RB) goto err;
1302 
1303 						if(v->msi>v->lsi)
1304 							{
1305 							v->size=v->msi-v->lsi+1;
1306 							}
1307 							else
1308 							{
1309 							v->size=v->lsi-v->msi+1;
1310 							}
1311 						}
1312 					}
1313 					else goto err;
1314 
1315 				vtok=get_strtoken();
1316 				if(vtok==V_END) goto err;
1317 				v->id=(char *)malloc_2(GLOBALS->yylen_vcd_c_1+1);
1318 				strcpy(v->id, GLOBALS->yytext_vcd_c_1);
1319                                 v->nid=vcdid_hash(GLOBALS->yytext_vcd_c_1,GLOBALS->yylen_vcd_c_1);
1320 
1321                                 if(v->nid == (GLOBALS->vcd_hash_max+1))
1322                                         {
1323                                         GLOBALS->vcd_hash_max = v->nid;
1324                                         }
1325                                 else
1326                                 if((v->nid>0)&&(v->nid<=GLOBALS->vcd_hash_max))
1327                                         {
1328                                         /* general case with aliases */
1329                                         }
1330                                 else
1331                                         {
1332                                         GLOBALS->vcd_hash_kill = 1;
1333                                         }
1334 
1335                                 if(v->nid < GLOBALS->vcd_minid_vcd_c_1) GLOBALS->vcd_minid_vcd_c_1 = v->nid;
1336                                 if(v->nid > GLOBALS->vcd_maxid_vcd_c_1) GLOBALS->vcd_maxid_vcd_c_1 = v->nid;
1337 
1338 				vtok=get_vartoken(0);
1339 				if(vtok!=V_STRING) goto err;
1340 				if(GLOBALS->slisthier_len)
1341 					{
1342 					v->name=(char *)malloc_2(GLOBALS->slisthier_len+1+GLOBALS->yylen_vcd_c_1+1);
1343 					strcpy(v->name,GLOBALS->slisthier);
1344 					strcpy(v->name+GLOBALS->slisthier_len,GLOBALS->vcd_hier_delimeter);
1345 					if(GLOBALS->alt_hier_delimeter)
1346 						{
1347 						strcpy_vcdalt(v->name+GLOBALS->slisthier_len+1,GLOBALS->yytext_vcd_c_1,GLOBALS->alt_hier_delimeter);
1348 						}
1349 						else
1350 						{
1351 						if((strcpy_delimfix(v->name+GLOBALS->slisthier_len+1,GLOBALS->yytext_vcd_c_1)) && (GLOBALS->yytext_vcd_c_1[0] != '\\'))
1352 							{
1353 							char *sd=(char *)malloc_2(GLOBALS->slisthier_len+1+GLOBALS->yylen_vcd_c_1+2);
1354 							strcpy(sd,GLOBALS->slisthier);
1355 							strcpy(sd+GLOBALS->slisthier_len,GLOBALS->vcd_hier_delimeter);
1356 							sd[GLOBALS->slisthier_len+1] = '\\';
1357 							strcpy(sd+GLOBALS->slisthier_len+2,v->name+GLOBALS->slisthier_len+1);
1358 							free_2(v->name);
1359 							v->name = sd;
1360 							}
1361 						}
1362 					}
1363 					else
1364 					{
1365 					v->name=(char *)malloc_2(GLOBALS->yylen_vcd_c_1+1);
1366 					if(GLOBALS->alt_hier_delimeter)
1367 						{
1368 						strcpy_vcdalt(v->name,GLOBALS->yytext_vcd_c_1,GLOBALS->alt_hier_delimeter);
1369 						}
1370 						else
1371 						{
1372 						if((strcpy_delimfix(v->name,GLOBALS->yytext_vcd_c_1)) && (GLOBALS->yytext_vcd_c_1[0] != '\\'))
1373 							{
1374 							char *sd=(char *)malloc_2(GLOBALS->yylen_vcd_c_1+2);
1375 							sd[0] = '\\';
1376 							strcpy(sd+1,v->name);
1377 							free_2(v->name);
1378 							v->name = sd;
1379 							}
1380 						}
1381 					}
1382 
1383                                 if(GLOBALS->pv_vcd_c_1)
1384                                         {
1385                                         if(!strcmp(GLOBALS->pv_vcd_c_1->name,v->name) && !disable_autocoalesce && (!strchr(v->name, '\\')))
1386                                                 {
1387                                                 GLOBALS->pv_vcd_c_1->chain=v;
1388                                                 v->root=GLOBALS->rootv_vcd_c_1;
1389                                                 if(GLOBALS->pv_vcd_c_1==GLOBALS->rootv_vcd_c_1) GLOBALS->pv_vcd_c_1->root=GLOBALS->rootv_vcd_c_1;
1390                                                 }
1391                                                 else
1392                                                 {
1393                                                 GLOBALS->rootv_vcd_c_1=v;
1394                                                 }
1395                                         }
1396 					else
1397 					{
1398 					GLOBALS->rootv_vcd_c_1=v;
1399 					}
1400                                 GLOBALS->pv_vcd_c_1=v;
1401 				}
1402 				else	/* regular vcd var, not an evcd port var */
1403 				{
1404 				vtok=get_vartoken(1);
1405 				if(vtok==V_END) goto err;
1406 				v->size=atoi_64(GLOBALS->yytext_vcd_c_1);
1407 				vtok=get_strtoken();
1408 				if(vtok==V_END) goto err;
1409 				v->id=(char *)malloc_2(GLOBALS->yylen_vcd_c_1+1);
1410 				strcpy(v->id, GLOBALS->yytext_vcd_c_1);
1411                                 v->nid=vcdid_hash(GLOBALS->yytext_vcd_c_1,GLOBALS->yylen_vcd_c_1);
1412 
1413                                 if(v->nid == (GLOBALS->vcd_hash_max+1))
1414                                         {
1415                                         GLOBALS->vcd_hash_max = v->nid;
1416                                         }
1417                                 else
1418                                 if((v->nid>0)&&(v->nid<=GLOBALS->vcd_hash_max))
1419                                         {
1420                                         /* general case with aliases */
1421                                         }
1422                                 else
1423                                         {
1424                                         GLOBALS->vcd_hash_kill = 1;
1425                                         }
1426 
1427                                 if(v->nid < GLOBALS->vcd_minid_vcd_c_1) GLOBALS->vcd_minid_vcd_c_1 = v->nid;
1428                                 if(v->nid > GLOBALS->vcd_maxid_vcd_c_1) GLOBALS->vcd_maxid_vcd_c_1 = v->nid;
1429 
1430 				vtok=get_vartoken(0);
1431 				if(vtok!=V_STRING) goto err;
1432 				if(GLOBALS->slisthier_len)
1433 					{
1434 					v->name=(char *)malloc_2(GLOBALS->slisthier_len+1+GLOBALS->yylen_vcd_c_1+1);
1435 					strcpy(v->name,GLOBALS->slisthier);
1436 					strcpy(v->name+GLOBALS->slisthier_len,GLOBALS->vcd_hier_delimeter);
1437 					if(GLOBALS->alt_hier_delimeter)
1438 						{
1439 						strcpy_vcdalt(v->name+GLOBALS->slisthier_len+1,GLOBALS->yytext_vcd_c_1,GLOBALS->alt_hier_delimeter);
1440 						}
1441 						else
1442 						{
1443 						if((strcpy_delimfix(v->name+GLOBALS->slisthier_len+1,GLOBALS->yytext_vcd_c_1)) && (GLOBALS->yytext_vcd_c_1[0] != '\\'))
1444 							{
1445                                                         char *sd=(char *)malloc_2(GLOBALS->slisthier_len+1+GLOBALS->yylen_vcd_c_1+2);
1446                                                         strcpy(sd,GLOBALS->slisthier);
1447                                                         strcpy(sd+GLOBALS->slisthier_len,GLOBALS->vcd_hier_delimeter);
1448                                                         sd[GLOBALS->slisthier_len+1] = '\\';
1449                                                         strcpy(sd+GLOBALS->slisthier_len+2,v->name+GLOBALS->slisthier_len+1);
1450                                                         free_2(v->name);
1451                                                         v->name = sd;
1452 							}
1453 						}
1454 					}
1455 					else
1456 					{
1457 					v->name=(char *)malloc_2(GLOBALS->yylen_vcd_c_1+1);
1458 					if(GLOBALS->alt_hier_delimeter)
1459 						{
1460 						strcpy_vcdalt(v->name,GLOBALS->yytext_vcd_c_1,GLOBALS->alt_hier_delimeter);
1461 						}
1462 						else
1463 						{
1464                                                 if((strcpy_delimfix(v->name,GLOBALS->yytext_vcd_c_1)) && (GLOBALS->yytext_vcd_c_1[0] != '\\'))
1465                                                         {
1466                                                         char *sd=(char *)malloc_2(GLOBALS->yylen_vcd_c_1+2);
1467                                                         sd[0] = '\\';
1468                                                         strcpy(sd+1,v->name);
1469                                                         free_2(v->name);
1470                                                         v->name = sd;
1471                                                         }
1472 						}
1473 					}
1474 
1475                                 if(GLOBALS->pv_vcd_c_1)
1476                                         {
1477                                         if(!strcmp(GLOBALS->pv_vcd_c_1->name,v->name))
1478                                                 {
1479                                                 GLOBALS->pv_vcd_c_1->chain=v;
1480                                                 v->root=GLOBALS->rootv_vcd_c_1;
1481                                                 if(GLOBALS->pv_vcd_c_1==GLOBALS->rootv_vcd_c_1) GLOBALS->pv_vcd_c_1->root=GLOBALS->rootv_vcd_c_1;
1482                                                 }
1483                                                 else
1484                                                 {
1485                                                 GLOBALS->rootv_vcd_c_1=v;
1486                                                 }
1487                                         }
1488 					else
1489 					{
1490 					GLOBALS->rootv_vcd_c_1=v;
1491 					}
1492                                 GLOBALS->pv_vcd_c_1=v;
1493 
1494 				vtok=get_vartoken(1);
1495 				if(vtok==V_END) goto dumpv;
1496 				if(vtok!=V_LB) goto err;
1497 				vtok=get_vartoken(0);
1498 				if(vtok!=V_STRING) goto err;
1499 				v->msi=atoi_64(GLOBALS->yytext_vcd_c_1);
1500 				vtok=get_vartoken(0);
1501 				if(vtok==V_RB)
1502 					{
1503 					v->lsi=v->msi;
1504 					goto dumpv;
1505 					}
1506 				if(vtok!=V_COLON) goto err;
1507 				vtok=get_vartoken(0);
1508 				if(vtok!=V_STRING) goto err;
1509 				v->lsi=atoi_64(GLOBALS->yytext_vcd_c_1);
1510 				vtok=get_vartoken(0);
1511 				if(vtok!=V_RB) goto err;
1512 				}
1513 
1514 			dumpv:
1515                         if(v->size == 0)
1516                                 {
1517                                 if(v->vartype != V_EVENT)
1518                                         {
1519 					if(v->vartype != V_STRINGTYPE)
1520 						{
1521 	                                        v->vartype = V_REAL;
1522 						}
1523                                         }
1524                                         else
1525                                         {
1526                                         v->size = 1;
1527                                         }
1528 
1529                                 } /* MTI fix */
1530 
1531 			if((v->vartype==V_REAL)||(v->vartype==V_STRINGTYPE)||((GLOBALS->convert_to_reals)&&((v->vartype==V_INTEGER)||(v->vartype==V_PARAMETER))))
1532 				{
1533 				if(v->vartype!=V_STRINGTYPE)
1534 					{
1535 					v->vartype=V_REAL;
1536 					}
1537 				v->size=1;		/* override any data we parsed in */
1538 				v->msi=v->lsi=0;
1539 				}
1540 			else
1541 			if((v->size>1)&&(v->msi<=0)&&(v->lsi<=0))
1542 				{
1543 				if(v->vartype==V_EVENT)
1544 					{
1545 					v->size=1;
1546 					}
1547 					else
1548 					{
1549 					/* any criteria for the direction here? */
1550 					v->msi=v->size-1;
1551 					v->lsi=0;
1552 					}
1553 				}
1554 			else
1555 			if((v->msi>v->lsi)&&((v->msi-v->lsi+1)!=v->size))
1556 				{
1557                                 if((v->vartype!=V_EVENT)&&(v->vartype!=V_PARAMETER))
1558                                         {
1559 					if((v->msi-v->lsi+1) > v->size) /* if() is 2d add */
1560 						{
1561 	                                        v->msi = v->size-1; v->lsi = 0;
1562 						}
1563                                         /* all this formerly was goto err; */
1564                                         }
1565                                         else
1566                                         {
1567                                         v->size=v->msi-v->lsi+1;
1568                                         }
1569 				}
1570 			else
1571 			if((v->lsi>=v->msi)&&((v->lsi-v->msi+1)!=v->size))
1572 				{
1573                                 if((v->vartype!=V_EVENT)&&(v->vartype!=V_PARAMETER))
1574                                         {
1575 					if((v->lsi-v->msi+1) > v->size) /* if() is 2d add */
1576 						{
1577 	                                        v->lsi = v->size-1; v->msi = 0;
1578 						}
1579                                         /* all this formerly was goto err; */
1580                                         }
1581                                         else
1582                                         {
1583                                         v->size=v->lsi-v->msi+1;
1584                                         }
1585 				}
1586 
1587 			/* initial conditions */
1588 			v->value=(char *)malloc_2(v->size+1);
1589 			v->value[v->size]=0;
1590 			v->narray=(struct Node **)calloc_2(v->size,sizeof(struct Node *));
1591 				{
1592 				int i;
1593 				if(GLOBALS->atomic_vectors)
1594 					{
1595 					for(i=0;i<v->size;i++)
1596 						{
1597 						v->value[i]='x';
1598 						}
1599 					v->narray[0]=(struct Node *)calloc_2(1,sizeof(struct Node));
1600 					v->narray[0]->head.time=-1;
1601 					v->narray[0]->head.v.h_val=AN_X;
1602 					set_vcd_vartype(v, v->narray[0]);
1603 					}
1604 					else
1605 					{
1606 					for(i=0;i<v->size;i++)
1607 						{
1608 						v->value[i]='x';
1609 
1610 						v->narray[i]=(struct Node *)calloc_2(1,sizeof(struct Node));
1611 						v->narray[i]->head.time=-1;
1612 						v->narray[i]->head.v.h_val=AN_X;
1613 						if(i == 0)
1614 							{
1615 							set_vcd_vartype(v, v->narray[0]);
1616 							}
1617 							else
1618 							{
1619 							v->narray[i]->vartype = v->narray[0]->vartype;
1620 							}
1621 						}
1622 					}
1623 				}
1624 
1625 			if(!GLOBALS->vcdsymroot_vcd_c_1)
1626 				{
1627 				GLOBALS->vcdsymroot_vcd_c_1=GLOBALS->vcdsymcurr_vcd_c_1=v;
1628 				}
1629 				else
1630 				{
1631 				GLOBALS->vcdsymcurr_vcd_c_1->next=v;
1632 				GLOBALS->vcdsymcurr_vcd_c_1=v;
1633 				}
1634 			GLOBALS->numsyms_vcd_c_1++;
1635 
1636 			if(GLOBALS->vcd_save_handle)
1637 				{
1638 				if(v->msi==v->lsi)
1639 					{
1640 					if((v->vartype==V_REAL)||(v->vartype==V_STRINGTYPE))
1641 						{
1642 						fprintf(GLOBALS->vcd_save_handle,"%s\n",v->name);
1643 						}
1644 						else
1645 						{
1646 						if(v->msi>=0)
1647 							{
1648 							if(!GLOBALS->vcd_explicit_zero_subscripts)
1649 								fprintf(GLOBALS->vcd_save_handle,"%s%c%d\n",v->name,GLOBALS->hier_delimeter,v->msi);
1650 								else
1651 								fprintf(GLOBALS->vcd_save_handle,"%s[%d]\n",v->name,v->msi);
1652 							}
1653 							else
1654 							{
1655 							fprintf(GLOBALS->vcd_save_handle,"%s\n",v->name);
1656 							}
1657 						}
1658 					}
1659 					else
1660 					{
1661 					int i;
1662 
1663 					if(!GLOBALS->atomic_vectors)
1664 						{
1665 						fprintf(GLOBALS->vcd_save_handle,"#%s[%d:%d]",v->name,v->msi,v->lsi);
1666 						if(v->msi>v->lsi)
1667 							{
1668 							for(i=v->msi;i>=v->lsi;i--)
1669 								{
1670 								if(!GLOBALS->vcd_explicit_zero_subscripts)
1671 									fprintf(GLOBALS->vcd_save_handle," %s%c%d",v->name,GLOBALS->hier_delimeter,i);
1672 									else
1673 									fprintf(GLOBALS->vcd_save_handle," %s[%d]",v->name,i);
1674 								}
1675 							}
1676 							else
1677 							{
1678 							for(i=v->msi;i<=v->lsi;i++)
1679 								{
1680 								if(!GLOBALS->vcd_explicit_zero_subscripts)
1681 									fprintf(GLOBALS->vcd_save_handle," %s%c%d",v->name,GLOBALS->hier_delimeter,i);
1682 									else
1683 									fprintf(GLOBALS->vcd_save_handle," %s[%d]",v->name,i);
1684 								}
1685 							}
1686 						fprintf(GLOBALS->vcd_save_handle,"\n");
1687 						}
1688 						else
1689 						{
1690 						fprintf(GLOBALS->vcd_save_handle,"%s[%d:%d]\n",v->name,v->msi,v->lsi);
1691 						}
1692 					}
1693 				}
1694 
1695 			goto bail;
1696 			err:
1697 			if(v)
1698 				{
1699 				GLOBALS->error_count_vcd_c_1++;
1700 				if(v->name)
1701 					{
1702 					fprintf(stderr, "Near byte %d, $VAR parse error encountered with '%s'\n", (int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)), v->name);
1703 					free_2(v->name);
1704 					}
1705 					else
1706 					{
1707 					fprintf(stderr, "Near byte %d, $VAR parse error encountered\n", (int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1)));
1708 					}
1709 				if(v->id) free_2(v->id);
1710 				if(v->value) free_2(v->value);
1711 				free_2(v);
1712 				GLOBALS->pv_vcd_c_1 = NULL;
1713 				}
1714 
1715 			bail:
1716 			if(vtok!=V_END) sync_end(NULL);
1717 			break;
1718 			}
1719 		case T_ENDDEFINITIONS:
1720 			GLOBALS->header_over_vcd_c_1=1;	/* do symbol table management here */
1721 			create_sorted_table();
1722 			if((!GLOBALS->sorted_vcd_c_1)&&(!GLOBALS->indexed_vcd_c_1))
1723 				{
1724 				fprintf(stderr, "No symbols in VCD file..nothing to do!\n");
1725 				vcd_exit(255);
1726 				}
1727 			if(GLOBALS->error_count_vcd_c_1)
1728 				{
1729 				fprintf(stderr, "\n%d VCD parse errors encountered, exiting.\n", GLOBALS->error_count_vcd_c_1);
1730 				vcd_exit(255);
1731 				}
1732 			break;
1733 		case T_STRING:
1734 			if(!GLOBALS->header_over_vcd_c_1)
1735 				{
1736 				GLOBALS->header_over_vcd_c_1=1;	/* do symbol table management here */
1737 				create_sorted_table();
1738 				if((!GLOBALS->sorted_vcd_c_1)&&(!GLOBALS->indexed_vcd_c_1)) break;
1739 				}
1740 				{
1741 				/* catchall for events when header over */
1742 				if(GLOBALS->yytext_vcd_c_1[0]=='#')
1743 					{
1744 					TimeType tim;
1745 					tim=atoi_64(GLOBALS->yytext_vcd_c_1+1);
1746 
1747 					if(GLOBALS->start_time_vcd_c_1<0)
1748 						{
1749 						GLOBALS->start_time_vcd_c_1=tim;
1750 						}
1751 /* backtracking fix */
1752 						else
1753 						{
1754 						if(tim < GLOBALS->current_time_vcd_c_1)	/* avoid backtracking time counts which can happen on malformed files */
1755 							{
1756                                                         if(!GLOBALS->vcd_already_backtracked)
1757                                                                 {
1758                                                                 GLOBALS->vcd_already_backtracked = 1;
1759                                                                 fprintf(stderr, "VCDLOAD | Time backtracking detected in VCD file!\n");
1760                                                                 }
1761 #if 0
1762 							tim = GLOBALS->current_time_vcd_c_1;
1763 #endif
1764 							}
1765 						}
1766 
1767 					GLOBALS->current_time_vcd_c_1=tim;
1768 					if(GLOBALS->end_time_vcd_c_1<tim) GLOBALS->end_time_vcd_c_1=tim;	/* in case of malformed vcd files */
1769 					DEBUG(fprintf(stderr,"#"TTFormat"\n",tim));
1770 					}
1771 					else
1772 					{
1773 					parse_valuechange();
1774 					}
1775 				}
1776 			break;
1777 		case T_DUMPALL:	/* dump commands modify vals anyway so */
1778 		case T_DUMPPORTSALL:
1779 			break;	/* just loop through..                 */
1780 		case T_DUMPOFF:
1781 		case T_DUMPPORTSOFF:
1782 			GLOBALS->dumping_off_vcd_c_1=1;
1783 			/* if((!GLOBALS->blackout_regions)||((GLOBALS->blackout_regions)&&(GLOBALS->blackout_regions->bstart<=GLOBALS->blackout_regions->bend))) : remove redundant condition */
1784 			if((!GLOBALS->blackout_regions)||(GLOBALS->blackout_regions->bstart<=GLOBALS->blackout_regions->bend))
1785 				{
1786 				struct blackout_region_t *bt = calloc_2(1, sizeof(struct blackout_region_t));
1787 
1788 				bt->bstart = GLOBALS->current_time_vcd_c_1;
1789 				bt->next = GLOBALS->blackout_regions;
1790 				GLOBALS->blackout_regions = bt;
1791 				}
1792 			break;
1793 		case T_DUMPON:
1794 		case T_DUMPPORTSON:
1795 			GLOBALS->dumping_off_vcd_c_1=0;
1796 			if((GLOBALS->blackout_regions)&&(GLOBALS->blackout_regions->bstart>GLOBALS->blackout_regions->bend))
1797 				{
1798 				GLOBALS->blackout_regions->bend = GLOBALS->current_time_vcd_c_1;
1799 				}
1800 			break;
1801 		case T_DUMPVARS:
1802 		case T_DUMPPORTS:
1803 			if(GLOBALS->current_time_vcd_c_1<0)
1804 				{ GLOBALS->start_time_vcd_c_1=GLOBALS->current_time_vcd_c_1=GLOBALS->end_time_vcd_c_1=0; }
1805 			break;
1806 		case T_VCDCLOSE:
1807 			sync_end("VCDCLOSE:");
1808 			break;	/* next token will be '#' time related followed by $end */
1809 		case T_END:	/* either closure for dump commands or */
1810 			break;	/* it's spurious                       */
1811 		case T_UNKNOWN_KEY:
1812 			sync_end(NULL);	/* skip over unknown keywords */
1813 			break;
1814 		case T_EOF:
1815 			if((GLOBALS->blackout_regions)&&(GLOBALS->blackout_regions->bstart>GLOBALS->blackout_regions->bend))
1816 				{
1817 				GLOBALS->blackout_regions->bend = GLOBALS->current_time_vcd_c_1;
1818 				}
1819 			return;
1820 		default:
1821 			DEBUG(fprintf(stderr,"UNKNOWN TOKEN\n"));
1822 		}
1823 	}
1824 }
1825 
1826 
1827 /*******************************************************************************/
1828 
add_histent(TimeType tim,struct Node * n,char ch,int regadd,char * vector)1829 void add_histent(TimeType tim, struct Node *n, char ch, int regadd, char *vector)
1830 {
1831 struct HistEnt *he;
1832 char heval;
1833 
1834 if(!vector)
1835 {
1836 if(!n->curr)
1837 	{
1838 	he=histent_calloc();
1839         he->time=-1;
1840         he->v.h_val=AN_X;
1841 
1842 	n->curr=he;
1843 	n->head.next=he;
1844 
1845 	add_histent(tim,n,ch,regadd, vector);
1846 	}
1847 	else
1848 	{
1849 	if(regadd) { tim*=(GLOBALS->time_scale); }
1850 
1851 	if(ch=='0')              heval=AN_0; else
1852 	if(ch=='1')              heval=AN_1; else
1853         if((ch=='x')||(ch=='X')) heval=AN_X; else
1854         if((ch=='z')||(ch=='Z')) heval=AN_Z; else
1855         if((ch=='h')||(ch=='H')) heval=AN_H; else
1856         if((ch=='u')||(ch=='U')) heval=AN_U; else
1857         if((ch=='w')||(ch=='W')) heval=AN_W; else
1858         if((ch=='l')||(ch=='L')) heval=AN_L; else
1859         /* if(ch=='-') */        heval=AN_DASH;		/* default */
1860 
1861 	if((n->curr->v.h_val!=heval)||(tim==GLOBALS->start_time_vcd_c_1)||(n->vartype==ND_VCD_EVENT)||(GLOBALS->vcd_preserve_glitches)) /* same region == go skip */
1862         	{
1863 		if(n->curr->time>=tim) /* backtracking fix */
1864 			{
1865 			DEBUG(printf("Warning: Glitch at time ["TTFormat"] Signal [%p], Value [%c->%c].\n",
1866 				tim, n, AN_STR[n->curr->v.h_val], ch));
1867 			n->curr->v.h_val=heval;		/* we have a glitch! */
1868 
1869 			GLOBALS->num_glitches_vcd_c_2++;
1870 			if(!(n->curr->flags&HIST_GLITCH))
1871 				{
1872 				n->curr->flags|=HIST_GLITCH;	/* set the glitch flag */
1873 				GLOBALS->num_glitch_regions_vcd_c_2++;
1874 				}
1875 			}
1876 			else
1877 			{
1878                 	he=histent_calloc();
1879                 	he->time=tim;
1880                 	he->v.h_val=heval;
1881 
1882                 	n->curr->next=he;
1883                         if(n->curr->v.h_val==heval)
1884                                 {
1885                                 n->curr->flags|=HIST_GLITCH;    /* set the glitch flag */
1886                                 GLOBALS->num_glitch_regions_vcd_recoder_c_4++;
1887                                 }
1888 			n->curr=he;
1889                 	GLOBALS->regions+=regadd;
1890 			}
1891                 }
1892        }
1893 }
1894 else
1895 {
1896 switch(ch)
1897 	{
1898 	case 's': /* string */
1899 	{
1900 	if(!n->curr)
1901 		{
1902 		he=histent_calloc();
1903 		he->flags=(HIST_STRING|HIST_REAL);
1904 	        he->time=-1;
1905 	        he->v.h_vector=NULL;
1906 
1907 		n->curr=he;
1908 		n->head.next=he;
1909 
1910 		add_histent(tim,n,ch,regadd, vector);
1911 		}
1912 		else
1913 		{
1914 		if(regadd) { tim*=(GLOBALS->time_scale); }
1915 
1916 			if(n->curr->time>=tim) /* backtracking fix */
1917 				{
1918 				DEBUG(printf("Warning: String Glitch at time ["TTFormat"] Signal [%p].\n",
1919 					tim, n));
1920 				if(n->curr->v.h_vector) free_2(n->curr->v.h_vector);
1921 				n->curr->v.h_vector=vector;		/* we have a glitch! */
1922 
1923 				GLOBALS->num_glitches_vcd_c_2++;
1924 				if(!(n->curr->flags&HIST_GLITCH))
1925 					{
1926 					n->curr->flags|=HIST_GLITCH;	/* set the glitch flag */
1927 					GLOBALS->num_glitch_regions_vcd_c_2++;
1928 					}
1929 				}
1930 				else
1931 				{
1932 	                	he=histent_calloc();
1933 				he->flags=(HIST_STRING|HIST_REAL);
1934 	                	he->time=tim;
1935 	                	he->v.h_vector=vector;
1936 
1937 	                	n->curr->next=he;
1938 				n->curr=he;
1939 	                	GLOBALS->regions+=regadd;
1940 				}
1941 	       }
1942 	break;
1943 	}
1944 	case 'g': /* real number */
1945 	{
1946 	if(!n->curr)
1947 		{
1948 		he=histent_calloc();
1949 		he->flags=HIST_REAL;
1950 	        he->time=-1;
1951 #ifdef WAVE_HAS_H_DOUBLE
1952 		he->v.h_double = strtod("NaN", NULL);
1953 #else
1954 	        he->v.h_vector=NULL;
1955 #endif
1956 
1957 		n->curr=he;
1958 		n->head.next=he;
1959 
1960 		add_histent(tim,n,ch,regadd, vector);
1961 		}
1962 		else
1963 		{
1964 		if(regadd) { tim*=(GLOBALS->time_scale); }
1965 
1966 		if(
1967 #ifdef WAVE_HAS_H_DOUBLE
1968 		  (vector&&(n->curr->v.h_double!=*(double *)vector))
1969 #else
1970 		  (n->curr->v.h_vector&&vector&&(*(double *)n->curr->v.h_vector!=*(double *)vector))
1971 #endif
1972 			||(tim==GLOBALS->start_time_vcd_c_1)
1973 #ifndef WAVE_HAS_H_DOUBLE
1974 			||(!n->curr->v.h_vector)
1975 #endif
1976 			||(GLOBALS->vcd_preserve_glitches)||(GLOBALS->vcd_preserve_glitches_real)
1977 			) /* same region == go skip */
1978 	        	{
1979 			if(n->curr->time>=tim) /* backtracking fix */
1980 				{
1981 				DEBUG(printf("Warning: Real number Glitch at time ["TTFormat"] Signal [%p].\n",
1982 					tim, n));
1983 #ifdef WAVE_HAS_H_DOUBLE
1984 				n->curr->v.h_double = *((double *)vector);
1985 #else
1986 				if(n->curr->v.h_vector) free_2(n->curr->v.h_vector);
1987 				n->curr->v.h_vector=vector;		/* we have a glitch! */
1988 #endif
1989 				GLOBALS->num_glitches_vcd_c_2++;
1990 				if(!(n->curr->flags&HIST_GLITCH))
1991 					{
1992 					n->curr->flags|=HIST_GLITCH;	/* set the glitch flag */
1993 					GLOBALS->num_glitch_regions_vcd_c_2++;
1994 					}
1995 				}
1996 				else
1997 				{
1998 	                	he=histent_calloc();
1999 				he->flags=HIST_REAL;
2000 	                	he->time=tim;
2001 #ifdef WAVE_HAS_H_DOUBLE
2002 				he->v.h_double = *((double *)vector);
2003 #else
2004 	                	he->v.h_vector=vector;
2005 #endif
2006 	                	n->curr->next=he;
2007 				n->curr=he;
2008 	                	GLOBALS->regions+=regadd;
2009 				}
2010 	                }
2011 			else
2012 			{
2013 #ifndef WAVE_HAS_H_DOUBLE
2014 			free_2(vector);
2015 #endif
2016 			}
2017 #ifdef WAVE_HAS_H_DOUBLE
2018 		free_2(vector);
2019 #endif
2020 	       }
2021 	break;
2022 	}
2023 	default:
2024 	{
2025 	if(!n->curr)
2026 		{
2027 		he=histent_calloc();
2028 	        he->time=-1;
2029 	        he->v.h_vector=NULL;
2030 
2031 		n->curr=he;
2032 		n->head.next=he;
2033 
2034 		add_histent(tim,n,ch,regadd, vector);
2035 		}
2036 		else
2037 		{
2038 		if(regadd) { tim*=(GLOBALS->time_scale); }
2039 
2040 		if(
2041 		  (n->curr->v.h_vector&&vector&&(strcmp(n->curr->v.h_vector,vector)))
2042 			||(tim==GLOBALS->start_time_vcd_c_1)
2043 			||(!n->curr->v.h_vector)
2044 			||(GLOBALS->vcd_preserve_glitches)
2045 			) /* same region == go skip */
2046 	        	{
2047 			if(n->curr->time>=tim) /* backtracking fix */
2048 				{
2049 				DEBUG(printf("Warning: Glitch at time ["TTFormat"] Signal [%p], Value [%c->%c].\n",
2050 					tim, n, AN_STR[n->curr->v.h_val], ch));
2051 				if(n->curr->v.h_vector) free_2(n->curr->v.h_vector);
2052 				n->curr->v.h_vector=vector;		/* we have a glitch! */
2053 
2054 				GLOBALS->num_glitches_vcd_c_2++;
2055 				if(!(n->curr->flags&HIST_GLITCH))
2056 					{
2057 					n->curr->flags|=HIST_GLITCH;	/* set the glitch flag */
2058 					GLOBALS->num_glitch_regions_vcd_c_2++;
2059 					}
2060 				}
2061 				else
2062 				{
2063 	                	he=histent_calloc();
2064 	                	he->time=tim;
2065 	                	he->v.h_vector=vector;
2066 
2067 	                	n->curr->next=he;
2068 				n->curr=he;
2069 	                	GLOBALS->regions+=regadd;
2070 				}
2071 	                }
2072 			else
2073 			{
2074 			free_2(vector);
2075 			}
2076 	       }
2077 	break;
2078 	}
2079 	}
2080 }
2081 
2082 }
2083 
2084 
set_vcd_vartype(struct vcdsymbol * v,nptr n)2085 void set_vcd_vartype(struct vcdsymbol *v, nptr n)
2086 {
2087 unsigned char nvt;
2088 
2089 switch(v->vartype)
2090 	{
2091         case V_EVENT:           nvt = ND_VCD_EVENT; break;
2092         case V_PARAMETER:       nvt = ND_VCD_PARAMETER; break;
2093         case V_INTEGER:         nvt = ND_VCD_INTEGER; break;
2094         case V_REAL:            nvt = ND_VCD_REAL; break;
2095         case V_REG:             nvt = ND_VCD_REG; break;
2096         case V_SUPPLY0:         nvt = ND_VCD_SUPPLY0; break;
2097         case V_SUPPLY1:         nvt = ND_VCD_SUPPLY1; break;
2098         case V_TIME:            nvt = ND_VCD_TIME; break;
2099         case V_TRI:             nvt = ND_VCD_TRI; break;
2100         case V_TRIAND:          nvt = ND_VCD_TRIAND; break;
2101         case V_TRIOR:           nvt = ND_VCD_TRIOR; break;
2102         case V_TRIREG:          nvt = ND_VCD_TRIREG; break;
2103         case V_TRI0:            nvt = ND_VCD_TRI0; break;
2104         case V_TRI1:            nvt = ND_VCD_TRI1; break;
2105         case V_WAND:            nvt = ND_VCD_WAND; break;
2106         case V_WIRE:            nvt = ND_VCD_WIRE; break;
2107         case V_WOR:             nvt = ND_VCD_WOR; break;
2108         case V_PORT:            nvt = ND_VCD_PORT; break;
2109 	case V_STRINGTYPE:	nvt = ND_GEN_STRING; break;
2110 	case V_BIT:		nvt = ND_SV_BIT; break;
2111 	case V_LOGIC:		nvt = ND_SV_LOGIC; break;
2112 	case V_INT:		nvt = ND_SV_INT; break;
2113 	case V_SHORTINT:	nvt = ND_SV_SHORTINT; break;
2114 	case V_LONGINT:		nvt = ND_SV_LONGINT; break;
2115 	case V_BYTE:		nvt = ND_SV_BYTE; break;
2116 	case V_ENUM:		nvt = ND_SV_ENUM; break;
2117 	/* V_SHORTREAL as a type does not exist for VCD: is cast to V_REAL */
2118         default:                nvt = ND_UNSPECIFIED_DEFAULT; break;
2119 	}
2120 n->vartype = nvt;
2121 }
2122 
2123 
add_tail_histents(void)2124 static void add_tail_histents(void)
2125 {
2126 int j;
2127 struct vcdsymbol *v;
2128 
2129 /* dump out any pending events 1st (removed) */
2130 /* then do 'x' trailers */
2131 
2132 v=GLOBALS->vcdsymroot_vcd_c_1;
2133 while(v)
2134 	{
2135 	if((v->vartype==V_REAL)||(v->vartype==V_STRINGTYPE))
2136 		{
2137 		double *d;
2138 
2139 		d=malloc_2(sizeof(double));
2140 		*d=1.0;
2141 		add_histent(MAX_HISTENT_TIME-1, v->narray[0], 'g', 0, (char *)d);
2142 		}
2143 	else
2144 	if((v->size==1)||(!GLOBALS->atomic_vectors))
2145 	for(j=0;j<v->size;j++)
2146 		{
2147 		add_histent(MAX_HISTENT_TIME-1, v->narray[j], 'x', 0, NULL);
2148 		}
2149 	else
2150 		{
2151 		add_histent(MAX_HISTENT_TIME-1, v->narray[0], 'x', 0, (char *)calloc_2(1,sizeof(char)));
2152 		}
2153 
2154 	v=v->next;
2155 	}
2156 
2157 v=GLOBALS->vcdsymroot_vcd_c_1;
2158 while(v)
2159 	{
2160 	if((v->vartype==V_REAL)||(v->vartype==V_STRINGTYPE))
2161 		{
2162 		double *d;
2163 
2164 		d=malloc_2(sizeof(double));
2165 		*d=0.0;
2166 		add_histent(MAX_HISTENT_TIME, v->narray[0], 'g', 0, (char *)d);
2167 		}
2168 	else
2169 	if((v->size==1)||(!GLOBALS->atomic_vectors))
2170 	for(j=0;j<v->size;j++)
2171 		{
2172 		add_histent(MAX_HISTENT_TIME, v->narray[j], 'z', 0, NULL);
2173 		}
2174 	else
2175 		{
2176 		add_histent(MAX_HISTENT_TIME, v->narray[0], 'z', 0, (char *)calloc_2(1,sizeof(char)));
2177 		}
2178 
2179 	v=v->next;
2180 	}
2181 }
2182 
2183 /*******************************************************************************/
2184 
vcd_build_symbols(void)2185 static void vcd_build_symbols(void)
2186 {
2187 int j;
2188 int max_slen=-1;
2189 struct sym_chain *sym_chain=NULL, *sym_curr=NULL;
2190 int duphier=0;
2191 char hashdirty;
2192 struct vcdsymbol *v, *vprime;
2193 char *str = wave_alloca(1); /* quiet scan-build null pointer warning below */
2194 #ifdef _WAVE_HAVE_JUDY
2195 int ss_len, longest = 0;
2196 #endif
2197 
2198 v=GLOBALS->vcdsymroot_vcd_c_1;
2199 while(v)
2200 	{
2201 	int msi;
2202 	int delta;
2203 
2204 		{
2205 		int slen;
2206 		int substnode;
2207 
2208 		msi=v->msi;
2209 		delta=((v->lsi-v->msi)<0)?-1:1;
2210 		substnode=0;
2211 
2212 		slen=strlen(v->name);
2213 		str=(slen>max_slen)?(wave_alloca((max_slen=slen)+32)):(str); /* more than enough */
2214 		strcpy(str,v->name);
2215 
2216 		if((v->msi>=0)||(v->msi != v->lsi))
2217 			{
2218 			strcpy(str+slen,GLOBALS->vcd_hier_delimeter);
2219 			slen++;
2220 			}
2221 
2222 		if((vprime=bsearch_vcd(v->id, strlen(v->id)))!=v) /* hash mish means dup net */
2223 			{
2224 			if(v->size!=vprime->size)
2225 				{
2226 				fprintf(stderr,"ERROR: Duplicate IDs with differing width: %s %s\n", v->name, vprime->name);
2227 				}
2228 				else
2229 				{
2230 				substnode=1;
2231 				}
2232 			}
2233 
2234 		if(((v->size==1)||(!GLOBALS->atomic_vectors))&&(v->vartype!=V_REAL)&&(v->vartype!=V_STRINGTYPE))
2235 			{
2236 			struct symbol *s = NULL;
2237 
2238 			for(j=0;j<v->size;j++)
2239 				{
2240 				if(v->msi>=0)
2241 					{
2242 					if(!GLOBALS->vcd_explicit_zero_subscripts)
2243 						sprintf(str+slen,"%d",msi);
2244 						else
2245 						sprintf(str+slen-1,"[%d]",msi);
2246 					}
2247 
2248 				hashdirty=0;
2249 				if(symfind(str, NULL))
2250 					{
2251 					char *dupfix=(char *)malloc_2(max_slen+32);
2252 #ifndef _WAVE_HAVE_JUDY
2253 					hashdirty=1;
2254 #endif
2255 					DEBUG(fprintf(stderr,"Warning: %s is a duplicate net name.\n",str));
2256 
2257 					do sprintf(dupfix, "$DUP%d%s%s", duphier++, GLOBALS->vcd_hier_delimeter, str);
2258 						while(symfind(dupfix, NULL));
2259 
2260 					strcpy(str, dupfix);
2261 					free_2(dupfix);
2262 					duphier=0; /* reset for next duplicate resolution */
2263 					}
2264 					/* fallthrough */
2265 					{
2266 					s=symadd(str,hashdirty?hash(str):GLOBALS->hashcache);
2267 #ifdef _WAVE_HAVE_JUDY
2268                                         ss_len = strlen(str); if(ss_len >= longest) { longest = ss_len + 1; }
2269 #endif
2270 					s->n=v->narray[j];
2271 					if(substnode)
2272 						{
2273 						struct Node *n, *n2;
2274 
2275 						n=s->n;
2276 						n2=vprime->narray[j];
2277 						/* nname stays same */
2278 						n->head=n2->head;
2279 						n->curr=n2->curr;
2280 						/* harray calculated later */
2281 						n->numhist=n2->numhist;
2282 						}
2283 
2284 #ifndef _WAVE_HAVE_JUDY
2285 					s->n->nname=s->name;
2286 #endif
2287 					if(!GLOBALS->firstnode)
2288 					        {
2289 					        GLOBALS->firstnode=
2290 					        GLOBALS->curnode=calloc_2(1, sizeof(struct symchain));
2291 					        }
2292 					        else
2293 					        {
2294 					        GLOBALS->curnode->next=calloc_2(1, sizeof(struct symchain));
2295 					        GLOBALS->curnode=GLOBALS->curnode->next;
2296 					        }
2297 					GLOBALS->curnode->symbol=s;
2298 
2299 					GLOBALS->numfacs++;
2300 					DEBUG(fprintf(stderr,"Added: %s\n",str));
2301 					}
2302 				msi+=delta;
2303 				}
2304 
2305 			if((j==1)&&(v->root))
2306 				{
2307 				s->vec_root=(struct symbol *)v->root;		/* these will get patched over */
2308 				s->vec_chain=(struct symbol *)v->chain;		/* these will get patched over */
2309 				v->sym_chain=s;
2310 
2311 				if(!sym_chain)
2312 					{
2313 					sym_curr=(struct sym_chain *)calloc_2(1,sizeof(struct sym_chain));
2314 					sym_chain=sym_curr;
2315 					}
2316 					else
2317 					{
2318 					sym_curr->next=(struct sym_chain *)calloc_2(1,sizeof(struct sym_chain));
2319 					sym_curr=sym_curr->next;
2320 					}
2321 				sym_curr->val=s;
2322 				}
2323 			}
2324 			else	/* atomic vector */
2325 			{
2326 			if((v->vartype!=V_REAL)&&(v->vartype!=V_STRINGTYPE)&&(v->vartype!=V_INTEGER)&&(v->vartype!=V_PARAMETER))
2327 			/* if((v->vartype!=V_REAL)&&(v->vartype!=V_STRINGTYPE)) */
2328 				{
2329 				sprintf(str+slen-1,"[%d:%d]",v->msi,v->lsi);
2330 				/* 2d add */
2331                                 if((v->msi>v->lsi)&&((v->msi-v->lsi+1)!=v->size))
2332                                         {
2333                                         if((v->vartype!=V_EVENT)&&(v->vartype!=V_PARAMETER))
2334                                                 {
2335                                                 v->msi = v->size-1; v->lsi = 0;
2336                                                 }
2337                                         }
2338                                 else
2339                                 if((v->lsi>=v->msi)&&((v->lsi-v->msi+1)!=v->size))
2340                                         {
2341                                         if((v->vartype!=V_EVENT)&&(v->vartype!=V_PARAMETER))
2342                                                 {
2343                                                 v->lsi = v->size-1; v->msi = 0;
2344                                                 }
2345                                         }
2346 				}
2347 				else
2348 				{
2349 				*(str+slen-1)=0;
2350 				}
2351 
2352 
2353 			hashdirty=0;
2354 			if(symfind(str, NULL))
2355 				{
2356 				char *dupfix=(char *)malloc_2(max_slen+32);
2357 #ifndef _WAVE_HAVE_JUDY
2358 				hashdirty=1;
2359 #endif
2360 				DEBUG(fprintf(stderr,"Warning: %s is a duplicate net name.\n",str));
2361 
2362 				do sprintf(dupfix, "$DUP%d%s%s", duphier++, GLOBALS->vcd_hier_delimeter, str);
2363 					while(symfind(dupfix, NULL));
2364 
2365 				strcpy(str, dupfix);
2366 				free_2(dupfix);
2367 				duphier=0; /* reset for next duplicate resolution */
2368 				}
2369 				/* fallthrough */
2370 				{
2371 				struct symbol *s;
2372 
2373 				s=symadd(str,hashdirty?hash(str):GLOBALS->hashcache);	/* cut down on double lookups.. */
2374 #ifdef _WAVE_HAVE_JUDY
2375                                 ss_len = strlen(str); if(ss_len >= longest) { longest = ss_len + 1; }
2376 #endif
2377 				s->n=v->narray[0];
2378 				if(substnode)
2379 					{
2380 					struct Node *n, *n2;
2381 
2382 					n=s->n;
2383 					n2=vprime->narray[0];
2384 					/* nname stays same */
2385 					n->head=n2->head;
2386 					n->curr=n2->curr;
2387 					/* harray calculated later */
2388 					n->numhist=n2->numhist;
2389 					n->extvals=n2->extvals;
2390 					n->msi=n2->msi;
2391 					n->lsi=n2->lsi;
2392 					}
2393 					else
2394 					{
2395 					s->n->msi=v->msi;
2396 					s->n->lsi=v->lsi;
2397 
2398 					s->n->extvals=1;
2399 					}
2400 
2401 #ifndef _WAVE_HAVE_JUDY
2402 				s->n->nname=s->name;
2403 #endif
2404 				if(!GLOBALS->firstnode)
2405 				        {
2406 				        GLOBALS->firstnode=
2407 				        GLOBALS->curnode=calloc_2(1, sizeof(struct symchain));
2408 				        }
2409 				        else
2410 				        {
2411 				        GLOBALS->curnode->next=calloc_2(1, sizeof(struct symchain));
2412 				        GLOBALS->curnode=GLOBALS->curnode->next;
2413 				        }
2414 				GLOBALS->curnode->symbol=s;
2415 
2416 				GLOBALS->numfacs++;
2417 				DEBUG(fprintf(stderr,"Added: %s\n",str));
2418 				}
2419 			}
2420 		}
2421 
2422 	v=v->next;
2423 	}
2424 
2425 #ifdef _WAVE_HAVE_JUDY
2426 {
2427 Pvoid_t  PJArray = GLOBALS->sym_judy;
2428 PPvoid_t PPValue;
2429 char *Index = calloc_2(1, longest);
2430 
2431 for (PPValue  = JudySLFirst (PJArray, (uint8_t *)Index, PJE0);
2432          PPValue != (PPvoid_t) NULL;
2433          PPValue  = JudySLNext  (PJArray, (uint8_t *)Index, PJE0))
2434     {
2435         struct symbol *s = *(struct symbol **)PPValue;
2436         s->name = strdup_2(Index);
2437         s->n->nname = s->name;
2438     }
2439 
2440 free_2(Index);
2441 }
2442 #endif
2443 
2444 if(sym_chain)
2445 	{
2446 	sym_curr=sym_chain;
2447 	while(sym_curr)
2448 		{
2449 		sym_curr->val->vec_root= ((struct vcdsymbol *)sym_curr->val->vec_root)->sym_chain;
2450 
2451 		if ((struct vcdsymbol *)sym_curr->val->vec_chain)
2452 			sym_curr->val->vec_chain=((struct vcdsymbol *)sym_curr->val->vec_chain)->sym_chain;
2453 
2454 		DEBUG(printf("Link: ('%s') '%s' -> '%s'\n",sym_curr->val->vec_root->name, sym_curr->val->name, sym_curr->val->vec_chain?sym_curr->val->vec_chain->name:"(END)"));
2455 
2456 		sym_chain=sym_curr;
2457 		sym_curr=sym_curr->next;
2458 		free_2(sym_chain);
2459 		}
2460 	}
2461 }
2462 
2463 /*******************************************************************************/
2464 
vcd_sortfacs(void)2465 void vcd_sortfacs(void)
2466 {
2467 int i;
2468 
2469 GLOBALS->facs=(struct symbol **)malloc_2(GLOBALS->numfacs*sizeof(struct symbol *));
2470 GLOBALS->curnode=GLOBALS->firstnode;
2471 for(i=0;i<GLOBALS->numfacs;i++)
2472         {
2473         char *subst;
2474 #ifdef WAVE_HIERFIX
2475         char ch;
2476 #endif
2477         int len;
2478 	struct symchain *sc;
2479 
2480         GLOBALS->facs[i]=GLOBALS->curnode->symbol;
2481 	subst=GLOBALS->facs[i]->name;
2482         if((len=strlen(subst))>GLOBALS->longestname) GLOBALS->longestname=len;
2483 	sc = GLOBALS->curnode;
2484         GLOBALS->curnode=GLOBALS->curnode->next;
2485 	free_2(sc);
2486 #ifdef WAVE_HIERFIX
2487         while((ch=(*subst)))
2488                 {
2489                 if(ch==GLOBALS->hier_delimeter) { *subst=VCDNAM_HIERSORT; } /* forces sort at hier boundaries */
2490                 subst++;
2491                 }
2492 #endif
2493         }
2494 GLOBALS->firstnode=GLOBALS->curnode=NULL;
2495 
2496 /* quicksort(facs,0,numfacs-1); */	/* quicksort deprecated because it degenerates on sorted traces..badly.  very badly. */
2497 wave_heapsort(GLOBALS->facs,GLOBALS->numfacs);
2498 
2499 #ifdef WAVE_HIERFIX
2500 for(i=0;i<GLOBALS->numfacs;i++)
2501         {
2502         char *subst, ch;
2503 
2504         subst=GLOBALS->facs[i]->name;
2505         while((ch=(*subst)))
2506                 {
2507                 if(ch==VCDNAM_HIERSORT) { *subst=GLOBALS->hier_delimeter; } /* restore back to normal */
2508                 subst++;
2509                 }
2510 
2511 #ifdef DEBUG_FACILITIES
2512         printf("%-4d %s\n",i,facs[i]->name);
2513 #endif
2514         }
2515 #endif
2516 
2517 GLOBALS->facs_are_sorted=1;
2518 
2519 init_tree();
2520 for(i=0;i<GLOBALS->numfacs;i++)
2521 {
2522 char *n = GLOBALS->facs[i]->name;
2523 build_tree_from_name(n, i);
2524 
2525 if(GLOBALS->escaped_names_found_vcd_c_1)
2526 	{
2527         char *subst, ch;
2528         subst=GLOBALS->facs[i]->name;
2529         while((ch=(*subst)))
2530                 {
2531                 if(ch==VCDNAM_ESCAPE) { *subst=GLOBALS->hier_delimeter; } /* restore back to normal */
2532                 subst++;
2533                 }
2534 	}
2535 }
2536 treegraft(&GLOBALS->treeroot);
2537 treesort(GLOBALS->treeroot, NULL);
2538 
2539 if(GLOBALS->escaped_names_found_vcd_c_1)
2540 	{
2541 	treenamefix(GLOBALS->treeroot);
2542 	}
2543 }
2544 
2545 /*******************************************************************************/
2546 
vcd_cleanup(void)2547 static void vcd_cleanup(void)
2548 {
2549 struct slist *s, *s2;
2550 struct vcdsymbol *v, *vt;
2551 
2552 if(GLOBALS->indexed_vcd_c_1)
2553 	{
2554 	free_2(GLOBALS->indexed_vcd_c_1); GLOBALS->indexed_vcd_c_1=NULL;
2555 	}
2556 
2557 if(GLOBALS->sorted_vcd_c_1)
2558 	{
2559 	free_2(GLOBALS->sorted_vcd_c_1); GLOBALS->sorted_vcd_c_1=NULL;
2560 	}
2561 
2562 v=GLOBALS->vcdsymroot_vcd_c_1;
2563 while(v)
2564 	{
2565 	if(v->name) free_2(v->name);
2566 	if(v->id) free_2(v->id);
2567 	if(v->value) free_2(v->value);
2568 	if(v->narray) free_2(v->narray);
2569 	vt=v;
2570 	v=v->next;
2571 	free_2(vt);
2572 	}
2573 GLOBALS->vcdsymroot_vcd_c_1=GLOBALS->vcdsymcurr_vcd_c_1=NULL;
2574 
2575 if(GLOBALS->slisthier) { free_2(GLOBALS->slisthier); GLOBALS->slisthier=NULL; }
2576 s=GLOBALS->slistroot;
2577 while(s)
2578 	{
2579 	s2=s->next;
2580 	if(s->str)free_2(s->str);
2581 	free_2(s);
2582 	s=s2;
2583 	}
2584 
2585 GLOBALS->slistroot=GLOBALS->slistcurr=NULL; GLOBALS->slisthier_len=0;
2586 
2587 if(GLOBALS->vcd_is_compressed_vcd_c_1)
2588 	{
2589 	pclose(GLOBALS->vcd_handle_vcd_c_1);
2590 	GLOBALS->vcd_handle_vcd_c_1 = NULL;
2591 	}
2592 	else
2593 	{
2594 	fclose(GLOBALS->vcd_handle_vcd_c_1);
2595 	GLOBALS->vcd_handle_vcd_c_1 = NULL;
2596 	}
2597 
2598 if(GLOBALS->yytext_vcd_c_1)
2599 	{
2600 	free_2(GLOBALS->yytext_vcd_c_1);
2601 	GLOBALS->yytext_vcd_c_1=NULL;
2602 	}
2603 }
2604 
2605 /*******************************************************************************/
2606 
vcd_main(char * fname)2607 TimeType vcd_main(char *fname)
2608 {
2609 GLOBALS->pv_vcd_c_1=GLOBALS->rootv_vcd_c_1=NULL;
2610 GLOBALS->vcd_hier_delimeter[0]=GLOBALS->hier_delimeter;
2611 
2612 errno=0;	/* reset in case it's set for some reason */
2613 
2614 GLOBALS->yytext_vcd_c_1=(char *)malloc_2(GLOBALS->T_MAX_STR_vcd_c_1+1);
2615 
2616 if(!GLOBALS->hier_was_explicitly_set) /* set default hierarchy split char */
2617 	{
2618 	GLOBALS->hier_delimeter='.';
2619 	}
2620 
2621 if(suffix_check(fname, ".gz") || suffix_check(fname, ".zip"))
2622 	{
2623 	char *str;
2624 	int dlen;
2625 	dlen=strlen(WAVE_DECOMPRESSOR);
2626 	str=wave_alloca(strlen(fname)+dlen+1);
2627 	strcpy(str,WAVE_DECOMPRESSOR);
2628 	strcpy(str+dlen,fname);
2629 	GLOBALS->vcd_handle_vcd_c_1=popen(str,"r");
2630 	GLOBALS->vcd_is_compressed_vcd_c_1=~0;
2631 	}
2632 	else
2633 	{
2634 	if(strcmp("-vcd",fname))
2635 		{
2636 		GLOBALS->vcd_handle_vcd_c_1=fopen(fname,"rb");
2637 
2638 		if(GLOBALS->vcd_handle_vcd_c_1)
2639 			{
2640 			fseeko(GLOBALS->vcd_handle_vcd_c_1, 0, SEEK_END);	/* do status bar for vcd load */
2641 			GLOBALS->vcd_fsiz_vcd_c_1 = ftello(GLOBALS->vcd_handle_vcd_c_1);
2642 			fseeko(GLOBALS->vcd_handle_vcd_c_1, 0, SEEK_SET);
2643 			}
2644 
2645 		if(GLOBALS->vcd_warning_filesize < 0) GLOBALS->vcd_warning_filesize = VCD_SIZE_WARN;
2646 
2647 		if(GLOBALS->vcd_warning_filesize)
2648 		if(GLOBALS->vcd_fsiz_vcd_c_1 > (GLOBALS->vcd_warning_filesize * (1024 * 1024)))
2649 			{
2650 			fprintf(stderr, "Warning! File size is %d MB.  This might fail to load.\n"
2651                                         "Consider converting it to the FST database format instead.  (See the\n"
2652                                         "vcd2fst(1) manpage for more information.)\n"
2653 					"To disable this warning, set rc variable vcd_warning_filesize to zero.\n"
2654 					"Alternatively, use the -o, --optimize command line option to convert to LXT2.\n\n",
2655 						(int)(GLOBALS->vcd_fsiz_vcd_c_1/(1024*1024)));
2656 			}
2657 		}
2658 		else
2659 		{
2660 		GLOBALS->vcd_handle_vcd_c_1=stdin;
2661 		GLOBALS->splash_disable = 1;
2662 		}
2663 	GLOBALS->vcd_is_compressed_vcd_c_1=0;
2664 	}
2665 
2666 if(!GLOBALS->vcd_handle_vcd_c_1)
2667 	{
2668 	fprintf(stderr, "Error opening %s .vcd file '%s'.\n",
2669 		GLOBALS->vcd_is_compressed_vcd_c_1?"compressed":"", fname);
2670 	perror("Why");
2671 	vcd_exit(255);
2672 	}
2673 
2674 /* SPLASH */				splash_create();
2675 
2676 sym_hash_initialize(GLOBALS);
2677 getch_alloc();		/* alloc membuff for vcd getch buffer */
2678 
2679 build_slisthier();
2680 
2681 vcd_parse();
2682 if(GLOBALS->varsplit_vcd_c_1)
2683 	{
2684 	free_2(GLOBALS->varsplit_vcd_c_1);
2685 	GLOBALS->varsplit_vcd_c_1=NULL;
2686 	}
2687 
2688 if((!GLOBALS->sorted_vcd_c_1)&&(!GLOBALS->indexed_vcd_c_1))
2689 	{
2690 	fprintf(stderr, "No symbols in VCD file..is it malformed?  Exiting!\n");
2691 	vcd_exit(255);
2692 	}
2693 add_tail_histents();
2694 
2695 if(GLOBALS->vcd_save_handle) { fclose(GLOBALS->vcd_save_handle); GLOBALS->vcd_save_handle = NULL; }
2696 
2697 fprintf(stderr, "["TTFormat"] start time.\n["TTFormat"] end time.\n", GLOBALS->start_time_vcd_c_1*GLOBALS->time_scale, GLOBALS->end_time_vcd_c_1*GLOBALS->time_scale);
2698 if(GLOBALS->num_glitches_vcd_c_2) fprintf(stderr, "Warning: encountered %d glitch%s across %d glitch region%s.\n",
2699 		GLOBALS->num_glitches_vcd_c_2, (GLOBALS->num_glitches_vcd_c_2!=1)?"es":"",
2700 		GLOBALS->num_glitch_regions_vcd_c_2, (GLOBALS->num_glitch_regions_vcd_c_2!=1)?"s":"");
2701 
2702 if(GLOBALS->vcd_fsiz_vcd_c_1)
2703         {
2704         splash_sync(GLOBALS->vcd_fsiz_vcd_c_1, GLOBALS->vcd_fsiz_vcd_c_1);
2705 	GLOBALS->vcd_fsiz_vcd_c_1 = 0;
2706         }
2707 else
2708 if(GLOBALS->vcd_is_compressed_vcd_c_1)
2709 	{
2710         splash_sync(1,1);
2711 	GLOBALS->vcd_fsiz_vcd_c_1 = 0;
2712 	}
2713 
2714 GLOBALS->min_time=GLOBALS->start_time_vcd_c_1*GLOBALS->time_scale;
2715 GLOBALS->max_time=GLOBALS->end_time_vcd_c_1*GLOBALS->time_scale;
2716 GLOBALS->global_time_offset = GLOBALS->global_time_offset * GLOBALS->time_scale;
2717 
2718 if((GLOBALS->min_time==GLOBALS->max_time)&&(GLOBALS->max_time==LLDescriptor(-1)))
2719         {
2720         fprintf(stderr, "VCD times range is equal to zero.  Exiting.\n");
2721         vcd_exit(255);
2722         }
2723 
2724 vcd_build_symbols();
2725 vcd_sortfacs();
2726 vcd_cleanup();
2727 
2728 getch_free();		/* free membuff for vcd getch buffer */
2729 
2730 if(GLOBALS->blackout_regions)
2731         {
2732         struct blackout_region_t *bt = GLOBALS->blackout_regions;
2733         while(bt)
2734                 {
2735                 bt->bstart *= GLOBALS->time_scale;
2736                 bt->bend *= GLOBALS->time_scale;
2737                 bt = bt->next;
2738                 }
2739         }
2740 
2741 GLOBALS->is_vcd=~0;
2742 
2743 /* SPLASH */                            splash_finalize();
2744 return(GLOBALS->max_time);
2745 }
2746 
2747 /*******************************************************************************/
2748 
2749