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