1 /* Copyright (c) 1991-2004 Pragmatic C Software Corp. */
2 
3 /*
4   This program is free software; you can redistribute it and/or modify it
5   under the terms of the GNU General Public License as published by the
6   Free Software Foundation; either version 2 of the License, or (at your
7   option) any later version.
8 
9   This program is distributed in the hope that it will be useful, but
10   WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   General Public License for more details.
13 
14   You should have received a copy of the GNU General Public License along
15   with this program; if not, write to the Free Software Foundation, Inc.,
16   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
17 */
18 
19 #define VERS2 "0.04a"
20 #define OFDT "07/28/2004"
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <fcntl.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27 #include <ctype.h>
28 #include <time.h>
29 #include <string.h>
30 #include "vcddiff.h"
31 
32 static int get_token(FILE *, char *);
33 static void read_to_end(FILE *);
34 static char timescale(FILE *, int *);
35 static void add_signal(char *, char *, unsigned int, int, int);
36 static int get_var_type(char *);
37 static void variable(FILE *, char *);
38 static void alloc_sig_mem(void);
39 static int get_vkeywrd(register char *);
40 static long get_lines(FILE *, int *, int *, char *);
41 static void print_signal_info(struct signal_t *, struct signal_t *, vtime_t,
42 		vtime_t, bool_t);
43 static void print_scalar_state(struct signal_t *, struct signal_t *, vtime_t,
44                 vtime_t, char, char, bool_t);
45 static void print_vector_state(struct signal_t *, struct signal_t *, vtime_t,
46                 vtime_t, char *, char *, bool_t);
47 static void print_scalar_edge(struct signal_t *, struct signal_t *, vtime_t,
48                 vtime_t, char, char, bool_t);
49 static void print_edges(struct signal_t *, char *, int, int, char);
50 static void print_vector_edge(struct signal_t *, struct signal_t *, vtime_t,
51                 vtime_t, char *, char *, bool_t);
52 static int get_nxt_chg(FILE *, char *, int *, int *, char *, vtime_t *,
53 		         bool_t);
54 static vtime_t get_time_diffs(FILE *, FILE *, char *, char *, long, long,
55 	          vtime_t, vtime_t, bool_t);
56 static void print_map(void);
57 static void compare_types(char *, char *, struct signal_t *, struct signal_t *);
58 static bool_t map(char *, char *, int **, struct signal_t *,
59                    struct signal_t *, struct signal_t **, bool_t);
60 static bool_t map_var_names(char *, char *);
61 static void run_diffs(FILE *, FILE *, char *, char *, long, long);
62 static void print_header(void);
63 static void print_help(void);
64 static void edge_space(int, int , bool_t);
65 
66 /* globals */
67 static int line_num1G;   /* cur position of file1 */
68 static int line_num2G;  /* cur position of file2 */
69 static char curmodG[1000]; /* cur mod hier name */
70 static FILE *file1G;   /* to check if it is the first file */
71 static bool_t state_flagG; /* print edges or states */
72 static bool_t wrap_flagG; /* print edges or states */
73 static struct signal_t	**sig_int1G;  /* int codes for file 1 */
74 static struct signal_t	**sig_int2G;	/* int codes for file 2 */
75 static int **fd1_to_fd2_mapG;   /* mappings from one file to the other*/
76 static int **fd2_to_fd1_mapG;
77 static int max_codeG;         /* max code so sig_int? is large enough */
78 static char scopesG[MAXSCOPES][MAXSIG];  /* scope of mods */
79 static int  quit_flagG;    /* flag to quit */
80 static bool_t  next_listG;    /* to signal the next list of signals */
81 struct signal_t *sig1_hdG;   /* the head of the first file of signals */
82 struct signal_t *sig2_hdG;   /* the head of the second file of signals */
83 struct signal_t *lastsigG;   /* mark the last signal of the file */
84 
85 /* signal to code from dinotrace wave viewer www.veripool.com/dinotrace */
86 #define	VERILOG_ID_TO_POS(_code_) \
87     (_code_[0]?((_code_[0]-32) + 94 * \
88 		(_code_[1]?((_code_[1]-32) + 94 * \
89 			    (_code_[2]?((_code_[2]-32) + 94 * \
90 					(_code_[3]?((_code_[3]-32) \
91 						    ):0) \
92 					):0) \
93 			    ):0) \
94 		):0)
95 
96 #define VERILOG_POS_TO_SIG1(_pos_) \
97     (((_pos_)<max_codeG)?sig_int1G[(_pos_)]:0)
98 
99 #define VERILOG_POS_TO_SIG2(_pos_) \
100     (((_pos_)<max_codeG)?sig_int2G[(_pos_)]:0)
101 /**********************************************************************/
102 
103 /*get a new token from the file fp, and place in token, return the length*/
get_token(FILE * fp,char * token)104 static int get_token(FILE *fp, char *token)
105 {
106  int i, c;
107 
108  i = 0;
109  while((c = fgetc(fp)) != EOF)
110  {
111 	 if(isspace(c))
112 	 {
113            if(c == '\n')
114            {
115  	     if(fp == file1G) line_num1G++;
116 	     else line_num2G++;
117 	   }
118 		 continue;
119          }
120 	 break;
121  }
122 
123  if(c == EOF) return EOF;
124  token[i++] = c;
125 
126  while(!isspace(c = fgetc(fp)))
127  {
128    if(c == EOF)
129  	 return EOF;
130    else
131      token[i++] = c;
132  }
133  if(c == '\n')
134  {
135     if(fp == file1G) line_num1G++;
136     else line_num2G++;
137  }
138 
139  token[i]='\0';
140  return i;
141 }
142 
143 /*read the file until an $end is reached*/
read_to_end(FILE * fp)144 static void read_to_end(FILE *fp)
145 {
146   char token[MAXTOKSIZE];
147 
148     while(get_token(fp, token) != EOF)
149     {
150 	if(!strncmp (token, "$end", 4))
151 	    return;
152     }
153 }
154 
155 /* get the timescale information for comparison return char of units, and
156  * the number 1, 10, 100 in tnum
157  * */
timescale(FILE * fp,int * tnum)158 static char timescale(FILE *fp, int *tnum)
159 {
160  int i, toklen;
161  char token[MAXTOKSIZE];
162  char tmp[MAXTOKSIZE];
163  char *tok;
164 
165     toklen = get_token(fp, token);
166     tok = token;
167     /* AIV 02/04/03 there can be a space between 1 ns, not always 1ns */
168     for(i = 0; i <toklen; i++)
169     {
170       if(!isdigit(token[i])) break;
171     }
172     if(i == toklen)
173     {
174       get_token(fp, tmp);
175       strcat(token, tmp);
176     }
177 
178     *tnum = atoi(tok);
179 
180     if(*tnum != 1 && *tnum != 10 && *tnum != 100)
181     {
182 	    printf("*** ERROR-time number(%d) in timescale on line %d is illegal - assuming 1\n", *tnum, (fp == file1G) ? line_num1G : line_num2G );
183 	    *tnum = 1;
184     }
185 
186     while(isdigit (*tok))
187 	    tok++;
188     if (!*tok)
189 	    get_token(fp, token);
190 
191     switch (*tok) {
192     case 's':
193     case 'm':
194     case 'u':
195     case 'n':
196     case 'p':
197     case 'f':
198       return(*tok);
199     default:
200 	  printf("*** ERROR-illegal character(%c) in timescale on line %d\n", *tok, (fp == file1G) ? line_num1G : line_num2G );
201 	  return(0);
202     }
203 }
204 
205 /* add a new signal to the list, init values signal name, identifies
206  * the code to index the array of signals, and the number of bits, if
207  * bits is 1 it is scalar
208  * */
add_signal(char * signame,char * ident,unsigned int code,int bits,int type)209 static void add_signal(char *signame,char *ident, unsigned int code,
210                                    int bits, int type)
211 {
212  char  *cp;
213  struct signal_t *newsig;
214 
215    /*get rid of scapes before and after*/
216    while(isspace(*signame)) signame++;
217    for (cp = signame + strlen(signame) - 1;cp >= signame && isspace(*cp);  cp--)    *cp = '\0';
218 
219    newsig = (struct signal_t *) malloc(sizeof(struct signal_t));
220    newsig->sig_code = code;
221    newsig->ident = (char *) malloc(strlen(ident)+1);
222    /* init values to x's */
223    newsig->state = '?';
224    newsig->type = type;
225    newsig->in_both = TRUE;
226    newsig->size = bits;
227    newsig->next = NULL;
228 
229    if(type == REAL)
230    {
231      /*FIXME what about large reals ???*/
232      newsig->vector = (char *) malloc(REALSIZE);
233      newsig->vector[0] = '0';
234      newsig->vector[1] = '\0';
235    }
236    else if(bits > 1)
237    {
238      newsig->vector = (char *) malloc(bits + 2);
239      newsig->vector[bits] = '\0';
240      bits--;
241      for(; bits >= 0; bits--)
242        newsig->vector[bits] = '?';
243    }
244 
245    /*signal not found so print first diff*/
246    newsig->found = FALSE;
247    strcpy(newsig->ident, ident);
248    /*link signals for hash setup and mapping*/
249    if(lastsigG)
250       lastsigG->next= newsig;
251 
252    if(sig1_hdG == NULL)
253       sig1_hdG = newsig;
254 
255    if(next_listG && sig2_hdG == NULL)
256       sig2_hdG = newsig;
257 
258    lastsigG = newsig;
259    newsig->signame = (char *) malloc(strlen(signame)+1);
260    strcpy(newsig->signame, signame);
261    max_codeG = MAX(max_codeG, code+1);
262 }
263 
264 
265 /*dump variable types must be kept in alphabetical order */
266 static struct variable_types_t var_types[] = {
267 	{"event", EVENT },
268         {"integer", INTEGER},
269         {"parameter", PARAMETER},
270         {"real", REAL},
271         {"reg", REG},
272         {"supply0", SUPPLY0},
273         {"supply1", SUPPLY1},
274         {"time", TIME},
275         {"tri", TRI},
276         {"tri0", TRI0},
277         {"tri1", TRI1},
278         {"triand", TRIAND},
279         {"trior", TRIOR},
280         {"trireg", TRIREG},
281         {"wand", WAND},
282         {"wire", WIRE},
283         {"wor",	WOR}
284 };
285 
286 
287 #define VARTYPE (sizeof(var_types) / sizeof(struct variable_types_t))
288 
get_var_type(char * tstr)289 static int get_var_type(char *tstr)
290 {
291  int l, h;
292  register int m, cv;
293 
294 
295  l = 0; h = VARTYPE - 1;
296  for (;;)
297   {
298    m = (l + h)/2;
299    if((cv = strcmp(var_types[m].vnam, tstr)) == 0)
300       return(var_types[m].vnum);
301    if(cv < 0) l = m + 1; else h = m - 1;
302    if(h < l) break;
303   }
304  return(-1);
305 
306 }
307 
308 /*var line so add a new signal with its identifier*/
variable(FILE * fp,char * file_name)309 static void variable(FILE *fp, char *file_name)
310 {
311   char signame[MAXSIG];
312   char ident[10];
313   char token[MAXTOKSIZE];
314   int  bits;
315   char type;
316 
317     /*type, size*/
318     get_token(fp, token);
319     /*most ofter a reg otherwise do a search */
320     if(strncmp(token, "reg", 3) == 0)
321 	    type = REG;
322     else
323             type = get_var_type(token);
324 
325     if(type < 0)
326     {
327       type = UNDEFINED;
328       printf("Error- Unknown variable type %s\n", token);
329     }
330 
331     /* get number of bits */
332     /* AIV FIXME error recovery should be used here for invalid tokens
333      * if a $var line is short vars (starts with a '$') rewind, print
334      * message and return */
335     get_token(fp, token);
336     bits = atoi(token);
337 
338     if(bits < 0)
339     {
340        printf ("Negative size illegal on line %d of %s\n", (fp == file1G) ? line_num1G : line_num2G, file_name);
341        return;
342     }
343 
344     /*identifier*/
345     get_token(fp, token);
346     strcpy(ident, token);
347 
348     /*variable name*/
349     get_token(fp, token);
350     strcpy (signame, curmodG);
351     strcat (signame, token);
352 
353 
354     get_token(fp, token);
355     /*if there is a space between the var name and the range concat it
356      * to the name */
357     if (token[0] != '$')
358 	strcat (signame, token);
359 
360     add_signal(signame, ident, VERILOG_ID_TO_POS(ident), bits, type);
361 }
362 
363 
364 /* setup memory for the hash of signals, which is the max of all signals,
365  * then setup up arrays according to the signal's code index
366  */
alloc_sig_mem(void)367 static void alloc_sig_mem(void)
368 {
369   struct signal_t *sig;
370 
371   sig_int1G = (struct signal_t **) calloc(sizeof(struct signal_t *), (max_codeG + 1));
372   for (sig = sig1_hdG; sig !=NULL; sig = sig->next)
373      sig_int1G[sig->sig_code] = sig;
374 
375   sig_int2G = (struct signal_t **) calloc(sizeof(struct signal_t *), (max_codeG + 1));
376   for (sig = sig2_hdG; sig !=NULL; sig = sig->next)
377      sig_int2G[sig->sig_code] = sig;
378 
379 }
380 
381 /*dump file keywords must be kept in alphabetical order */
382 static struct variable_types_t vkeywds[] = {
383         { "comment", V_COMMENT},
384         { "date", V_DATE },
385         { "end", V_END },
386         { "enddefinitions", V_ENDDEF},
387         { "scope", V_SCOPE},
388         { "timescale", V_TIMESCALE },
389         { "upscope", V_UPSCOPE },
390         { "var", V_VAR },
391         { "version", V_VERSION }
392 };
393 
394 #define VKEYWDS (sizeof(vkeywds) / sizeof(struct variable_types_t))
395 
396 /*search for verilog keywords*/
get_vkeywrd(register char * tstr)397 static int get_vkeywrd(register char *tstr)
398 {
399  int l, h;
400  register int m, cv;
401 
402  //start at $end
403  l = -2; h = VKEYWDS - 1;
404  for (;;)
405   {
406    m = (l + h)/2;
407    if((cv = strcmp(vkeywds[m].vnam, tstr)) == 0)
408         return(vkeywds[m].vnum);
409    if(cv < 0) l = m + 1; else h = m - 1;
410    if(h < l) break;
411   }
412  return(EOF);
413 }
414 
415 
416 /* process all the lines until $enddef is reached, determines all variable
417  * names, seperated by a '.' between scopes, place the timescale number
418  * and units, and return the file location to start processing diffs
419  */
get_lines(FILE * fp,int * units,int * tnum,char * file_name)420 static long get_lines(FILE *fp, int *units, int *tnum, char *file_name)
421 {
422   char sep[2];
423   int level;
424   register int i;
425   char *tok;
426   char token[MAXTOKSIZE];
427 
428     sep[0] = '.';
429     sep[1] = '\0';
430     level = 0;
431     *units = 1;
432 
433     while(get_token(fp, token) != EOF)
434     {
435       tok = token;
436       if(tok[0] != '$')
437       {
438         printf ("***ERROR Unknown token '%s' on line %d of %s\n",
439            tok, (fp == file1G) ? line_num1G: line_num2G, file_name);
440         continue;
441       }
442       tok++;
443 
444       switch(get_vkeywrd(tok)){
445         case V_END:
446                 break;
447 
448 	case V_VAR:
449 		 variable(fp, file_name);
450 	      break;
451 
452         case V_UPSCOPE:
453 	         if(level > 0) level--;
454 	      break;
455 
456 	case V_SCOPE:
457 	    get_token(fp, tok);
458 	    get_token(fp, tok);
459 
460 	    if(level < MAXSCOPES)
461             {
462 		strcpy(scopesG[level], tok);
463 
464 	        strcpy(curmodG, scopesG[0]);
465 	        strcat(curmodG, sep);
466 		level++;
467 
468 		if(level)
469 		{
470                   for (i=1; i<level; i++) {
471 	             strcat(curmodG, scopesG[i]);
472 	             strcat(curmodG, sep);
473                   }
474 	        }
475 
476 	    }
477 	    else
478             {
479 	       printf("*** ERROR-exceeded max scope levels %d\n", level);
480 	       exit(0);
481 	    }
482           break;
483         case V_COMMENT:
484 	case V_DATE:
485 	case V_VERSION:
486 	       read_to_end(fp);
487 	     break;
488 
489         case V_TIMESCALE:
490 		 *units = timescale(fp, tnum);
491 		break;
492 
493         case V_ENDDEF:
494 	    next_listG = TRUE;
495 	    lastsigG = NULL;
496 	    return(ftell(fp));
497 
498 	default:
499 	    printf ("Unknown command '%s' on line %d of %s\n",
500 		     tok, (fp == file1G) ? line_num1G: line_num2G, file_name);
501 	    break;
502 
503     }
504   }
505     return(-1);
506 }
507 
508 /* print the diff signal information */
print_signal_info(struct signal_t * sig1,struct signal_t * sig2,vtime_t time1,vtime_t time2,bool_t isone)509 static void print_signal_info(struct signal_t *sig1,
510                               struct signal_t *sig2,
511                               vtime_t time1, vtime_t time2, bool_t isone)
512 {
513 
514    if(time1 == time2)
515    {
516 
517       if(sig1->sig_code == sig2->sig_code)
518           printf("%s (%s) differs at time %lld\n", sig1->signame,sig1->ident, time1);
519       else
520           printf("%s (%s , %s) differs at time %lld\n", sig1->signame,
521                 sig1->ident, sig2->ident, time1);
522      return;
523     }
524    else
525    {
526        if(sig1->sig_code == sig2->sig_code)
527               printf("%c %s (%s) at time %lld next occurence at time %lld\n", isone ? '>' : '<',  sig1->signame, sig1->ident, time1, time2);
528        else
529               printf("%c %s (%s, %s) at time %lld next occurence at time %lld\n", isone ? '>' : '<',  sig1->signame,sig1->ident, sig2->ident, time1, time2);
530      return;
531    }
532 
533 }
534 
535 
536 
537 /* print the scalar value  */
print_scalar_state(struct signal_t * sig1,struct signal_t * sig2,vtime_t time1,vtime_t time2,char state1,char state2,bool_t isone)538 static void print_scalar_state(struct signal_t *sig1,
539                                struct signal_t *sig2,
540                                vtime_t time1, vtime_t time2,
541                                char state1, char state2, bool_t isone)
542 {
543 
544    if(time1 == time2)
545    {
546       sig1->found = TRUE;
547       sig2->found = TRUE;
548       if(state1 != state2)
549       {
550          print_signal_info(sig1, sig2, time1, time2, isone);
551          printf("\t%c\n\t%c\n",state1, state2);
552 	 return;
553       }
554    }
555   else
556   {
557          print_signal_info(sig1, sig2, time1, time2, isone);
558          printf("%c #%lld \t%c\n", isone ? '>' : '<', time1, state1);
559 	 printf("%c #%lld \t%c\n", isone ? '>' : '<', time2, state2);
560 	      return;
561      }
562 }
563 
564 
565 /* print the vector value  */
print_vector_state(struct signal_t * sig1,struct signal_t * sig2,vtime_t time1,vtime_t time2,char * sval1,char * sval2,bool_t isone)566 static void print_vector_state(struct signal_t *sig1,
567                                struct signal_t *sig2,
568                                vtime_t time1, vtime_t time2,
569                                char *sval1, char *sval2, bool_t isone)
570 {
571  int size1, size2;
572  register int i;
573 
574  size1 = strlen(sval1);
575  size2 = strlen(sval2);
576  if(time1 == time2)
577  {
578     sig1->found = TRUE;
579     sig2->found = TRUE;
580    if(strcmp(sval1, sval2) != 0)
581    {
582        print_signal_info(sig1, sig2, time1, time2, isone);
583        if(size1 == size2)
584          printf("\t%s\n\t%s\n", sval1, sval2);
585        else
586        {
587          if(size1 > size2)
588          {
589            printf("\t%s\n\t", sval1);
590            for(i = 0; i < size1 - size2; i++)
591                putc(' ', stdout);
592            printf("%s\n", sval2);
593          }
594          else
595          {
596            printf("\t");
597            for(i = 0; i < size2-size1; i++)
598                putc(' ', stdout);
599            printf("%s\n\t%s\n", sval1, sval2);
600          }
601        }
602        return;
603       }
604    }
605   else
606   {
607      print_signal_info(sig1, sig2, time1, time2, isone);
608      if(size1 == size2)
609      {
610        printf("%c #%lld \t%s\n", isone ? '>' : '<', time1, sval1);
611        printf("%c #%lld \t%s\n", isone ? '>' : '<', time2, sval2);
612      }
613      else
614      {
615          if(size1 > size2)
616          {
617            printf("%c #%lld \t%s\n", isone ? '>' : '<', time1, sval1);
618            printf("%c #%lld \t", isone ? '>' : '<', time2);
619            for(i = 0; i < size1 - size2; i++)
620                putc(' ', stdout);
621            printf("%s\n", sval2);
622          }
623          else
624          {
625            printf("%c #%lld \t", isone ? '>' : '<', time1);
626            for(i = 0; i < size2-size1; i++)
627                putc(' ', stdout);
628            printf("%s\n", sval1);
629            printf("%c #%lld \t%s\n", isone ? '>' : '<', time2, sval2);
630          }
631      }
632    }
633 }
634 
635 
636 
637 /* print scalar edge value  */
print_scalar_edge(struct signal_t * sig1,struct signal_t * sig2,vtime_t time1,vtime_t time2,char state1,char state2,bool_t isone)638 static void print_scalar_edge(struct signal_t *sig1,
639                               struct signal_t *sig2,
640                               vtime_t time1, vtime_t time2,
641                               char state1, char state2, bool_t isone)
642 {
643 
644         if(time1 == time2)
645         {
646           sig1->found = TRUE;
647           sig2->found = TRUE;
648           if(state1 != state2)
649           {
650             print_signal_info(sig1, sig2, time1, time2, isone);
651 
652 	    if(sig1->state == state1)
653                printf("\t(%c-)\n", state1);
654 	    else
655                printf("\t(%c%c)\n", sig1->state, state1);
656 	    if(sig2->state == state2)
657                printf("\t(%c-)\n", state2);
658 	    else
659                printf("\t(%c%c)\n", sig2->state, state2);
660 	    return;
661 	  }
662 	 }
663          else
664 	 {
665            print_signal_info(sig1, sig2, time1, time2, isone);
666 
667            if(sig1->state == state1)
668               printf("%c #%lld \t(%c-)\n", isone ? '>' : '<', time1, state1);
669            else
670               printf("%c #%lld \t(%c%c)\n", isone ? '>' : '<', time1, sig1->state, state1);
671            if(sig2->state == state2)
672               printf("%c #%lld \t(%c-)\n", isone ? '>' : '<', time2, state2);
673            else
674               printf("%c #%lld \t(%c%c)\n", isone ? '>' : '<', time2, sig2->state, state2);
675            return;
676         }
677 }
678 
679 /* print the edge values
680   sig - signal pointer
681   sval - sval string value
682   str_size - size of sval
683   search - '<' or '>' if a search was performed otherwise 'n' for none
684   this is needed for wrapping of the line
685 */
print_edges(struct signal_t * sig,char * sval,int str_size,int vec_size,char searchc)686 static void print_edges(struct signal_t *sig, char *sval, int str_size,
687                         int vec_size, char searchc)
688 {
689  register int i;
690  int min, tprint;
691 
692  /*AIV 02/06/03 the print edges were wrong for different sizes */
693  /* for example, b10 is now b101 at the next time */
694  /* vector is the old value and sval is the new */
695 
696  if(str_size > vec_size)
697 	 min = vec_size;
698  else
699 	 min = str_size;
700 
701  tprint = 0;
702  for(i=0; i < min; i++, tprint++)
703  {
704    if(sig->vector[i] == sval[i])
705      printf(" (%c-)", sig->vector[i]);
706    else
707      printf(" (%c%c)", sig->vector[i], sval[i]);
708 
709    /* only want to print 11 edges per line */
710      if(wrap_flagG && tprint != 0 && !(tprint % EDGE_PER_LINE))
711      {
712         if(searchc != 'n')
713           printf(" \\\n%c\t", searchc);
714         else
715           printf(" \\\n\t");
716      }
717  }
718  if(str_size == vec_size) return;
719 
720  if(min == vec_size)
721  {
722    for(i = min; i < str_size; i++, tprint++)
723    {
724       printf(" (?%c)", sval[i]);
725       if(wrap_flagG && tprint != 0 && !(tprint % EDGE_PER_LINE))
726       {
727         if(searchc != 'n')
728           printf(" \\\n%c\t", searchc);
729         else
730           printf(" \\\n\t");
731       }
732    }
733  }
734  else
735  {
736    /* if the first value is a '?', no need to print the rest
737     * since it can only be '?' on the first value change */
738    if(sig->vector[0] != '?')
739    {
740      for(i = min; i < vec_size; i++, tprint++)
741      {
742       printf(" (%c?)", sig->vector[i]);
743       if(wrap_flagG && tprint != 0 && !(tprint % EDGE_PER_LINE))
744       {
745         if(searchc != 'n')
746           printf(" \\\n%c\t", searchc);
747         else
748           printf(" \\\n\t");
749       }
750      }
751    }
752  }
753 
754 }
755 
756 /* add space so the vector edge valued line up correctly */
edge_space(int size1,int size2,bool_t is_sigone)757 static void edge_space(int size1, int size2, bool_t is_sigone)
758 {
759  register int i, r, diff;
760 
761  if(size1 == size2) return;
762  if(is_sigone && size2 > size1)
763  {
764     diff = (size2 - size1) * CHAR_PER_EDGE;
765     if(wrap_flagG)
766     {
767       r = diff / EDGE_PER_LINE;
768       if(r > 0)
769       {
770         r = (r * EDGE_PER_LINE);
771         diff -= r;
772         if(diff <= CHAR_PER_EDGE) diff = 0;
773       }
774     }
775     for(i=0; i < diff; i++)
776          putc(' ', stdout);
777  }
778  if(!is_sigone && size1 > size2)
779  {
780      diff = (size1 - size2) * CHAR_PER_EDGE;
781      if(wrap_flagG)
782      {
783        r = diff / EDGE_PER_LINE;
784        if(r > 0)
785        {
786         r = (r * EDGE_PER_LINE);
787         diff -= r;
788         if(diff <= CHAR_PER_EDGE) diff = 0;
789        }
790      }
791      for(i=0; i < diff; i++)
792           putc(' ', stdout);
793  }
794 
795 }
796 
797 
798 
799 
800 /* print vector edge */
print_vector_edge(struct signal_t * sig1,struct signal_t * sig2,vtime_t time1,vtime_t time2,char * sval1,char * sval2,bool_t isone)801 static void print_vector_edge(struct signal_t *sig1,
802                               struct signal_t *sig2,
803                               vtime_t time1, vtime_t time2,
804                               char *sval1, char *sval2, bool_t isone)
805 {
806  int size1, size2;
807  int vsize1, vsize2;
808  int max1, max2;
809  char dirc;
810 
811    if(time1 == time2)
812    {
813        sig1->found = TRUE;
814        sig2->found = TRUE;
815 
816        if(strcmp(sval1, sval2) != 0)
817 	{
818 
819 	  if(sig1->type == REAL)
820 	  {
821             print_vector_state(sig1, sig2, time1, time2, sval1, sval2, isone);
822 	    return;
823 	  }
824 
825 	  print_signal_info(sig1, sig2, time1, time2, isone);
826           printf("\t");
827 
828           size1 = strlen(sval1);
829           vsize1 = strlen(sig1->vector);
830           max1 = MAX(size1, vsize1);
831 
832           size2 = strlen(sval2);
833           vsize2 = strlen(sig2->vector);
834           max2 = MAX(size2, vsize2);
835 
836           edge_space(max1, max2, TRUE);
837           print_edges(sig1, sval1, size1, vsize1, 'n');
838           if(wrap_flagG && sig1->size > EDGE_PER_LINE)
839              printf("\n\n\t");
840           else
841             printf("\n\t");
842           edge_space(max1, max2, FALSE);
843           print_edges(sig2, sval2, size2, vsize2, 'n');
844           printf("\n");
845 	  return;
846 	}
847    }
848    else
849    {
850 	 if(sig1->type == REAL)
851 	 {
852             print_vector_state(sig1, sig2, time1, time2, sval1, sval2, isone);
853 	    return;
854 	 }
855          print_signal_info(sig1, sig2, time1, time2, isone);
856          dirc = isone ? '>' : '<';
857          printf("%c #%lld \t", dirc, time1);
858 
859          size1 = strlen(sval1);
860          vsize1 = strlen(sig1->vector);
861          max1 = MAX(size1, vsize1);
862 
863          size2 = strlen(sval2);
864          vsize2 = strlen(sig2->vector);
865          max2 = MAX(size2, vsize2);
866 
867          edge_space(max1, max2, TRUE);
868          print_edges(sig1, sval1, size1, vsize1, dirc);
869          printf("\n%c #%lld \t", dirc, time2);
870          edge_space(max1, max2, FALSE);
871          print_edges(sig2, sval2, size2, vsize2, dirc);
872          printf("\n");
873 	 return;
874   }
875 }
876 
877 /* get the next time change in the other file if there is one */
get_nxt_chg(FILE * fp,char * fname,int * sigcode,int * bit,char * value,vtime_t * time,bool_t isone)878 static int get_nxt_chg(FILE *fp, char *fname, int *sigcode, int *bit,
879                        char *value, vtime_t *time, bool_t isone)
880 {
881  char *line;
882  char token[MAXTOKSIZE];
883 
884    while(get_token(fp, token) != EOF)
885    {
886       line = token;
887 
888       switch (*line++)
889       {
890         /* scalar cases */
891 	case '0':
892 	case '1':
893 	case 'z':
894 	case 'Z':
895 	case 'x':
896 	case 'X':
897           *bit = *(line-1);
898           *sigcode = VERILOG_ID_TO_POS(line);
899 
900          if(isone)
901          {
902            if(VERILOG_POS_TO_SIG1(*sigcode) == NULL)
903 	   {
904              printf("Unknown Identifier '%s' in file %d '%s' on line %d\n",
905 	        line, isone ? 1 : 2, fname,
906 	        isone ? line_num1G : line_num2G );
907 	     continue;
908 	   }
909 	 }
910 	 else if(VERILOG_POS_TO_SIG2(*sigcode) == NULL)
911 	 {
912            printf("Unknown Identifier '%s' in file %d '%s' on line %d\n",
913 	       line, isone ? 1 : 2, fname,
914                isone ? line_num1G : line_num2G );
915    	    continue;
916 	 }
917 	 return(SCALAR);
918 	 break;
919         /* vector or real cases */
920 	case 'b':
921 	case 'r':
922 	    strcpy(value, line);
923 	    get_token(fp, token);
924 	    *sigcode = VERILOG_ID_TO_POS(token);
925 	    if(isone)
926 	    {
927 	       if(VERILOG_POS_TO_SIG1(*sigcode) == NULL)
928 	       {
929                  printf("Unknown Identifier '%s' in file %d '%s' on line %d\n",
930 		        line, isone ? 1 : 2, fname,
931 		        isone ? line_num1G : line_num2G );
932 	       continue;
933 	       }
934 	    }
935 	    else if(VERILOG_POS_TO_SIG2(*sigcode) == NULL)
936 	    {
937                  printf("Unknown Identifier '%s' in file %d '%s' on line %d\n",
938 		        line, isone ? 1 : 2, fname,
939 		        isone ? line_num1G : line_num2G );
940 		 continue;
941 	    }
942 	    return(VECTOR);
943 
944         /* time change value */
945 	case '#':
946 	    *time = (vtime_t) atoll(line);
947 	    return(TIME);
948 	case '$':
949 	    /* AIV 02/03/03 need to read until $end for $comment */
950 	    if(!strcmp(line, "comment") || !strcmp(line, "dumpall"))
951 	       read_to_end(fp);
952 	    break;
953         default:
954 	    line--;
955             printf("***ERROR Unknown token '%s' in file %d '%s' on line %d\n",
956 	  	     line, isone ? 1 : 2, fname,
957 		     isone ? line_num1G : line_num2G );
958 	     /*FIXME shouldn't die here if possible */
959 	      exit(0);
960             continue;
961 	  break;
962 	}
963    }
964    return(EOF);
965 }
966 
967 /* used to place the string back on the fp to be used later */
restore(FILE * fp,char * str,int size)968 static void restore(FILE *fp, char *str, int size)
969 {
970  int i;
971  char *cp;
972 
973  ungetc(' ', fp);
974  cp = &str[size-1];
975 
976  for(i =0; i< size; i++, cp--)
977 	 ungetc(*cp, fp);
978 
979 }
980 
981 /* return true if the next signal isn't the same, otherwise false */
peek_nxt_sig(FILE * fp,int sigcode1,bool_t isone)982 static bool_t peek_nxt_sig(FILE *fp, int sigcode1, bool_t isone)
983 {
984   char tmp[MAXTOKSIZE], sig[MAXTOKSIZE];
985   int size1, size2, sigcode2;
986   char *cp;
987 
988   size1 = get_token(fp, tmp);
989   cp = tmp;
990 
991   if(tmp[0] == 'b')
992   {
993    size2 = get_token(fp, sig);
994    restore(fp, sig, size2);
995    restore(fp, tmp, size1);
996    cp = sig;
997   }
998   else if(tmp[0] == '0' || tmp[0] == '1' || tmp[0] =='x' || tmp[0] =='z')
999   {
1000       restore(fp, tmp, size1);
1001       cp++;
1002   }
1003   else
1004   {
1005    restore(fp, tmp, size1);
1006    return(TRUE);
1007   }
1008 
1009   /* map signal to the right sigcode */
1010   sigcode2 = VERILOG_ID_TO_POS(cp);
1011 
1012   /* LOOKATME can this ever happen ??*/
1013   if(sigcode2 > max_codeG) return(TRUE);
1014   if(isone)
1015   {
1016     if(fd2_to_fd1_mapG[sigcode2] == NULL) return(TRUE);
1017     sigcode2 = *fd2_to_fd1_mapG[sigcode2];
1018   }
1019   else
1020   {
1021     if(fd1_to_fd2_mapG[sigcode2] == NULL) return(TRUE);
1022     sigcode2 = *fd1_to_fd2_mapG[sigcode2];
1023   }
1024 
1025   return(sigcode1 != sigcode2);
1026 }
1027 
1028 
1029 /* rewind to file and reset line count to the start of a #time */
rewind_time(FILE * fp,long seek,vtime_t * time,vtime_t treset,int * linenum,int lreset)1030 static void rewind_time(FILE *fp, long seek, vtime_t *time,
1031   	                vtime_t treset, int *linenum, int lreset)
1032 {
1033   *time = treset;
1034   fseek(fp, seek, SEEK_SET);
1035  /* reset the line counts */
1036   *linenum = lreset;
1037 }
1038 
1039 
1040 /* get the differences of a time block from #time to the next #time2 or EOF */
1041 
get_time_diffs(FILE * mainfp,FILE * otherfp,char * mname,char * oname,long seek1,long seek2,vtime_t ltime1,vtime_t ltime2,bool_t isone)1042 static vtime_t get_time_diffs(FILE *mainfp, FILE *otherfp, char *mname,
1043                            char *oname, long seek1, long seek2,
1044                            vtime_t ltime1, vtime_t ltime2, bool_t isone)
1045 {
1046   char svalue1[MAXTOKSIZE], svalue2[MAXTOKSIZE];
1047   int retval;
1048   int sigcode1, sigcode2;
1049   int  state1, state2;
1050   int tmpline1, tmpline2;
1051   vtime_t time, nxt_time;
1052   struct signal_t *sig1, *sig2;
1053   bool_t first;
1054 
1055   sigcode1 = sigcode2 = 0;
1056   first = TRUE;
1057   time = ltime1;
1058   nxt_time = ltime2;
1059 
1060   /* AIV 02/04/03 added temps to reset line count for unkown tokens, etc */
1061    tmpline1 = line_num1G;
1062    tmpline2 = line_num2G;
1063 
1064 
1065   /* LOOKATME rewind needed here because of reset ungets, and seek from
1066      the start of the file, should write own buffer  */
1067    rewind(isone ? mainfp : otherfp);
1068    if(isone)
1069      fseek(mainfp, seek1, SEEK_CUR);
1070    else
1071      fseek(otherfp, seek2, SEEK_CUR);
1072 
1073   while(retval != EOF)
1074   {
1075 
1076     retval = get_nxt_chg(mainfp, mname, &sigcode1, &state1, svalue1, &time, isone);
1077     switch(retval)
1078     {
1079       case SCALAR:
1080       case VECTOR:
1081       /* rewind if the next sig isn't the same */
1082       /* LOOKATME could change so that if the first sig isn't*/
1083       /* get_nxt would rewind, to speed up ?? */
1084       if(!first && peek_nxt_sig(otherfp, sigcode1, isone))
1085       {
1086           rewind_time(otherfp, seek2, &nxt_time, ltime2,
1087 		      isone ? &line_num2G : &line_num1G,
1088 		      isone ? tmpline2 : tmpline1);
1089       }
1090 
1091       first = FALSE;
1092       if(isone)
1093       {
1094         sig1 = VERILOG_POS_TO_SIG1(sigcode1);
1095         sigcode1 = *fd1_to_fd2_mapG[sigcode1];
1096         sig2 = VERILOG_POS_TO_SIG2(sigcode1);
1097       }
1098       else
1099       {
1100         sig1 = VERILOG_POS_TO_SIG2(sigcode1);
1101         sigcode1 = *fd2_to_fd1_mapG[sigcode1];
1102         sig2 = VERILOG_POS_TO_SIG1(sigcode1);
1103       }
1104       if(!sig1->in_both)
1105 	    break;
1106       if(sig1->found)
1107       {
1108         sig1->found = FALSE;
1109         sig2->found = FALSE;
1110         if(retval == SCALAR) sig1->state = state1;
1111         else strcpy(sig1->vector, svalue1);
1112         break;
1113      }
1114      /*should check to see if sig1 and sig 2 are the same type??*/
1115      for(;;)
1116      {
1117        if(get_nxt_chg(otherfp, oname, &sigcode2, &state2, svalue2, &nxt_time, !isone) == EOF)
1118        {
1119           printf("%s (%s) Never found in file %d at time %lld\n", sig1->signame,
1120                      sig1->ident, isone ? 1 : 2, time);
1121          break;
1122        }
1123        else if(sigcode1 == sigcode2)
1124 	        break;
1125       }
1126 
1127      if(retval == SCALAR)
1128      {
1129 	if(state_flagG)
1130           print_scalar_state(sig1, sig2, time, nxt_time,
1131                                           state1, state2, isone);
1132 	else
1133           print_scalar_edge(sig1, sig2, time, nxt_time,
1134                                           state1, state2, isone);
1135         sig1->state = state1;
1136      }
1137      else if(retval == VECTOR)
1138      {
1139         if(state_flagG)
1140           print_vector_state(sig1, sig2, time, nxt_time,
1141                                          svalue1, svalue2, isone);
1142 	else
1143           print_vector_edge(sig1, sig2, time, nxt_time,
1144                                           svalue1, svalue2, isone);
1145        strcpy(sig1->vector, svalue1);
1146      }
1147     /* if isn't the same time must of scanned foward so rewind */
1148      if(nxt_time != time)
1149      {
1150         rewind_time(otherfp, seek2, &nxt_time, ltime2,
1151 		      isone ? &line_num2G : &line_num1G,
1152 		      isone ? tmpline2 : tmpline1);
1153      }
1154 
1155     break;
1156    case TIME:
1157       /* rewind to the start time, to process other file*/
1158      if(isone)
1159      {
1160          rewind_time(otherfp, seek2, &nxt_time, ltime2,
1161 		      isone ? &line_num2G : &line_num1G,
1162 		      isone ? tmpline2 : tmpline1);
1163      }
1164     if(time != 0)
1165        return(time);
1166     break;
1167   case EOF:
1168      quit_flagG = EOF;
1169      return(time);
1170   default:
1171 	   continue;
1172 	}
1173    }
1174   /*FIXME should never get here emit error */
1175   return(time);
1176 }
1177 
1178 
1179 
1180 /* print the map of identifiers to signal name between files */
print_map(void)1181 static void print_map(void)
1182 {
1183    register int i;
1184    struct signal_t *sig;
1185 
1186    for(i = 0; i< max_codeG; i++)
1187    {
1188     if(fd1_to_fd2_mapG[i] != NULL)
1189     {
1190         sig = VERILOG_POS_TO_SIG2(*fd1_to_fd2_mapG[i]);
1191 	if(!sig->in_both) continue;
1192 	printf("%d %d %s\n", i, *fd1_to_fd2_mapG[i], sig->signame);
1193 
1194     }
1195    }
1196    printf("*********Second*********\n");
1197    for(i = 0; i< max_codeG; i++)
1198    {
1199     if(fd2_to_fd1_mapG[i] != NULL)
1200      {
1201         sig = VERILOG_POS_TO_SIG1(*fd2_to_fd1_mapG[i]);
1202 	if(!sig->in_both) continue;
1203 	printf("%d %d %s\n", i, *fd2_to_fd1_mapG[i], sig->signame);
1204 
1205      }
1206    }
1207 
1208 }
1209 
1210 /* check to make sure the files are the same in type/size in both files */
compare_types(char * file_nam1,char * file_nam2,struct signal_t * sig1,struct signal_t * sig2)1211 static void compare_types(char *file_nam1, char *file_nam2,
1212                           struct signal_t *sig1, struct signal_t *sig2)
1213 {
1214 
1215   if(sig1->in_both)
1216   {
1217     if(sig1->type != sig2->type)
1218     {
1219       if(sig1->sig_code == sig2->sig_code)
1220          printf("WARNING - Ignoring signal %s (%s) - types don't match\n",
1221                     sig1->signame, sig1->ident);
1222       else
1223          printf("WARNING - Ignoring signal %s (%s %s) - types don't match\n",
1224                     sig1->signame, sig1->ident, sig2->ident);
1225 
1226       printf("\t file '%s' type '%s'\n", file_nam1, var_types[sig1->type].vnam);
1227       printf("\t file '%s' type '%s'\n\n", file_nam2, var_types[sig2->type].vnam);
1228       sig1->in_both = FALSE;
1229       sig2->in_both = FALSE;
1230       return;
1231     }
1232     if(sig1->size != sig2->size)
1233     {
1234        if(sig1->sig_code == sig2->sig_code)
1235           printf("WARNING - Ignoring signal %s (%s) - sizes don't match\n",
1236                         sig1->signame, sig1->ident);
1237        else
1238           printf("WARNING - Ignoring signal %s (%s %s) - sizes don't match\n",
1239                         sig1->signame, sig1->ident, sig2->ident);
1240 
1241         printf("\t file '%s' size '%d'\n", file_nam1, sig1->size);
1242         printf("\t file '%s' size '%d'\n\n", file_nam2, sig2->size);
1243         sig1->in_both = FALSE;
1244         sig2->in_both = FALSE;
1245         return;
1246      }
1247   }
1248 }
1249 
1250 /* map the signal names to identifiers from one file to the other */
map(char * file_nam1,char * file_nam2,int ** file_map,struct signal_t * startsig,struct signal_t * otherstart,struct signal_t ** sig_arr,bool_t isone)1251 static bool_t map(char *file_nam1, char *file_nam2, int **file_map,
1252                      struct signal_t *startsig, struct signal_t *otherstart,
1253                      struct signal_t **sig_arr, bool_t isone)
1254 {
1255   struct signal_t *sig1, *sig2;
1256   bool_t one_found;
1257 
1258 
1259   one_found = FALSE;
1260   for(sig1 = startsig; sig1 != NULL; sig1 = sig1->next)
1261   {
1262      if(isone)
1263        sig2 = VERILOG_POS_TO_SIG2(sig1->sig_code);
1264      else
1265        sig2 = VERILOG_POS_TO_SIG1(sig1->sig_code);
1266 
1267     if(sig2 == NULL)
1268     {
1269        for(sig2 = otherstart; sig2 != NULL; sig2 = sig2->next)
1270        {
1271            if(!sig2->in_both) continue;
1272            if(strcmp(sig1->signame, sig2->signame) == 0)
1273            {
1274               file_map[sig1->sig_code] = &sig2->sig_code;
1275               compare_types(file_nam1, file_nam2, sig1, sig2);
1276               one_found = TRUE;
1277               break;
1278            }
1279        }
1280     }
1281     else if(strcmp(sig1->signame, sig2->signame) == 0)
1282     {
1283         file_map[sig1->sig_code] = &sig1->sig_code;
1284         compare_types(file_nam1, file_nam2, sig1, sig2);
1285         one_found = TRUE;
1286     }
1287     else
1288     {
1289        for(sig2 = otherstart; sig2 != NULL; sig2 = sig2->next)
1290        {
1291            if(!sig2->in_both) continue;
1292            if(strcmp(sig1->signame, sig2->signame) == 0)
1293            {
1294               file_map[sig1->sig_code] = &sig2->sig_code;
1295               compare_types(file_nam1, file_nam2, sig1, sig2);
1296               one_found = TRUE;
1297               break;
1298            }
1299        }
1300     }
1301     if(sig2 == NULL)
1302     {
1303        printf("WARNING - Ignoring signal %s (%s) - not defined in both files\n", sig1->signame, sig1->ident);
1304        printf("\t  Defined in file '%s' and not file '%s'\n\n", file_nam1, file_nam2);
1305        file_map[sig1->sig_code] = &sig1->sig_code;
1306        sig1->in_both = FALSE;
1307     }
1308  }
1309 
1310   return(one_found);
1311 }
1312 
1313 /* map both files */
map_var_names(char * file_nam1,char * file_nam2)1314 static bool_t map_var_names(char *file_nam1, char *file_nam2)
1315 {
1316   fd1_to_fd2_mapG = (int**) malloc(sizeof(int) * max_codeG);
1317   fd2_to_fd1_mapG = (int**) malloc(sizeof(int) * max_codeG);
1318 
1319   map(file_nam1, file_nam2, fd1_to_fd2_mapG, sig1_hdG, sig2_hdG, sig_int1G, TRUE);
1320 
1321    return(map(file_nam2, file_nam1, fd2_to_fd1_mapG, sig2_hdG, sig1_hdG, sig_int2G, FALSE));
1322 
1323   //print_map();
1324 
1325 }
1326 
1327 /* acutally run the files to diff the two */
run_diffs(FILE * fp1,FILE * fp2,char * fnam1,char * fnam2,long start1,long start2)1328 static void run_diffs(FILE *fp1, FILE *fp2, char *fnam1, char *fnam2,
1329                       long start1, long start2)
1330 {
1331  vtime_t time1, time2, temp_time1;
1332  long temp1_chars;
1333  char token[MAXTOKSIZE];;
1334 
1335   time1 = time2 = temp_time1 = 0;
1336 
1337   while(quit_flagG != EOF)
1338   {
1339 
1340    /* while the times are the same */
1341    while(time1 == time2)
1342    {
1343      temp_time1 = time1;
1344      time1 =  get_time_diffs(fp1, fp2, fnam1, fnam2, start1, start2,
1345                               time1, time2, TRUE);
1346      temp1_chars = ftell(fp1);
1347 
1348      time2 =  get_time_diffs(fp2, fp1, fnam2, fnam1, start2, start1,
1349                               time2, temp_time1, FALSE);
1350      start2=ftell(fp2);
1351      start1=temp1_chars;
1352      if(quit_flagG) break;
1353    }
1354 
1355    /* time one is ahead */
1356     while(time2 < time1)
1357     {
1358      time2 = get_time_diffs(fp2, fp1, fnam2, fnam1, start2, start1,
1359                              time2, temp_time1, FALSE);
1360      start2 = ftell(fp2);
1361      if(quit_flagG)
1362      {
1363           if(get_token(fp1, token) != EOF)
1364 	  {
1365 		  printf("*****End of file hit at file 2 ('%s') time %lld quiting\n", fnam2, time2);
1366 		  printf("WARNING - Files have different end times\n");
1367 	  }
1368 	  break;
1369      }
1370    }
1371 
1372 
1373    /* while time two is ahead */
1374     while(time1 < time2)
1375     {
1376      time1 =  get_time_diffs(fp1, fp2, fnam1, fnam2, start1, start2, time1, time2, TRUE);
1377      start1=ftell(fp1);
1378      if(quit_flagG)
1379      {
1380           if(get_token(fp2, token) != EOF)
1381 	  {
1382 		  printf("*****End of file hit at file 1 ('%s') time %lld quiting\n", fnam1, time1);
1383 		  printf("WARNING - Files have different end times\n");
1384 	  }
1385           break;
1386      }
1387     }
1388   }
1389 }
1390 
1391 /* print help information */
print_help(void)1392 static void print_help(void)
1393 {
1394   printf("Usage: [options] 'file1' 'file2'\n Compares Verilog VCD dump files.\n\n");
1395 
1396   printf(" --state \n -s \n");
1397   printf("\tPrints the current state of variables, instead of\n \tthe default edge value. \n");
1398   printf(" --wrap  \n -w \n");
1399   printf("\tWraps the line, only used for default edge print values\n\tnot --state print messages. \n");
1400   exit(0);
1401 }
1402 
1403 
1404 /* print program header info */
print_header(void)1405 static void print_header(void)
1406 {
1407  char s1[30];
1408  time_t now;
1409 
1410  printf("%s_%s of %s (%s).\n", "vcddiff", VERS2, OFDT, "Linux-ELF");
1411  printf("Copyright (c) 2002-2004 Pragmatic C Software Corp.\n");
1412  printf("All Rights reserved.  Licensed under the GNU General Public License (GPL).\n");
1413  printf("See the 'COPYING' file for details.  NO WARRANTY provided.\n");
1414  time(&now);
1415  strcpy(s1, ctime(&now));
1416  s1[24] = '\0';
1417  printf("Today is %s.\n\n", s1);
1418 
1419 }
1420 
set_options(int argc,char ** argv)1421 static void set_options(int argc, char **argv)
1422 {
1423  int i;
1424 
1425  for(i = 1; i < argc-2; i++)
1426  {
1427    if(!strcmp(argv[i], "--state") || !strcmp(argv[i],"-s"))
1428    {
1429       if(wrap_flagG)
1430         printf("WARNING - wrap cannot be used with --state option, wrap disabled\n\n");
1431       else
1432        state_flagG = TRUE;
1433    }
1434    else if(!strcmp(argv[i], "--wrap") || !strcmp(argv[i],"-w"))
1435    {
1436       if(state_flagG)
1437         printf("WARNING - wrap cannot be used with --state option, wrap disabled\n\n");
1438       else
1439         wrap_flagG = TRUE;
1440    }
1441    else
1442    {
1443      printf("ERROR - Unknown option %s\n", argv[i]);
1444      printf("\t Try 'vcddiff --help' for more infomation\n");
1445      exit(0);
1446    }
1447  }
1448 
1449 }
1450 
1451 
main(int argc,char ** argv)1452 int main(int argc, char **argv)
1453 {
1454    int unit1, unit2, tnum1, tnum2;
1455    long start1, start2;
1456    char *file_nam1, *file_nam2;
1457    bool_t map_found;
1458    FILE *fp1, *fp2;
1459 
1460   quit_flagG = FALSE;
1461   sig1_hdG = NULL;
1462   sig2_hdG = NULL;
1463 
1464    print_header();
1465    if(argc < 2)
1466    {
1467      printf("ERROR - Usage: [options] 'file1' 'file2'\n");
1468      printf("\t Try 'vcddiff --help' for more infomation\n");
1469      exit(1);
1470    }
1471    if(!strcmp(argv[1], "--help") || !strcmp(argv[1],"-h"))
1472       print_help();
1473 
1474    if(argc < 3)
1475    {
1476      printf("ERROR - Usage: [options] 'file1' 'file2'\n");
1477      printf("\t Try 'vcddiff --help' for more infomation\n");
1478      exit(1);
1479    }
1480 
1481 
1482    wrap_flagG = state_flagG = FALSE;
1483 
1484    if((fp1 = fopen(argv[argc-2], "r")) == NULL)
1485    {
1486      printf("*** ERROR-opening file %s\n", argv[argc-2]);
1487      exit(1);
1488    }
1489 
1490    /* set first file to the global pointer to check the line count */
1491    file1G = fp1;
1492 
1493    if((fp2 = fopen(argv[argc-1], "r")) == NULL)
1494    {
1495      printf("*** ERROR-opening file %s\n", argv[argc-1]);
1496      exit(1);
1497    }
1498    set_options(argc, argv);
1499 
1500    sig_int1G = NULL;
1501    sig_int2G = NULL;
1502 
1503    /*could skip copying the filename, just pass argv*/
1504    file_nam1 = (char*) malloc(strlen(argv[argc-2])+ 1);
1505    strcpy(file_nam1, argv[argc-2]);
1506    start1 = get_lines(fp1, &unit1, &tnum1, file_nam1);
1507 
1508    file_nam2 = (char *) malloc(strlen(argv[argc-1]) + 1);
1509    strcpy(file_nam2, argv[argc-1]);
1510    start2 = get_lines(fp2, &unit2, &tnum2, file_nam2);
1511    alloc_sig_mem();
1512    map_found = map_var_names(file_nam1, file_nam2);
1513 
1514 
1515   if(map_found)
1516   {
1517    if(tnum1 != tnum2)
1518    {
1519      printf("*** ERROR-dump files have different timescale time numbers '%d' in file 1, and '%d' in file 2\n", tnum1, tnum2);
1520      exit(1);
1521    }
1522 
1523    if(unit1 != unit2)
1524    {
1525      printf("*** ERROR-dump files have different time scale units '%cs' in file 1, and '%cs' in file 2\n", unit1, unit2);
1526      exit(1);
1527    }
1528 
1529     run_diffs(fp1, fp2, file_nam1, file_nam2, start1, start2);
1530   }
1531   else
1532      printf("*** ERROR-dump files have no matching variables to diff\n");
1533 
1534    /* free and close */
1535    free (sig_int1G);
1536    free (sig_int2G);
1537    free(fd1_to_fd2_mapG);
1538    free(fd2_to_fd1_mapG);
1539    fclose(fp1);
1540    fclose(fp2);
1541    return(0);
1542 
1543 }
1544