1 /*
2  * Copyright (c) 2009-2014 Tony Bybell.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include <config.h>
24 
25 #if HAVE_GETOPT_H
26 #include <getopt.h>
27 #endif
28 
29 #include "fst/fstapi.h"
30 #include "../../contrib/rtlbrowse/jrb.h"
31 #include "wave_locale.h"
32 
33 #ifdef EXTLOAD_SUFFIX
34 #ifdef EXTCONV_PATH
35 #define VCD2FST_EXTLOAD_CONV
36 #endif
37 #endif
38 
39 #ifdef EXT2LOAD_SUFFIX
40 #ifdef EXT2CONV_PATH
41 #define VCD2FST_EXT2LOAD_CONV
42 #endif
43 #endif
44 
45 #ifdef EXT3LOAD_SUFFIX
46 #ifdef EXT3CONV_PATH
47 #define VCD2FST_EXT3LOAD_CONV
48 #endif
49 #endif
50 
51 #if defined(VCD2FST_EXTLOAD_CONV) || defined(VCD2FST_EXT2LOAD_CONV) || defined(VCD2FST_EXT3LOAD_CONV)
52 #define VCD2FST_EXTLOADERS_CONV
53 #endif
54 
55 static uint32_t var_direction_idx = 0;
56 static unsigned char *var_direction = NULL;
57 
58 
realloc_2(void * ptr,size_t siz)59 static void *realloc_2(void *ptr, size_t siz) /* cppcheck */
60 {
61 void *pnt = realloc(ptr, siz);
62 if(!pnt)
63 	{
64 	fprintf(stderr, "ERROR: Out of memory in realloc(), exiting!\n"); /* normally free(ptr) here */
65 	exit(255);
66 	}
67 
68 return(pnt);
69 }
70 
71 
72 /*********************************************************/
73 /*** vvv extload component type name determination vvv ***/
74 /*********************************************************/
75 
76 #if defined(VCD2FST_EXTLOAD_CONV)
77 
78 #ifdef _WAVE_HAVE_JUDY
79 #include <Judy.h>
80 Pvoid_t  PJArray = NULL;
81 #else
82 JRB comp_name_jrb = NULL;
83 #endif
84 
85 static const char *fst_scope_name = NULL;
86 static uint32_t numfacs = 0;
87 
get_info(FILE * extload)88 static char *get_info(FILE *extload)
89 {
90 static char sbuff[65537];
91 char * rc;
92 
93 for(;;)
94         {
95         rc = fgets(sbuff, 65536, extload);
96 	if(!rc)
97                 {
98                 return(NULL);
99                 }
100 
101 	switch(rc[0])
102 		{
103                 case 'v':
104                         if(!strncmp("var creation cnt", rc, 16))
105                                 {
106                                 char *pnt = strchr(rc+16, ':');
107                                 if(pnt)
108                                         {
109                                         pnt++;
110                                         sscanf(pnt, "%u", &numfacs);
111                                         }
112                                 }
113 			break;
114 
115 		default:
116 			break;
117 		}
118 	}
119 }
120 
get_scopename(void * xc,FILE * extload)121 static char *get_scopename(void *xc, FILE *extload)
122 {
123 static char sbuff[65537];
124 char * rc;
125 #ifdef _WAVE_HAVE_JUDY
126 PPvoid_t PPValue;
127 #else
128 JRB str;
129 Jval jv;
130 #endif
131 
132 for(;;)
133         {
134         rc = fgets(sbuff, 65536, extload);
135         if(rc)
136 		{
137                 if(isspace(rc[0]))
138                         {
139                         char sbuff2[65537];
140 
141                         sbuff2[0] = 0;
142 
143                         if(strstr(rc+1, "Struct Name:"))
144                                 {
145                                 sscanf(rc+14,"%s", sbuff2);
146                                 if(sbuff2[0])
147                                         {
148                                         sprintf(rc, "Scope: vcd_struct %s NULL\n", sbuff2);
149                                         }
150                                 }
151                         else
152                         if(strstr(rc+1, "Struct End"))
153                                 {
154                                 sprintf(rc, "Upscope:\n");
155                                 }
156 			}
157 		}
158 	else
159                 {
160                 return(NULL);
161                 }
162 
163 	if(rc[0] == 'V')
164 		{
165                 if(!strncmp("Var: ", rc, 5))
166                         {
167                         char *pnt = rc + 5;
168                         char *pntd = strrchr(pnt, ':');
169 
170                         if(pntd)
171                                 {
172                                 unsigned char vd = FST_VD_IMPLICIT;
173 
174                                 pntd = strchr(pntd, ' ');
175                                 if(pntd)
176                                         {
177                                         pntd++;
178                                         if(*pntd == 'o')
179                                                 {
180                                                 vd = FST_VD_OUTPUT;
181                                                 }
182                                         else
183                                         if(!strncmp(pntd, "in", 2))
184                                                 {
185                                                 vd = (pntd[2] == 'p') ? FST_VD_INPUT : FST_VD_INOUT;
186                                                 }
187                                         }
188 
189 				var_direction[var_direction_idx++] = vd;
190                                 }
191 			}
192 		}
193 	else
194         if(rc[0] == 'S')
195                 {
196                 if(!strncmp(rc, "Scope:", 6))
197                         {
198                         char vht[2048];
199                         char cname[2048];
200                         char ctype[2048];
201 			int mtype = FST_ST_VCD_MODULE;
202 
203 			cname[0] = ctype[1] = 0;
204 
205                         sscanf(rc+6, "%s %s %s", vht, cname, ctype+1);
206 			if(!strncmp("vcd_", vht, 4))
207 				{
208 				switch(vht[4])
209 					{
210 					case 'g':	mtype = FST_ST_VCD_GENERATE; break; /* other code looks for non-modules to replace type with */
211 					case 's':	mtype = FST_ST_VCD_STRUCT;   break; /* other code looks for non-modules to replace type with */
212 					default:	break;
213 					}
214 				}
215 			else
216 			if(!strncmp("sv_", vht, 3))
217 				{
218 				switch(vht[3])
219 					{
220 					case 'i':	mtype = FST_ST_VCD_INTERFACE; break; /* other code looks for non-modules to replace type with */
221 					default:	break;
222 					}
223 				}
224                         else
225                         if(!strncmp(vht, "vhdl_", 5))
226                                 {
227                                 switch(vht[5])
228                                         {
229                                         case 'a':       mtype = FST_ST_VHDL_ARCHITECTURE; break;
230                                         case 'r':       mtype = FST_ST_VHDL_RECORD; break;
231                                         case 'b':       mtype = FST_ST_VHDL_BLOCK; break;
232                                         case 'g':       mtype = FST_ST_VHDL_GENERATE; break;
233                                         case 'i':       mtype = FST_ST_VHDL_IF_GENERATE; break;
234                                         case 'f':       mtype = (vht[6] == 'u') ? FST_ST_VHDL_FUNCTION : FST_ST_VHDL_FOR_GENERATE; break;
235                                         case 'p':       mtype = (!strncmp(vht+6, "roces", 5)) ? FST_ST_VHDL_PROCESS: FST_ST_VHDL_PROCEDURE; break;
236                                         default:        break;
237                                         }
238                                 }
239 
240 			ctype[0] = mtype + 1; /* bias for zero terminated string */
241 
242                         fst_scope_name = fstReaderPushScope(xc, cname, NULL);
243 
244 			/* process fst_scope_name + cname vs ctype here */
245 			if((strcmp(ctype+1, "NULL") && strcmp(cname, ctype+1)) || (mtype != FST_ST_VCD_MODULE))
246 				{
247 #ifdef _WAVE_HAVE_JUDY
248 				PPValue = JudySLIns(&PJArray, (uint8_t *)fst_scope_name, PJE0);
249 				if(!*((char **)PPValue))
250 					{
251 					*((char **)PPValue) = strdup(ctype);
252 					}
253 #else
254 				char cstring[65537];
255 				strcpy(cstring, fst_scope_name);
256 				str = jrb_find_str(comp_name_jrb, cstring);
257 				if(!str)
258 					{
259 					jv.s = strdup(ctype);
260 					jrb_insert_str(comp_name_jrb, strdup(cstring), jv);
261 					}
262 #endif
263 				}
264                         }
265                 }
266         else
267         if(rc[0] == 'U')
268                 {
269                 fst_scope_name = fstReaderPopScope(xc);
270                 }
271         }
272 
273 return(rc);
274 }
275 
276 
iter_scope(char * fname)277 static void iter_scope(char *fname)
278 {
279 char sbuff[65537];
280 FILE *extload;
281 void *xc = fstReaderOpenForUtilitiesOnly();
282 
283 sprintf(sbuff, "%s -info %s 2>&1", EXTLOAD_PATH, fname);
284 extload = popen(sbuff, "r");
285 if(extload)
286 	{
287 	while(get_info(extload));
288 	pclose(extload);
289 	}
290 
291 if(numfacs)
292 	{
293 	var_direction = calloc(numfacs, sizeof(unsigned char));
294 	var_direction_idx = 0;
295 	}
296 
297 sprintf(sbuff, "%s -tree %s 2>&1", EXTLOAD_PATH, fname);
298 extload = popen(sbuff, "r");
299 if(extload)
300 	{
301 	while(get_scopename(xc, extload));
302 	pclose(extload);
303 	}
304 
305 var_direction_idx = 0;
306 
307 fstReaderClose(xc); /* corresponds to fstReaderOpenForUtilitiesOnly() */
308 }
309 
310 
dealloc_scope(void)311 static void dealloc_scope(void)
312 {
313 #ifdef _WAVE_HAVE_JUDY
314 PPvoid_t PPValue;
315 
316 if(PJArray)
317         {
318         char Index[65537];
319 	Index[0] = 0;
320 
321         for (PPValue  = JudySLFirst (PJArray, (uint8_t *)Index, PJE0);
322                  PPValue != (PPvoid_t) NULL;
323                  PPValue  = JudySLNext  (PJArray, (uint8_t *)Index, PJE0))
324             {
325 		free(*(char **)PPValue);
326             }
327 
328         JudySLFreeArray(&PJArray, PJE0);
329         PJArray = NULL;
330         }
331 #else
332 if(comp_name_jrb)
333 	{
334         JRB node;
335 	char *Index;
336 
337         jrb_traverse(node, comp_name_jrb)
338             {
339                 Index = node->key.s;
340                 free(Index);
341                 Index = node->val.s;
342                 free(Index);
343             }
344 
345         jrb_free_tree(comp_name_jrb);
346         comp_name_jrb = NULL;
347 	}
348 #endif
349 }
350 
351 #endif
352 
353 /*********************************************************/
354 /*** ^^^ extload component type name determination ^^^ ***/
355 /*********************************************************/
356 
atoi_2(const unsigned char * s)357 static uint64_t atoi_2(const unsigned char *s)
358 {
359 uint64_t res = 0;
360 unsigned char ch;
361 
362 ch = *s - '0';
363 while(*s && (ch > 9))
364         {
365         s++;
366 	ch = *s - '0';
367         }
368 
369 while(ch < 10)
370         {
371         s++;
372         res *= 10;
373         res += ch;
374 	ch = *s - '0';
375         }
376 
377 return(res);
378 }
379 
380 
getline_replace(char ** wbuf,char ** buf,size_t * len,FILE * f)381 static inline int getline_replace(char **wbuf, char **buf, size_t *len, FILE *f)
382 {
383 char *fgets_rc;
384 
385 if(!*wbuf)
386 	{
387 	*len = 32767;
388 	*wbuf = malloc((*len) + 1);
389 	(*wbuf)[*len] = 1;
390 	}
391 
392 (*wbuf)[0] = 0;
393 fgets_rc = fgets(*wbuf, (*len) + 1, f);
394 while(((*wbuf)[*len] != 1) && !feof(f))
395 	{
396 	/* fprintf(stderr, "overflow %d\n", (int)(*len)); */
397 	*wbuf = realloc_2(*wbuf, (*len) * 2 + 1);
398 	(*wbuf)[(*len) * 2] = 1;
399 
400 	fgets_rc = fgets(*wbuf + (*len), (*len) + 1, f);
401 	*len = 2 * (*len);
402 	}
403 
404 *buf = *wbuf;
405 while(*(buf)[0]==' ') { (*buf)++; } /* verilator leading spaces fix */
406 
407 if((!(*buf)[0])||(!fgets_rc))
408 	{
409 	return(0);
410 	}
411 	else
412 	{
413 	return(1);
414 	}
415 }
416 
417 JRB vcd_ids = NULL;
418 
vcdid_hash(char * s,int len)419 static unsigned int vcdid_hash(char *s, int len)
420 {
421 unsigned int val=0;
422 int i;
423 
424 s += len;
425 
426 for(i=0;i<len;i++)
427         {
428 	val *= 94;
429         val += ((unsigned char)*(--s)) - 32;
430         }
431 
432 return(val);
433 }
434 
435 int pack_type = FST_WR_PT_LZ4;  /* set to fstWriterPackType */
436 int compression_explicitly_set = 0;
437 int repack_all = 0; /* 0 is normal, 1 does the repack (via fstapi) at end */
438 int parallel_mode = 0; /* 0 is is single threaded, 1 is multi-threaded */
439 
440 
441 #ifdef VCD2FST_EXTLOADERS_CONV
suffix_check(const char * s,const char * sfx)442 static int suffix_check(const char *s, const char *sfx)
443 {
444 size_t sfxlen = strlen(sfx);
445 return((strlen(s)>=sfxlen)&&(!strcasecmp(s+strlen(s)-sfxlen,sfx)));
446 }
447 #endif
448 
449 
fst_main(char * vname,char * fstname)450 int fst_main(char *vname, char *fstname)
451 {
452 FILE *f;
453 char *buf = NULL, *wbuf = NULL;
454 size_t glen = 0;
455 void *ctx;
456 int line = 0;
457 int ss;
458 fstHandle returnedhandle;
459 JRB node;
460 uint64_t prev_tim = 0;
461 ssize_t bin_fixbuff_len = 65537;
462 char *bin_fixbuff = NULL;
463 int hash_kill = 0;
464 unsigned int hash_max = 0;
465 int *node_len_array = NULL;
466 int is_popen = 0;
467 #ifdef VCD2FST_EXTLOAD_CONV
468 int is_extload = 0;
469 void *xc = NULL;
470 #endif
471 int port_encountered = 0;
472 
473 bin_fixbuff = malloc(bin_fixbuff_len);
474 
475 if(!strcmp("-", vname))
476 	{
477 	f = stdin;
478 	}
479 	else
480 	{
481 #ifdef VCD2FST_EXTLOAD_CONV
482 	if(suffix_check(vname, "."EXTLOAD_SUFFIX) || suffix_check(vname, "."EXTLOAD_SUFFIX".gz") || suffix_check(vname, "."EXTLOAD_SUFFIX".bz2"))
483 		{
484 		sprintf(bin_fixbuff, EXTCONV_PATH" %s", vname);
485 		f = popen(bin_fixbuff, "r");
486 		is_popen = 1;
487 		is_extload = 1;
488 #ifndef _WAVE_HAVE_JUDY
489 		comp_name_jrb = make_jrb();
490 #endif
491 		iter_scope(vname);
492 		}
493 		else
494 #endif
495 		{
496 #ifdef VCD2FST_EXT2LOAD_CONV
497 		if(suffix_check(vname, "."EXT2LOAD_SUFFIX))
498 			{
499 			sprintf(bin_fixbuff, EXT2CONV_PATH" %s", vname);
500 			f = popen(bin_fixbuff, "r");
501 			is_popen = 1;
502 			}
503 			else
504 #endif
505 #ifdef VCD2FST_EXT3LOAD_CONV
506 		if(suffix_check(vname, "."EXT3LOAD_SUFFIX))
507 			{
508 			sprintf(bin_fixbuff, EXT3CONV_PATH" %s", vname);
509 			f = popen(bin_fixbuff, "r");
510 			is_popen = 1;
511 			}
512 			else
513 #endif
514 			{
515 			f = fopen(vname, "rb");
516 			}
517 		}
518 	}
519 
520 if(!f)
521 	{
522 	printf("Could not open '%s', exiting.\n", vname);
523 	free(bin_fixbuff); bin_fixbuff = NULL;
524 	free(vname); free(fstname);
525 	exit(255);
526 	}
527 
528 ctx = fstWriterCreate(fstname, 1);
529 
530 if(!ctx)
531 	{
532 	printf("Could not open '%s', exiting.\n", fstname);
533 	free(bin_fixbuff); bin_fixbuff = NULL;
534 	free(vname); free(fstname);
535 	fclose(f);
536 	exit(255);
537 	}
538 
539 #if defined(VCD2FST_EXTLOAD_CONV)
540 if(is_popen && is_extload)
541 	{
542 	xc = fstReaderOpenForUtilitiesOnly();
543 	}
544 #endif
545 
546 vcd_ids = make_jrb();
547 fstWriterSetPackType(ctx, pack_type);
548 fstWriterSetRepackOnClose(ctx, repack_all);
549 fstWriterSetParallelMode(ctx, parallel_mode);
550 
551 while(!feof(f))
552 	{
553 	char *buf1;
554 
555 	ss = getline_replace(&wbuf, &buf, &glen, f);
556 	if(!ss)
557 		{
558 		break;
559 		}
560 	line++;
561 
562 	if(buf[0] != '$') continue;
563 	buf1 = buf + 1;
564 
565 	if(!strncmp(buf1, "var", 3))
566 		{
567 		char *st = strtok(buf+5, " \t");
568 		enum fstVarType vartype;
569 		int len;
570 		char *nam;
571 		unsigned int hash;
572 
573 		if(!st)
574 			{
575 			continue; /* variable declaration not on a single line */
576 			}
577 
578 		vartype = FST_VT_VCD_WIRE;
579 		switch(st[0])
580 			{
581 			case 'w':
582 				if(!strcmp(st, "wire"))
583 					{
584 					}
585 				else
586 				if(!strcmp(st, "wand"))
587 					{
588 					vartype = FST_VT_VCD_WAND;
589 					}
590 				else
591 				if(!strcmp(st, "wor"))
592 					{
593 					vartype = FST_VT_VCD_WOR;
594 					}
595 				break;
596 
597 			case 'r':
598 				if(!strcmp(st, "reg"))
599 					{
600 					vartype = FST_VT_VCD_REG;
601 					}
602 				else
603 				if(!strcmp(st, "real"))
604 					{
605 					vartype = FST_VT_VCD_REAL;
606 					}
607 				else
608 				if(!strcmp(st, "real_parameter"))
609 					{
610 					vartype = FST_VT_VCD_REAL_PARAMETER;
611 					}
612 				else
613 				if(!strcmp(st, "realtime"))
614 					{
615 					vartype = FST_VT_VCD_REALTIME;
616 					}
617 				break;
618 
619 			case 'p':
620 				if(!strcmp(st, "parameter"))
621 					{
622 					vartype = FST_VT_VCD_PARAMETER;
623 					}
624 				else
625 				if(!strcmp(st, "port"))
626 					{
627 					vartype = FST_VT_VCD_PORT;
628 					port_encountered = 1;
629 					}
630 				break;
631 
632 			case 'i':
633 				if(!strcmp(st, "integer"))
634 					{
635 					vartype = FST_VT_VCD_INTEGER;
636 					}
637 				else
638 				if(!strcmp(st, "int"))
639 					{
640 					vartype = FST_VT_SV_INT;
641 					}
642 				break;
643 
644 			case 'e':
645 				if(!strcmp(st, "event"))
646 					{
647 					vartype = FST_VT_VCD_EVENT;
648 					}
649 				else
650 				if(!strcmp(st, "enum"))
651 					{
652 					vartype = FST_VT_SV_ENUM;
653 					}
654 				break;
655 
656 			case 'b':
657 				if(!strcmp(st, "bit"))
658 					{
659 					vartype = FST_VT_SV_BIT;
660 					}
661 				else
662 				if(!strcmp(st, "byte"))
663 					{
664 					vartype = FST_VT_SV_BYTE;
665 					}
666 				break;
667 
668 			case 'l':
669 				if(!strcmp(st, "logic"))
670 					{
671 					vartype = FST_VT_SV_LOGIC;
672 					}
673 				else
674 				if(!strcmp(st, "longint"))
675 					{
676 					vartype = FST_VT_SV_LONGINT;
677 					}
678 				break;
679 
680 			case 's':
681 				if(!strcmp(st, "supply1"))
682 					{
683 					vartype = FST_VT_VCD_SUPPLY1;
684 					}
685 				else
686 				if(!strcmp(st, "supply0"))
687 					{
688 					vartype = FST_VT_VCD_SUPPLY0;
689 					}
690 				else
691 				if(!strcmp(st, "string"))
692 					{
693 					vartype = FST_VT_GEN_STRING;
694 					}
695 				else
696 				if(!strcmp(st, "shortint"))
697 					{
698 					vartype = FST_VT_SV_SHORTINT;
699 					}
700 				else
701 				if(!strcmp(st, "shortreal"))
702 					{
703 					vartype = FST_VT_SV_SHORTREAL;
704 					}
705 				else
706 				if(!strcmp(st, "sparray"))
707 					{
708 					vartype = FST_VT_VCD_SPARRAY;
709 					}
710 				break;
711 
712 			case 't':
713 				if(!strcmp(st, "time"))
714 					{
715 					vartype = FST_VT_VCD_TIME;
716 					}
717 				else
718 				if(!strcmp(st, "tri"))
719 					{
720 					vartype = FST_VT_VCD_TRI;
721 					}
722 				else
723 				if(!strcmp(st, "triand"))
724 					{
725 					vartype = FST_VT_VCD_TRIAND;
726 					}
727 				else
728 				if(!strcmp(st, "trior"))
729 					{
730 					vartype = FST_VT_VCD_TRIOR;
731 					}
732 				else
733 				if(!strcmp(st, "trireg"))
734 					{
735 					vartype = FST_VT_VCD_TRIREG;
736 					}
737 				else
738 				if(!strcmp(st, "tri0"))
739 					{
740 					vartype = FST_VT_VCD_TRI0;
741 					}
742 				else
743 				if(!strcmp(st, "tri1"))
744 					{
745 					vartype = FST_VT_VCD_TRI1;
746 					}
747 				break;
748 
749 			default:
750 				break;
751 			}
752 
753 		st = strtok(NULL, " \t");
754 		len = atoi(st);
755 		switch(vartype)
756 			{
757 			case FST_VT_VCD_PORT:
758 				if(*st == '[') /* VCS extension, so reparse */
759 					{
760 					int p_hi = atoi(st+1);
761 					int p_lo = p_hi;
762 					char *p_colon = strchr(st+1, ':');
763 					if(p_colon)
764 						{
765 						p_lo = atoi(p_colon+1);
766 						}
767 
768 					if(p_hi > p_lo)
769 						{
770 						len = p_hi - p_lo + 1;
771 						}
772 						else
773 						{
774 						len = p_lo - p_hi + 1;
775 						}
776 					}
777 
778 				len = (len * 3) + 2;
779 				break;
780 			case FST_VT_GEN_STRING: len = 0; break;
781 			case FST_VT_VCD_EVENT: len = (len != 0) ? len : 1;  break;
782 			default:
783 				if(len == 0) { len = 1; }
784 				break;
785 			}
786 
787 		st = strtok(NULL, " \t"); /* vcdid */
788 		hash = vcdid_hash(st, strlen(st));
789 
790 		if(hash == (hash_max+1))
791 			{
792 			hash_max = hash;
793 			}
794 		else
795 		if((hash>0)&&(hash<=hash_max))
796 			{
797 			/* general case with aliases */
798 			}
799 		else
800 			{
801 			hash_kill = 1;
802 			}
803 
804 		nam = strtok(NULL, " \t"); /* name */
805 		st = strtok(NULL, " \t"); /* $end */
806 
807 		if(st)
808 			{
809 			if(strncmp(st, "$end", 4))
810 				{
811 				*(st-1) = ' ';
812 				}
813 
814 			node = jrb_find_int(vcd_ids, hash);
815 			if(!node)
816 				{
817 				Jval val;
818 				returnedhandle = fstWriterCreateVar(ctx, vartype, !var_direction ? FST_VD_IMPLICIT : var_direction[var_direction_idx++], len, nam, 0);
819 				val.i = returnedhandle;
820 				jrb_insert_int(vcd_ids, hash, val)->val2.i = len;
821 				}
822 				else
823 				{
824 				fstWriterCreateVar(ctx, vartype, !var_direction ? FST_VD_IMPLICIT : var_direction[var_direction_idx++], node->val2.i, nam, node->val.i);
825 				}
826 
827 #if defined(VCD2FST_EXTLOAD_CONV)
828 			if(var_direction)
829 				{
830 				if(var_direction_idx == numfacs)
831 					{
832 					free(var_direction);
833 					var_direction = NULL;
834 					}
835 				}
836 #endif
837 			}
838 		}
839 	else
840 	if(!strncmp(buf1, "scope", 5))
841 		{
842 		char *st = strtok(buf+6, " \t");
843 		enum fstScopeType scopetype = FST_ST_VCD_MODULE;
844 
845 		switch(st[0])
846 			{
847 			case 'm':
848 				if(!strcmp(st, "module"))
849 					{
850 					}
851 				break;
852 
853 			case 't':
854 				if(!strcmp(st, "task"))
855 					{
856 					scopetype = FST_ST_VCD_TASK;
857 					}
858 				break;
859 
860 			case 'f':
861 				if(!strcmp(st, "function"))
862 					{
863 					scopetype = FST_ST_VCD_FUNCTION;
864 					}
865 				else
866 				if(!strcmp(st, "fork"))
867 					{
868 					scopetype = FST_ST_VCD_FORK;
869 					}
870 				break;
871 
872 			case 'b':
873 				if(!strcmp(st, "begin"))
874 					{
875 					scopetype = FST_ST_VCD_BEGIN;
876 					}
877 				break;
878 
879 			case 'g':
880 				if(!strcmp(st, "generate"))
881 					{
882 					scopetype = FST_ST_VCD_GENERATE;
883 					}
884 				break;
885 
886 			case 's':
887 				if(!strcmp(st, "struct"))
888 					{
889 					scopetype = FST_ST_VCD_STRUCT;
890 					}
891 				break;
892 
893 			case 'u':
894 				if(!strcmp(st, "union"))
895 					{
896 					scopetype = FST_ST_VCD_UNION;
897 					}
898 				break;
899 
900 			case 'c':
901 				if(!strcmp(st, "class"))
902 					{
903 					scopetype = FST_ST_VCD_CLASS;
904 					}
905 				break;
906 
907 			case 'i':
908 				if(!strcmp(st, "interface"))
909 					{
910 					scopetype = FST_ST_VCD_INTERFACE;
911 					}
912 				break;
913 
914 			case 'p':
915 				if(!strcmp(st, "package"))
916 					{
917 					scopetype = FST_ST_VCD_PACKAGE;
918 					}
919 				else
920 				if(!strcmp(st, "program"))
921 					{
922 					scopetype = FST_ST_VCD_PROGRAM;
923 					}
924 				break;
925 
926 			case 'v':
927 				if(!strcmp(st, "vhdl_architecture"))
928 					{
929 					scopetype = FST_ST_VHDL_ARCHITECTURE;
930 					}
931 				else
932 				if(!strcmp(st, "vhdl_procedure"))
933 					{
934 					scopetype = FST_ST_VHDL_PROCEDURE;
935 					}
936 				else
937 				if(!strcmp(st, "vhdl_function"))
938 					{
939 					scopetype = FST_ST_VHDL_FUNCTION;
940 					}
941 				else
942 				if(!strcmp(st, "vhdl_record"))
943 					{
944 					scopetype = FST_ST_VHDL_RECORD;
945 					}
946 				else
947 				if(!strcmp(st, "vhdl_process"))
948 					{
949 					scopetype = FST_ST_VHDL_PROCESS;
950 					}
951 				else
952 				if(!strcmp(st, "vhdl_block"))
953 					{
954 					scopetype = FST_ST_VHDL_BLOCK;
955 					}
956 				else
957 				if(!strcmp(st, "vhdl_for_generate"))
958 					{
959 					scopetype = FST_ST_VHDL_FOR_GENERATE;
960 					}
961 				else
962 				if(!strcmp(st, "vhdl_if_generate"))
963 					{
964 					scopetype = FST_ST_VHDL_IF_GENERATE;
965 					}
966 				else
967 				if(!strcmp(st, "vhdl_generate"))
968 					{
969 					scopetype = FST_ST_VHDL_GENERATE;
970 					}
971 				break;
972 
973 			default:
974 				break;
975 			}
976 
977 		st = strtok(NULL, " \t");
978 
979 #if defined(VCD2FST_EXTLOAD_CONV)
980 #ifdef _WAVE_HAVE_JUDY
981 		if(PJArray)
982 			{
983 			const char *fst_scope_name2 = fstReaderPushScope(xc, st, NULL);
984 			PPvoid_t PPValue = JudySLGet(PJArray, (uint8_t *)fst_scope_name2, PJE0);
985 
986 			if(PPValue)
987 				{
988 				unsigned char st_replace = (*((unsigned char *)*PPValue)) - 1;
989 				if(st_replace != FST_ST_VCD_MODULE)
990 					{
991 					scopetype = st_replace;
992 					}
993 
994 				if((scopetype == FST_ST_VCD_GENERATE)||(scopetype == FST_ST_VCD_STRUCT))
995 					{
996 					PPValue = NULL;
997 					}
998 
999 				fstWriterSetScope(ctx, scopetype, st, PPValue ? ((char *)(*PPValue)+1) : NULL);
1000 				}
1001 				else
1002 				{
1003 				fstWriterSetScope(ctx, scopetype, st, NULL);
1004 				}
1005 			}
1006 #else
1007 		if(comp_name_jrb)
1008 			{
1009 			const char *fst_scope_name2 = fstReaderPushScope(xc, st, NULL);
1010 			char cstring[65537];
1011 			JRB str;
1012 
1013 			strcpy(cstring, fst_scope_name2);
1014 			str = jrb_find_str(comp_name_jrb, cstring);
1015 
1016 			if(str)
1017 				{
1018 				unsigned char st_replace = str->val.s[0] - 1;
1019 				if(st_replace != FST_ST_VCD_MODULE)
1020 					{
1021 					scopetype = st_replace;
1022 					}
1023 
1024 				if((scopetype == FST_ST_VCD_GENERATE)||(scopetype == FST_ST_VCD_STRUCT))
1025 					{
1026 					str = NULL;
1027 					}
1028 
1029 				fstWriterSetScope(ctx, scopetype, st, str ? (str->val.s+1) : NULL);
1030 				}
1031 				else
1032 				{
1033 				fstWriterSetScope(ctx, scopetype, st, NULL);
1034 				}
1035 			}
1036 #endif
1037 			else
1038 #endif
1039 			{
1040 			fstWriterSetScope(ctx, scopetype, st, NULL);
1041 			}
1042 		}
1043 	else
1044 	if(!strncmp(buf1, "upscope", 7))
1045 		{
1046 		fstWriterSetUpscope(ctx);
1047 #if defined(VCD2FST_EXTLOAD_CONV)
1048 		if(xc)
1049 			{
1050 			fstReaderPopScope(xc);
1051 			}
1052 #endif
1053 		}
1054 	else
1055 	if(!strncmp(buf1, "endd", 4))
1056 		{
1057 #if defined(VCD2FST_EXTLOAD_CONV)
1058 #ifdef _WAVE_HAVE_JUDY
1059 		if(PJArray)
1060 #else
1061 		if(comp_name_jrb)
1062 #endif
1063 			{
1064 			dealloc_scope();
1065 			}
1066 #endif
1067 		if(port_encountered && (!compression_explicitly_set) && (pack_type == FST_WR_PT_LZ4)) /* EVCD data compresses far better with fastlz, so use if not directed explicitly */
1068 			{
1069 			fstWriterSetPackType(ctx, (pack_type = FST_WR_PT_FASTLZ));
1070 			}
1071 		break;
1072 		}
1073 	else
1074 	if(!strncmp(buf1, "timezero", 8))
1075 		{
1076 		char *pnt;
1077 		int64_t tzero = 0;
1078 
1079 		if((pnt = strstr(buf, "$end")))
1080 			{
1081 			*pnt = 0;
1082 			sscanf(buf+10, "%"SCNd64, &tzero);
1083 			}
1084 		else
1085                         {
1086                         ss = getline_replace(&wbuf, &buf, &glen, f);
1087                         if(!ss)
1088                                 {
1089                                 break;
1090                                 }
1091                         line++;
1092 			sscanf(buf, "%"SCNd64, &tzero);
1093                         }
1094 
1095 		fstWriterSetTimezero(ctx, tzero);
1096 		}
1097 	else
1098 	if(!strncmp(buf1, "timescale", 9))
1099 		{
1100 		char *pnt;
1101 		char *num = NULL;
1102 		int exp = -9;
1103 		int tv = 1;
1104 
1105 		if((pnt = strstr(buf, "$end")))
1106 			{
1107 			*pnt = 0;
1108 			num = strchr(buf, '1');
1109 			if(!num)
1110 				{
1111 				num = strchr(buf, '0'); /* verilator */
1112 				if(num) { *num = '1'; }
1113 				}
1114 			}
1115 
1116 		if(!num)
1117 			{
1118 			ss = getline_replace(&wbuf, &buf, &glen, f);
1119 			if(!ss)
1120 				{
1121 				break;
1122 				}
1123 			line++;
1124 			num = buf;
1125 			}
1126 
1127 		pnt = num;
1128 		while(*pnt)
1129 			{
1130 			int mat = 0;
1131 			switch(*pnt)
1132 				{
1133 				case 'm': exp = -3;  mat = 1; break;
1134 				case 'u': exp = -6;  mat = 1; break;
1135 				case 'n': exp = -9;  mat = 1; break;
1136 				case 'p': exp = -12; mat = 1; break;
1137 				case 'f': exp = -15; mat = 1; break;
1138 				case 'a': exp = -18; mat = 1; break;
1139 				case 'z': exp = -21; mat = 1; break;
1140 				case 's': exp =  0;  mat = 1; break;
1141 				default: break;
1142 				}
1143 			if(mat) break;
1144 			pnt++;
1145 			}
1146 
1147 		tv = atoi(num);
1148 		if(tv == 10)
1149 			{
1150 			exp++;
1151 			}
1152 		else
1153 		if(tv == 100)
1154 			{
1155 			exp+=2;
1156 			}
1157 
1158 		fstWriterSetTimescale(ctx, exp);
1159 		}
1160 	else
1161 	if(!strncmp(buf1, "date", 4))
1162 		{
1163 		char *pnt, *rsp;
1164 		int found = 0;
1165 
1166 		if((pnt = strstr(buf, "$end")))
1167 			{
1168                         *pnt = 0;
1169 			pnt = buf + 5;
1170 			while(*pnt && ((*pnt)==' ')) { pnt++; }
1171 			while((rsp = strrchr(pnt, ' ')))
1172 				{
1173 				if(*(rsp+1) == 0)
1174 					{
1175 					*rsp = 0;
1176 					}
1177 					else
1178 					{
1179 					break;
1180 					}
1181 				}
1182 			if(strlen(pnt)) { found = 1; }
1183 			}
1184 		else
1185 			{
1186 			pnt = buf + 5;
1187 			while(*pnt && ((*pnt)==' ')) { pnt++; }
1188 			while((rsp = strrchr(pnt, ' ')))
1189 				{
1190 				if(*(rsp+1) == 0)
1191 					{
1192 					*rsp = 0;
1193 					}
1194 					else
1195 					{
1196 					break;
1197 					}
1198 				}
1199 			if(strlen(pnt) > 3) { found = 1; }
1200 			}
1201 
1202 		if(!found)
1203 			{
1204 			ss = getline_replace(&wbuf, &buf, &glen, f);
1205 			if(!ss)
1206 				{
1207 				break;
1208 				}
1209 			line++;
1210 			pnt = buf;
1211 			}
1212 
1213 		while(*pnt == '\t') pnt++;
1214 		fstWriterSetDate(ctx, pnt);
1215 		}
1216 	else
1217 	if((!strncmp(buf1, "version", 7)) || (!strncmp(buf1, "comment", 7)))
1218 		{
1219 		char *pnt, *crpnt, *rsp;
1220 		int is_version = (buf[1] == 'v');
1221 
1222                 if((pnt = strstr(buf, "$end")))
1223                         {
1224                         *pnt = 0;
1225 			pnt = buf+8;
1226 			while(*pnt && ((*pnt)==' ')) { pnt++; }
1227 			while((rsp = strrchr(pnt, ' ')))
1228 				{
1229 				if(*(rsp+1) == 0)
1230 					{
1231 					*rsp = 0;
1232 					}
1233 					else
1234 					{
1235 					break;
1236 					}
1237 				}
1238                         }
1239 			else
1240 			{
1241 			ss = getline_replace(&wbuf, &buf, &glen, f);
1242 			if(!ss)
1243 				{
1244 				break;
1245 				}
1246 			line++;
1247 			pnt = buf;
1248 			}
1249 
1250 		while(*pnt == '\t') pnt++;
1251 		crpnt = strchr(pnt, '\n');
1252 		if(crpnt) *crpnt = 0;
1253 		crpnt = strchr(pnt, '\r');
1254 		if(crpnt) *crpnt = 0;
1255 
1256 		if(is_version)
1257 			{
1258 			fstWriterSetVersion(ctx, pnt);
1259 			}
1260 			else
1261 			{
1262 			fstWriterSetComment(ctx, pnt);
1263 			}
1264 		}
1265 	}
1266 
1267 if((!hash_kill) && (vcd_ids))
1268 	{
1269 	unsigned int hash;
1270 
1271 	node_len_array = calloc(hash_max + 1, sizeof(int));
1272 
1273 	for(hash=1;hash<=hash_max;hash++)
1274 		{
1275 		node = jrb_find_int(vcd_ids, hash);
1276 		if(node)
1277 			{
1278 			node_len_array[hash] = node->val2.i;
1279 			}
1280 			else
1281 			{
1282 			node_len_array[hash] = 1; /* should never happen */
1283 			}
1284 		}
1285 
1286 	jrb_free_tree(vcd_ids);
1287 	vcd_ids = NULL;
1288 	}
1289 	else
1290 	{
1291 	hash_kill = 1; /* scan-build */
1292 	}
1293 
1294 for(;;) /* was while(!feof(f)) */
1295 	{
1296 	unsigned int hash;
1297 	uint64_t tim;
1298 	char *nl, *sp;
1299 	double doub;
1300 
1301 	ss = getline_replace(&wbuf, &buf, &glen, f);
1302 	if(!ss)
1303 		{
1304 		break;
1305 		}
1306 
1307 	nl = buf;
1308 	while(*nl)
1309 		{
1310 		if((*nl == '\n') || (*nl == '\r'))
1311 			{
1312 			*nl = 0;
1313 			break;
1314 			}
1315 		nl++;
1316 		}
1317 
1318 	switch(buf[0])
1319 		{
1320 		case '0':
1321 		case '1':
1322 		case 'x':
1323 		case 'z':
1324 			hash = vcdid_hash(buf+1, nl - (buf+1));
1325 			if(!hash_kill)
1326 				{
1327 				fstWriterEmitValueChange(ctx, hash, buf);
1328 				}
1329 				else
1330 				{
1331 				node = jrb_find_int(vcd_ids, hash);
1332 				if(node)
1333 					{
1334 					fstWriterEmitValueChange(ctx, node->val.i, buf);
1335 					}
1336 					else
1337 					{
1338 					}
1339 				}
1340 			break;
1341 
1342 		case 'b':
1343 			{ /* this block replaces the single statement sp = strchr(buf, ' ');        */
1344 			  /* as the odds are the VCD ID will be small compared to the vector length */
1345 			char *sp_scan = nl;
1346 			sp = NULL;
1347 
1348 			/* if(buf != sp_scan) [can't happen or switch() wouldn't get here] */
1349 				{
1350 				while(buf != --sp_scan)
1351 					{
1352 					if(*sp_scan == ' ')
1353 						{
1354 						sp = sp_scan;
1355 						break;
1356 						}
1357 					}
1358 				}
1359 			}
1360 
1361 			if(!sp) break;
1362 			*sp = 0;
1363 			hash = vcdid_hash(sp+1, nl - (sp+1));
1364 			if(!hash_kill)
1365 				{
1366 				int bin_len = sp - (buf + 1); /* strlen(buf+1) */
1367 				int node_len = node_len_array[hash];
1368 
1369 				if(bin_len >= node_len)
1370 					{
1371 					fstWriterEmitValueChange(ctx, hash, buf+1);
1372 					}
1373 					else
1374 					{
1375 					int delta = node_len - bin_len;
1376 
1377 					if(node_len >= bin_fixbuff_len)
1378 						{
1379 						bin_fixbuff_len = node_len + 1;
1380 						bin_fixbuff = realloc_2(bin_fixbuff, bin_fixbuff_len);
1381 						}
1382 
1383 					memset(bin_fixbuff, buf[1] != '1' ? buf[1] : '0', delta);
1384 					memcpy(bin_fixbuff + delta, buf+1, bin_len);
1385 					fstWriterEmitValueChange(ctx, hash, bin_fixbuff);
1386 					}
1387 				}
1388 				else
1389 				{
1390 				node = jrb_find_int(vcd_ids, hash);
1391 				if(node)
1392 					{
1393 					int bin_len = sp - (buf + 1); /* strlen(buf+1) */
1394 					int node_len = node->val2.i;
1395 					if(bin_len >= node_len)
1396 						{
1397 						fstWriterEmitValueChange(ctx, node->val.i, buf+1);
1398 						}
1399 						else
1400 						{
1401 						int delta = node_len - bin_len;
1402 
1403 						if(node_len >= bin_fixbuff_len)
1404 							{
1405 							bin_fixbuff_len = node_len + 1;
1406 							bin_fixbuff = realloc_2(bin_fixbuff, bin_fixbuff_len);
1407 							}
1408 
1409 						memset(bin_fixbuff, buf[1] != '1' ? buf[1] : '0', delta);
1410 						memcpy(bin_fixbuff + delta, buf+1, bin_len);
1411 						fstWriterEmitValueChange(ctx, node->val.i, bin_fixbuff);
1412 						}
1413 					}
1414 					else
1415 					{
1416 					}
1417 				}
1418 			break;
1419 
1420 		case 's':
1421 			sp = strchr(buf, ' ');
1422 			if(!sp) break;
1423 			*sp = 0;
1424 			hash = vcdid_hash(sp+1, nl - (sp+1));
1425 			if(!hash_kill)
1426 				{
1427 				int bin_len = sp - (buf + 1); /* strlen(buf+1) */
1428 
1429 				bin_len = fstUtilityEscToBin(NULL, (unsigned char *)(buf+1), bin_len);
1430 				fstWriterEmitVariableLengthValueChange(ctx, hash, buf+1, bin_len);
1431 				}
1432 				else
1433 				{
1434 				node = jrb_find_int(vcd_ids, hash);
1435 				if(node)
1436 					{
1437 					int bin_len = sp - (buf + 1); /* strlen(buf+1) */
1438 
1439 					bin_len = fstUtilityEscToBin(NULL, (unsigned char *)(buf+1), bin_len);
1440 					fstWriterEmitVariableLengthValueChange(ctx, node->val.i, buf+1, bin_len);
1441 					}
1442 					else
1443 					{
1444 					}
1445 				}
1446 			break;
1447 
1448 		case 'p':
1449 			{
1450 			char *src = buf+1;
1451 			char *pnt;
1452 			int pchar = 0;
1453 			int p_len = strlen(src);
1454 
1455 			if(p_len >= bin_fixbuff_len)
1456 				{
1457 				bin_fixbuff_len = p_len + 1;
1458 				bin_fixbuff = realloc_2(bin_fixbuff, bin_fixbuff_len);
1459 				}
1460 			pnt = bin_fixbuff;
1461 
1462 			for(;;)
1463 				{
1464 				if(!*src) break;
1465 				if(isspace((int)(unsigned char)*src))
1466 					{
1467 					if(pchar != ' ') { *(pnt++) = pchar = ' '; }
1468 					src++;
1469 					continue;
1470 					}
1471 				*(pnt++) = pchar = *(src++);
1472 				}
1473 			*pnt = 0;
1474 
1475 			sp = strchr(bin_fixbuff, ' ');
1476 			if(!sp) break;
1477 			sp = strchr(sp+1, ' ');
1478 			if(!sp) break;
1479 			sp = strchr(sp+1, ' ');
1480 			if(!sp) break;
1481 			*sp = 0;
1482 
1483 			hash = vcdid_hash(sp+1, strlen(sp+1)); /* nl is no longer good here */
1484 			if(!hash_kill)
1485 				{
1486 				fstWriterEmitValueChange(ctx, hash, bin_fixbuff);
1487 				}
1488 				else
1489 				{
1490 				node = jrb_find_int(vcd_ids, hash);
1491 				if(node)
1492 					{
1493 					fstWriterEmitValueChange(ctx, node->val.i, bin_fixbuff);
1494 					}
1495 					else
1496 					{
1497 					}
1498 				}
1499 			}
1500 			break;
1501 
1502 		case 'r':
1503 			sp = strchr(buf, ' ');
1504 			if(!sp) break;
1505 			hash = vcdid_hash(sp+1, nl - (sp+1));
1506 			if(!hash_kill)
1507 				{
1508 		                sscanf(buf+1,"%lg",&doub);
1509 				fstWriterEmitValueChange(ctx, hash, &doub);
1510 				}
1511 				else
1512 				{
1513 				node = jrb_find_int(vcd_ids, hash);
1514 				if(node)
1515 					{
1516 			                sscanf(buf+1,"%lg",&doub);
1517 					fstWriterEmitValueChange(ctx, node->val.i, &doub);
1518 					}
1519 					else
1520 					{
1521 					}
1522 				}
1523 			break;
1524 
1525 		case 'h': /* same as 01xz above but moved down here as it's less common */
1526 		case 'u':
1527 		case 'w':
1528 		case 'l':
1529 		case '-':
1530 			hash = vcdid_hash(buf+1, nl - (buf+1));
1531 			if(!hash_kill)
1532 				{
1533 				fstWriterEmitValueChange(ctx, hash, buf);
1534 				}
1535 				else
1536 				{
1537 				node = jrb_find_int(vcd_ids, hash);
1538 				if(node)
1539 					{
1540 					fstWriterEmitValueChange(ctx, node->val.i, buf);
1541 					}
1542 					else
1543 					{
1544 					}
1545 				}
1546 			break;
1547 
1548 		case '#':
1549 			tim = atoi_2((unsigned char *)(buf+1));
1550 			if((tim >= prev_tim)||(!prev_tim))
1551 				{
1552 				prev_tim = tim;
1553 				fstWriterEmitTimeChange(ctx, tim);
1554 				}
1555 			break;
1556 
1557 		default:
1558 			if(!strncmp(buf, "$dumpon", 7))
1559 				{
1560 				fstWriterEmitDumpActive(ctx, 1);
1561 				}
1562 			else
1563 			if(!strncmp(buf, "$dumpoff", 8))
1564 				{
1565 				fstWriterEmitDumpActive(ctx, 0);
1566 				}
1567 			else
1568 			if(!strncmp(buf, "$dumpvars", 9))
1569 				{
1570 				/* nothing */
1571 				}
1572 			else
1573 				{
1574 				/* printf("FST '%s'\n", buf); */
1575 				}
1576 			break;
1577 		}
1578 	}
1579 
1580 fstWriterClose(ctx);
1581 
1582 #if defined(VCD2FST_EXTLOAD_CONV)
1583 if(xc)
1584 	{
1585 	fstReaderClose(xc);
1586 	}
1587 #endif
1588 
1589 
1590 if(vcd_ids)
1591 	{
1592 	jrb_free_tree(vcd_ids);
1593 	vcd_ids = NULL;
1594 	}
1595 
1596 free(bin_fixbuff); bin_fixbuff = NULL;
1597 free(wbuf); wbuf = NULL;
1598 free(node_len_array); node_len_array = NULL;
1599 
1600 if(f != stdin)
1601 	{
1602 	if(is_popen)
1603 		{
1604 		pclose(f);
1605 		}
1606 		else
1607 		{
1608 		fclose(f);
1609 		}
1610 	}
1611 
1612 return(0);
1613 }
1614 
1615 
print_help(char * nam)1616 void print_help(char *nam)
1617 {
1618 #ifdef VCD2FST_EXTLOADERS_CONV
1619 
1620 int slen;
1621 char *ucase_ext = calloc(1, 1024);
1622 int i;
1623 
1624 ucase_ext[0] = 0;
1625 
1626 #if defined(VCD2FST_EXTLOAD_CONV)
1627 strcat(ucase_ext, "/");
1628 strcat(ucase_ext, EXTLOAD_SUFFIX);
1629 #endif
1630 
1631 #if defined(VCD2FST_EXT2LOAD_CONV)
1632 strcat(ucase_ext, "/");
1633 strcat(ucase_ext, EXT2LOAD_SUFFIX);
1634 #endif
1635 
1636 #if defined(VCD2FST_EXT3LOAD_CONV)
1637 strcat(ucase_ext, "/");
1638 strcat(ucase_ext, EXT3LOAD_SUFFIX);
1639 #endif
1640 
1641 slen = strlen(ucase_ext);
1642 
1643 for(i=0;i<slen;i++)
1644 	{
1645 	ucase_ext[i] = toupper(ucase_ext[i]);
1646 	}
1647 
1648 #endif
1649 
1650 
1651 #ifdef __linux__
1652 printf(
1653 "Usage: %s [OPTION]... [VCDFILE] [FSTFILE]\n\n"
1654 #ifdef VCD2FST_EXTLOADERS_CONV
1655 "  -v, --vcdname=FILE         specify VCD%s input filename\n"
1656 #else
1657 "  -v, --vcdname=FILE         specify VCD input filename\n"
1658 #endif
1659 "  -f, --fstname=FILE         specify FST output filename\n"
1660 "  -4, --fourpack             use lz4 algorithm for speed (default)\n"
1661 "  -F, --fastpack             use fastlz algorithm for speed\n"
1662 "  -Z, --zlibpack             use zlib algorithm for size\n"
1663 "  -c, --compress             zlib compress entire file on close\n"
1664 "  -p, --parallel             enable parallel mode\n"
1665 "  -h, --help                 display this help then exit\n\n"
1666 
1667 "Note that VCDFILE and FSTFILE are optional provided the\n"
1668 "--vcdname and --fstname options are specified.\n\n"
1669 "Report bugs to <"PACKAGE_BUGREPORT">.\n",nam
1670 #ifdef VCD2FST_EXTLOADERS_CONV
1671 ,ucase_ext
1672 #endif
1673 );
1674 #else
1675 printf(
1676 "Usage: %s [OPTION]... [VCDFILE] [FSTFILE]\n\n"
1677 #ifdef VCD2FST_EXTLOADERS_CONV
1678 "  -v FILE                    specify VCD%s input filename\n"
1679 #else
1680 "  -v FILE                    specify VCD input filename\n"
1681 #endif
1682 "  -f FILE                    specify FST output filename\n"
1683 "  -4                         use lz4 algorithm for speed (default)\n"
1684 "  -F                         use fastlz algorithm for speed\n"
1685 "  -Z                         use zlib algorithm for size\n"
1686 "  -c                         zlib compress entire file on close\n"
1687 "  -p                         enable parallel mode\n"
1688 "  -h                         display this help then exit\n\n"
1689 
1690 "Note that VCDFILE and FSTFILE are optional provided the\n"
1691 "--vcdname and --fstname options are specified.\n\n"
1692 "Report bugs to <"PACKAGE_BUGREPORT">.\n",nam
1693 #ifdef VCD2FST_EXTLOADERS_CONV
1694 ,ucase_ext
1695 #endif
1696 );
1697 #endif
1698 
1699 #ifdef VCD2FST_EXTLOADERS_CONV
1700 free(ucase_ext);
1701 #endif
1702 
1703 exit(0);
1704 }
1705 
1706 
main(int argc,char ** argv)1707 int main(int argc, char **argv)
1708 {
1709 char opt_errors_encountered=0;
1710 char *vname=NULL, *lxname=NULL;
1711 int c;
1712 
1713 WAVE_LOCALE_FIX
1714 
1715 while (1)
1716         {
1717 #ifdef __linux__
1718         int option_index = 0;
1719 
1720         static struct option long_options[] =
1721                 {
1722 		{"vcdname", 1, 0, 'v'},
1723 		{"fstname", 1, 0, 'f'},
1724 		{"fastpack", 0, 0, 'F'},
1725 		{"fourpack", 0, 0, '4'},
1726 		{"zlibpack", 0, 0, 'Z'},
1727 		{"compress", 0, 0, 'c'},
1728 		{"parallel", 0, 0, 'p'},
1729                 {"help", 0, 0, 'h'},
1730                 {0, 0, 0, 0}
1731                 };
1732 
1733         c = getopt_long (argc, argv, "v:f:ZF4cph", long_options, &option_index);
1734 #else
1735         c = getopt      (argc, argv, "v:f:ZF4cph");
1736 #endif
1737 
1738         if (c == -1) break;     /* no more args */
1739 
1740         switch (c)
1741                 {
1742 		case 'v':
1743 			if(vname) free(vname);
1744                         vname = malloc(strlen(optarg)+1);
1745                         strcpy(vname, optarg);
1746 			break;
1747 
1748 		case 'f':
1749 			if(lxname) free(lxname);
1750                         lxname = malloc(strlen(optarg)+1);
1751                         strcpy(lxname, optarg);
1752 			break;
1753 
1754 		case 'Z':
1755 			compression_explicitly_set = 1;
1756 			pack_type = FST_WR_PT_ZLIB;
1757 			break;
1758 
1759 		case 'F':
1760 			compression_explicitly_set = 1;
1761 			pack_type = FST_WR_PT_FASTLZ;
1762 			break;
1763 
1764 		case '4':
1765 			compression_explicitly_set = 1;
1766 			pack_type = FST_WR_PT_LZ4;
1767 			break;
1768 
1769 		case 'c':
1770 			repack_all = 1;
1771 			break;
1772 
1773 		case 'p':
1774 			parallel_mode = 1;
1775 			break;
1776 
1777                 case 'h':
1778 			print_help(argv[0]);
1779                         break;
1780 
1781                 case '?':
1782                         opt_errors_encountered=1;
1783                         break;
1784 
1785                 default:
1786                         /* unreachable */
1787                         break;
1788                 }
1789         }
1790 
1791 if(opt_errors_encountered)
1792         {
1793         print_help(argv[0]);
1794         }
1795 
1796 if (optind < argc)
1797         {
1798         while (optind < argc)
1799                 {
1800                 if(!vname)
1801                         {
1802                         vname = malloc(strlen(argv[optind])+1);
1803                         strcpy(vname, argv[optind++]);
1804                         }
1805                 else if(!lxname)
1806                         {
1807                         lxname = malloc(strlen(argv[optind])+1);
1808                         strcpy(lxname, argv[optind++]);
1809                         }
1810 		else
1811 			{
1812 			break;
1813 			}
1814                 }
1815         }
1816 
1817 if((!vname)||(!lxname))
1818         {
1819         print_help(argv[0]);
1820         }
1821 
1822 fst_main(vname, lxname);
1823 
1824 free(vname); free(lxname);
1825 
1826 return(0);
1827 }
1828 
1829