ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/radcompare.c
Revision: 2.14
Committed: Fri Oct 19 23:56:15 2018 UTC (5 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.13: +18 -18 lines
Log Message:
Renamed ptr to str

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: radcompare.c,v 2.13 2018/10/19 23:50:32 greg Exp $";
3 #endif
4 /*
5 * Compare Radiance files for significant differences
6 *
7 * G. Ward
8 */
9
10 #include <stdlib.h>
11 #include <math.h>
12 #include <ctype.h>
13 #include "platform.h"
14 #include "rtio.h"
15 #include "resolu.h"
16 #include "color.h"
17 #include "lookup.h"
18 /* Reporting levels */
19 #define REP_QUIET 0 /* no reporting */
20 #define REP_ERROR 1 /* report errors only */
21 #define REP_WARN 2 /* report warnings as well */
22 #define REP_VERBOSE 3 /* verbose reporting */
23
24 int report = REP_WARN; /* reporting level */
25
26 int ign_header = 0; /* ignore header differences? */
27
28 double rel_min = 1e-5; /* positive for relative comparisons */
29
30 double rms_lim = 0.01; /* RMS difference limit */
31
32 double max_lim = 0.25; /* difference limit if non-negative */
33
34 int lin1cnt=0, lin2cnt=0; /* file line position */
35
36 const char nsuffix[10][3] = { /* 1st, 2nd, 3rd, etc. */
37 "th","st","nd","rd","th","th","th","th","th","th"
38 };
39 #define num_sfx(n) nsuffix[(n)%10]
40
41 /* file types */
42 const char *file_type[] = {
43 "Unrecognized",
44 "TEXT_generic",
45 "ascii",
46 COLRFMT,
47 CIEFMT,
48 "float",
49 "double",
50 "BSDF_RBFmesh",
51 "Radiance_octree",
52 "Radiance_tmesh",
53 "BINARY_unknown",
54 NULL /* terminator */
55 };
56 /* keep consistent with above */
57 enum {TYP_UNKNOWN, TYP_TEXT, TYP_ASCII, TYP_RGBE, TYP_XYZE, TYP_FLOAT,
58 TYP_DOUBLE, TYP_RBFMESH, TYP_OCTREE, TYP_TMESH, TYP_BINARY};
59
60 #define has_header(t) (!( 1L<<(t) & (1L<<TYP_TEXT | 1L<<TYP_BINARY) ))
61
62 /* header variables to always ignore */
63 const char *hdr_ignkey[] = {
64 "SOFTWARE",
65 "CAPDATE",
66 "GMT",
67 NULL /* terminator */
68 };
69 /* header variable settings */
70 LUTAB hdr1 = LU_SINIT(free,free);
71 LUTAB hdr2 = LU_SINIT(free,free);
72
73 /* advance appropriate file line count */
74 #define adv_linecnt(htp) (lin1cnt += (htp == &hdr1), \
75 lin2cnt += (htp == &hdr2))
76
77 typedef struct { /* dynamic line buffer */
78 char *str;
79 int len;
80 int siz;
81 } LINEBUF;
82
83 #define init_line(bp) ((bp)->str = NULL, (bp)->siz = 0)
84 /* 100 MByte limit on line buffer */
85 #define MAXBUF (100L<<20)
86
87 /* input files */
88 char *progname = NULL;
89 const char stdin_name[] = "<stdin>";
90 const char *f1name=NULL, *f2name=NULL;
91 FILE *f1in=NULL, *f2in=NULL;
92
93 /* running real differences */
94 double diff2sum = 0;
95 long nsum = 0;
96
97 /* Report usage and exit */
98 static void
99 usage()
100 {
101 fputs("Usage: ", stderr);
102 fputs(progname, stderr);
103 fputs(" [-h][-s|-w|-v][-rel min_test][-rms epsilon][-max epsilon] reference test\n",
104 stderr);
105 exit(2);
106 }
107
108 /* Read a text line, increasing buffer size as necessary */
109 static int
110 read_line(LINEBUF *bp, FILE *fp)
111 {
112 bp->len = 0;
113 if (!bp->str) {
114 bp->str = (char *)malloc(bp->siz = 512);
115 if (!bp->str)
116 goto memerr;
117 }
118 while (fgets(bp->str + bp->len, bp->siz - bp->len, fp)) {
119 bp->len += strlen(bp->str + bp->len);
120 if (bp->str[bp->len-1] == '\n')
121 break; /* found EOL */
122 if (bp->len < bp->siz - 4)
123 continue; /* at EOF? */
124 if (bp->siz >= MAXBUF)
125 break; /* don't go to extremes */
126 if ((bp->siz += bp->siz/2) > MAXBUF)
127 bp->siz = MAXBUF;
128 bp->str = (char *)realloc(bp->str, bp->siz);
129 if (!bp->str)
130 goto memerr;
131 }
132 return(bp->len);
133 memerr:
134 fprintf(stderr,
135 "%s: out of memory in read_line() allocating %d byte buffer\n",
136 progname, bp->siz);
137 exit(2);
138 }
139
140 /* Free line buffer */
141 static void
142 free_line(LINEBUF *bp)
143 {
144 if (bp->str) free(bp->str);
145 init_line(bp);
146 }
147
148 /* Get type ID from name (or 0 if not found) */
149 static int
150 xlate_type(const char *nm)
151 {
152 int i;
153
154 if (!nm || !*nm)
155 return(TYP_UNKNOWN);
156 for (i = 1; file_type[i]; i++)
157 if (!strcmp(nm, file_type[i]))
158 return(i);
159 return(TYP_UNKNOWN);
160 }
161
162 /* Compare real values and keep track of differences */
163 static int
164 real_check(double r1, double r2)
165 {
166 double diff2 = (r1 - r2)*(r1 - r2);
167
168 if (rel_min > 0) { /* doing relative differences? */
169 double av2 = .25*(r1*r1 + 2.*fabs(r1*r2) + r2*r2);
170 if (av2 > rel_min*rel_min)
171 diff2 /= av2;
172 }
173 if (max_lim >= 0 && diff2 > max_lim*max_lim) {
174 if (report != REP_QUIET)
175 printf(
176 "%s: %sdifference between %.8g and %.8g exceeds epsilon of %.8g\n",
177 progname,
178 (rel_min > 0) ? "relative " : "",
179 r1, r2, max_lim);
180 return(0);
181 }
182 diff2sum += diff2;
183 nsum++;
184 return(1);
185 }
186
187 /* Compare two color values for equivalence */
188 static int
189 color_check(COLOR c1, COLOR c2)
190 {
191 int p;
192
193 if (!real_check(colval(c1,RED)+colval(c1,GRN)+colval(c1,BLU)*(1./3.),
194 colval(c2,RED)+colval(c2,GRN)+colval(c2,BLU))*(1./3.))
195 return(0);
196
197 p = (colval(c1,GRN) > colval(c1,RED)) ? GRN : RED;
198 if (colval(c1,BLU) > colval(c1,p)) p = BLU;
199
200 return(real_check(colval(c1,p), colval(c2,p)));
201 }
202
203 /* Compare two strings for equivalence */
204 static int
205 equiv_string(char *s1, char *s2)
206 {
207 #define CLS_STR 0
208 #define CLS_INT 1
209 #define CLS_FLT 2
210 /* skip whitespace at beginning */
211 while (isspace(*s1)) s1++;
212 while (isspace(*s2)) s2++;
213 while (*s1) { /* check each word */
214 int inquote;
215 if (!*s2) /* unexpected EOL in s2? */
216 return(0);
217 inquote = *s1;
218 if ((inquote != '\'') & (inquote != '"'))
219 inquote = 0;
220 if (inquote) { /* quoted text must match exactly */
221 if (*s1++ != *s2++)
222 return(0);
223 while (*s1 != inquote) {
224 if (!*s1)
225 return(0);
226 if (*s1++ != *s2++)
227 return(0);
228 }
229 s1++;
230 if (*s2++ != inquote)
231 return(0);
232 } else { /* else classify word type */
233 char *s1s = s1;
234 char *s2s = s2;
235 int cls = CLS_STR;
236 s1 = sskip(s1);
237 s2 = sskip(s2);
238 if (iskip(s1s) == s1) {
239 if (iskip(s2s) == s2)
240 cls = CLS_INT;
241 else if (fskip(s2s) == s2)
242 cls = CLS_FLT;
243 } else if (fskip(s1s) == s1) {
244 if (fskip(s2s) != s2)
245 return(0);
246 cls = CLS_FLT;
247 }
248 switch (cls) {
249 case CLS_INT: /* strncmp() faster */
250 case CLS_STR:
251 if (s1 - s1s != s2 - s2s)
252 return(0);
253 if (strncmp(s1s, s2s, s1 - s1s))
254 return(0);
255 break;
256 case CLS_FLT:
257 if (!real_check(atof(s1s), atof(s2s)))
258 return(0);
259 break;
260 }
261 }
262 while (isspace(*s1)) s1++;
263 while (isspace(*s2)) s2++;
264 }
265 return(!*s2); /* match if we reached the end of s2, too */
266 #undef CLS_STR
267 #undef CLS_INT
268 #undef CLS_FLT
269 }
270
271 /* Check if string is var=value pair and set if not in ignore list */
272 static int
273 setheadvar(char *val, void *p)
274 {
275 LUTAB *htp = (LUTAB *)p;
276 LUENT *tep;
277 char *key;
278 int kln, vln;
279 int n;
280
281 adv_linecnt(htp); /* side-effect is to count lines */
282 if (!isalpha(*val)) /* key must start line */
283 return(0);
284 key = val++;
285 while (*val && !isspace(*val) & (*val != '='))
286 val++;
287 kln = val - key;
288 while (isspace(*val)) /* check for value */
289 *val++ = '\0';
290 if (*val != '=')
291 return(0);
292 *val++ = '\0';
293 while (isspace(*val))
294 val++;
295 if (!*val) /* nothing set? */
296 return(0);
297 /* check if key to ignore */
298 for (n = 0; hdr_ignkey[n]; n++)
299 if (!strcmp(key, hdr_ignkey[n]))
300 return(0);
301 vln = strlen(val); /* eliminate space and newline at end */
302 while (isspace(val[--vln]))
303 ;
304 val[++vln] = '\0';
305 if (!(tep = lu_find(htp, key)))
306 return(-1); /* memory allocation error */
307 if (!tep->key)
308 tep->key = strcpy(malloc(kln+1), key);
309 if (tep->data)
310 free(tep->data);
311 tep->data = strcpy(malloc(vln+1), val);
312 return(1);
313 }
314
315 /* Lookup correspondent in other header */
316 static int
317 match_val(const LUENT *ep1, void *p2)
318 {
319 const LUENT *ep2 = lu_find((LUTAB *)p2, ep1->key);
320 if (!ep2 || !ep2->data) {
321 if (report != REP_QUIET)
322 printf("%s: variable '%s' missing in '%s'\n",
323 progname, ep1->key, f2name);
324 return(-1);
325 }
326 if (!equiv_string((char *)ep1->data, (char *)ep2->data)) {
327 if (report != REP_QUIET) {
328 printf("%s: header variable '%s' has different values\n",
329 progname, ep1->key);
330 if (report >= REP_VERBOSE) {
331 printf("%s: %s=%s\n", f1name,
332 ep1->key, (char *)ep1->data);
333 printf("%s: %s=%s\n", f2name,
334 ep2->key, (char *)ep2->data);
335 }
336 }
337 return(-1);
338 }
339 return(1); /* good match */
340 }
341
342 /* Compare two sets of header variables */
343 static int
344 headers_match()
345 {
346 int ne = lu_doall(&hdr1, match_val, &hdr2);
347 if (ne < 0)
348 return(0); /* something didn't match! */
349 /* non-fatal if second header has extra */
350 if (report >= REP_WARN && (ne = lu_doall(&hdr2, NULL, NULL) - ne))
351 printf("%s: warning - '%s' has %d extra header setting(s)\n",
352 progname, f2name, ne);
353 return(1); /* good match */
354 }
355
356 /* Check generic input to determine if it is binary, -1 on error */
357 static int
358 input_is_binary(FILE *fin)
359 {
360 int n = 0;
361 int c = 0;
362
363 while ((c = getc(fin)) != EOF) {
364 ++n;
365 if (!c | (c > 127))
366 break; /* non-ascii character */
367 if (n >= 10240)
368 break; /* enough to be confident */
369 }
370 if (!n)
371 return(-1); /* first read failed */
372 if (fseek(fin, 0L, 0) < 0)
373 return(-1); /* rewind failed */
374 return(!c | (c > 127));
375 }
376
377 /* Identify and return data type from header (if one) */
378 static int
379 identify_type(const char *name, FILE *fin, LUTAB *htp)
380 {
381 extern const char HDRSTR[];
382 int c;
383 /* check magic header start */
384 if ((c = getc(fin)) != HDRSTR[0]) {
385 if (c == EOF) goto badeof;
386 ungetc(c, fin);
387 c = 0;
388 } else if ((c = getc(fin)) != HDRSTR[1]) {
389 if (c == EOF) goto badeof;
390 ungetc(c, fin); ungetc(HDRSTR[0], fin);
391 c = 0;
392 }
393 if (c) { /* appears to have a header */
394 char sbuf[32];
395 if (!fgets(sbuf, sizeof(sbuf), fin))
396 goto badeof;
397 adv_linecnt(htp); /* for #?ID string */
398 if (report >= REP_WARN && strncmp(sbuf, "RADIANCE", 8)) {
399 fputs(name, stdout);
400 fputs(": warning - unexpected header ID: ", stdout);
401 fputs(sbuf, stdout);
402 }
403 if (getheader(fin, setheadvar, htp) < 0) {
404 fputs(name, stderr);
405 fputs(": unknown error reading header\n", stderr);
406 return(-1);
407 }
408 adv_linecnt(htp); /* for trailing emtpy line */
409 return(xlate_type((const char *)lu_find(htp,"FORMAT")->data));
410 }
411 c = input_is_binary(fin); /* else peek to see if binary */
412 if (c < 0) {
413 fputs(name, stderr);
414 fputs(": read/seek error\n", stderr);
415 return(-1);
416 }
417 if (c)
418 return(TYP_BINARY);
419 SET_FILE_TEXT(fin); /* originally set to binary */
420 return(TYP_TEXT);
421 badeof:
422 if (report != REP_QUIET) {
423 fputs(name, stdout);
424 fputs(": unexpected end-of-file\n", stdout);
425 }
426 return(-1);
427 }
428
429 /* Check that overall RMS error is below threshold */
430 static int
431 good_RMS()
432 {
433 if (!nsum)
434 return(1);
435 if (diff2sum/(double)nsum > rms_lim*rms_lim) {
436 if (report != REP_QUIET)
437 printf(
438 "%s: %sRMS difference between '%s' and '%s' of %.5g exceeds limit of %.5g\n",
439 progname,
440 (rel_min > 0) ? "relative " : "",
441 f1name, f2name,
442 sqrt(diff2sum/(double)nsum), rms_lim);
443 return(0);
444 }
445 if (report >= REP_VERBOSE)
446 printf("%s: %sRMS difference of reals in '%s' and '%s' is %.5g\n",
447 progname, (rel_min > 0) ? "relative " : "",
448 f1name, f2name, sqrt(diff2sum/(double)nsum));
449 return(1);
450 }
451
452 /* Compare two inputs as generic binary files */
453 static int
454 compare_binary()
455 {
456 int c1=0, c2=0;
457
458 if (report >= REP_VERBOSE) {
459 fputs(progname, stdout);
460 fputs(": comparing inputs as binary\n", stdout);
461 }
462 for ( ; ; ) { /* exact byte matching */
463 c1 = getc(f1in);
464 c2 = getc(f2in);
465 if (c1 == EOF) {
466 if (c2 == EOF)
467 return(1); /* success! */
468 if (report != REP_QUIET) {
469 fputs(f1name, stdout);
470 fputs(": unexpected end-of-file\n", stdout);
471 }
472 return(0);
473 }
474 if (c2 == EOF) {
475 if (report != REP_QUIET) {
476 fputs(f2name, stdout);
477 fputs(": unexpected end-of-file\n", stdout);
478 }
479 return(0);
480 }
481 if (c1 != c2)
482 break; /* quit and report difference */
483 }
484 if (report == REP_QUIET)
485 return(0);
486 printf("%s: binary files '%s' and '%s' differ at byte offset %ld|%ld\n",
487 progname, f1name, f2name, ftell(f1in), ftell(f2in));
488 if (report >= REP_VERBOSE)
489 printf("%s: byte in '%s' is 0x%X, byte in '%s' is 0x%X\n",
490 progname, f1name, c1, f2name, c2);
491 return(0);
492 }
493
494 /* Compare two inputs as generic text files */
495 static int
496 compare_text()
497 {
498 LINEBUF l1buf, l2buf;
499
500 if (report >= REP_VERBOSE) {
501 fputs(progname, stdout);
502 fputs(": comparing inputs as ASCII text\n", stdout);
503 }
504 init_line(&l1buf); init_line(&l2buf); /* compare a line at a time */
505 while (read_line(&l1buf, f1in)) {
506 lin1cnt++;
507 if (!*sskip2(l1buf.str,0))
508 continue; /* ignore empty lines */
509
510 while (read_line(&l2buf, f2in)) {
511 lin2cnt++;
512 if (*sskip2(l2buf.str,0))
513 break; /* found other non-empty line */
514 }
515 if (!l2buf.len) { /* input 2 EOF? */
516 if (report != REP_QUIET) {
517 fputs(f2name, stdout);
518 fputs(": unexpected end-of-file\n", stdout);
519 }
520 free_line(&l1buf); free_line(&l2buf);
521 return(0);
522 }
523 /* compare non-empty lines */
524 if (!equiv_string(l1buf.str, l2buf.str)) {
525 if (report != REP_QUIET) {
526 printf("%s: inputs '%s' and '%s' differ at line %d|%d\n",
527 progname, f1name, f2name,
528 lin1cnt, lin2cnt);
529 if ( report >= REP_VERBOSE &&
530 (l1buf.len < 256) &
531 (l2buf.len < 256) ) {
532 fputs("------------- Mismatch -------------\n", stdout);
533 printf("%s@%d:\t%s", f1name,
534 lin1cnt, l1buf.str);
535 printf("%s@%d:\t%s", f2name,
536 lin2cnt, l2buf.str);
537 }
538 }
539 free_line(&l1buf); free_line(&l2buf);
540 return(0);
541 }
542 }
543 free_line(&l1buf); /* check for EOF on input 2 */
544 while (read_line(&l2buf, f2in)) {
545 if (!*sskip2(l2buf.str,0))
546 continue;
547 if (report != REP_QUIET) {
548 fputs(f1name, stdout);
549 fputs(": unexpected end-of-file\n", stdout);
550 }
551 free_line(&l2buf);
552 return(0);
553 }
554 free_line(&l2buf);
555 return(good_RMS()); /* final check for reals */
556 }
557
558 /* Compare two inputs that are known to be RGBE or XYZE images */
559 static int
560 compare_hdr()
561 {
562 RESOLU rs1, rs2;
563 COLOR *scan1, *scan2;
564 int x, y;
565
566 if (report >= REP_VERBOSE) {
567 fputs(progname, stdout);
568 fputs(": comparing inputs as HDR images\n", stdout);
569 }
570 fgetsresolu(&rs1, f1in);
571 fgetsresolu(&rs2, f2in);
572 if (rs1.rt != rs2.rt) {
573 if (report != REP_QUIET)
574 printf(
575 "%s: Images '%s' and '%s' have different pixel ordering\n",
576 progname, f1name, f2name);
577 return(0);
578 }
579 if ((rs1.xr != rs2.xr) | (rs1.yr != rs2.yr)) {
580 if (report != REP_QUIET)
581 printf(
582 "%s: Images '%s' and '%s' are different sizes\n",
583 progname, f1name, f2name);
584 return(0);
585 }
586 scan1 = (COLOR *)malloc(scanlen(&rs1)*sizeof(COLOR));
587 scan2 = (COLOR *)malloc(scanlen(&rs2)*sizeof(COLOR));
588 if (!scan1 | !scan2) {
589 fprintf(stderr, "%s: out of memory in compare_hdr()\n", progname);
590 exit(2);
591 }
592 for (y = 0; y < numscans(&rs1); y++) {
593 if ((freadscan(scan1, scanlen(&rs1), f1in) < 0) |
594 (freadscan(scan2, scanlen(&rs2), f2in) < 0)) {
595 if (report != REP_QUIET)
596 printf("%s: unexpected end-of-file\n",
597 progname);
598 free(scan1);
599 free(scan2);
600 return(0);
601 }
602 for (x = 0; x < scanlen(&rs1); x++) {
603 if (color_check(scan1[x], scan2[x]))
604 continue;
605 if (report != REP_QUIET) {
606 printf(
607 "%s: pixels at scanline %d offset %d differ\n",
608 progname, y, x);
609 if (report >= REP_VERBOSE) {
610 printf("%s: (R,G,B)=(%g,%g,%g)\n",
611 f1name, colval(scan1[x],RED),
612 colval(scan1[x],GRN),
613 colval(scan1[x],BLU));
614 printf("%s: (R,G,B)=(%g,%g,%g)\n",
615 f2name, colval(scan2[x],RED),
616 colval(scan2[x],GRN),
617 colval(scan2[x],BLU));
618 }
619 }
620 free(scan1);
621 free(scan2);
622 return(0);
623 }
624 }
625 free(scan1);
626 free(scan2);
627 return(good_RMS()); /* final check of RMS */
628 }
629
630 /* Compare two inputs that are known to be 32-bit floating-point data */
631 static int
632 compare_float()
633 {
634 long nread = 0;
635 float f1, f2;
636
637 if (report >= REP_VERBOSE) {
638 fputs(progname, stdout);
639 fputs(": comparing inputs as 32-bit IEEE floats\n", stdout);
640 }
641 while (getbinary(&f1, sizeof(f1), 1, f1in)) {
642 if (!getbinary(&f2, sizeof(f2), 1, f2in))
643 goto badeof;
644 ++nread;
645 if (real_check(f1, f2))
646 continue;
647 if (report != REP_QUIET)
648 printf("%s: %ld%s float values differ\n",
649 progname, nread, num_sfx(nread));
650 return(0);
651 }
652 if (!getbinary(&f2, sizeof(f2), 1, f2in))
653 return(good_RMS()); /* final check of RMS */
654 badeof:
655 if (report != REP_QUIET)
656 printf("%s: unexpected end-of-file\n", progname);
657 return(0);
658 }
659
660 /* Compare two inputs that are known to be 64-bit floating-point data */
661 static int
662 compare_double()
663 {
664 long nread = 0;
665 double f1, f2;
666
667 if (report >= REP_VERBOSE) {
668 fputs(progname, stdout);
669 fputs(": comparing inputs as 64-bit IEEE doubles\n", stdout);
670 }
671 while (getbinary(&f1, sizeof(f1), 1, f1in)) {
672 if (!getbinary(&f2, sizeof(f2), 1, f2in))
673 goto badeof;
674 ++nread;
675 if (real_check(f1, f2))
676 continue;
677 if (report != REP_QUIET)
678 printf("%s: %ld%s double values differ\n",
679 progname, nread, num_sfx(nread));
680 return(0);
681 }
682 if (!getbinary(&f2, sizeof(f2), 1, f2in))
683 return(good_RMS()); /* final check of RMS */
684 badeof:
685 if (report != REP_QUIET)
686 printf("%s: unexpected end-of-file\n", progname);
687 return(0);
688 }
689
690 /* Compare two Radiance files for equivalence */
691 int
692 main(int argc, char *argv[])
693 {
694 int typ1, typ2;
695 int a;
696
697 progname = argv[0];
698 for (a = 1; a < argc && argv[a][0] == '-'; a++) {
699 switch (argv[a][1]) {
700 case 'h': /* ignore header info. */
701 ign_header = !ign_header;
702 continue;
703 case 's': /* silent operation */
704 report = REP_QUIET;
705 continue;
706 case 'w': /* turn off warnings */
707 if (report > REP_ERROR)
708 report = REP_ERROR;
709 continue;
710 case 'v': /* turn on verbose mode */
711 report = REP_VERBOSE;
712 continue;
713 case 'm': /* maximum epsilon */
714 max_lim = atof(argv[++a]);
715 continue;
716 case 'r':
717 if (argv[a][2] == 'e') /* relative difference */
718 rel_min = atof(argv[++a]);
719 else if (argv[a][2] == 'm') /* RMS limit */
720 rms_lim = atof(argv[++a]);
721 else
722 usage();
723 continue;
724 case '\0': /* first file from stdin */
725 f1in = stdin;
726 f1name = stdin_name;
727 break;
728 default:
729 usage();
730 }
731 break;
732 }
733 if (a != argc-2) /* make sure of two inputs */
734 usage();
735 if (!strcmp(argv[a], argv[a+1])) { /* inputs are same? */
736 if (report >= REP_WARN)
737 printf("%s: warning - identical inputs given\n",
738 progname);
739 return(0);
740 }
741 if (!f1name) f1name = argv[a];
742 if (!f2name) f2name = argv[a+1];
743 /* open inputs */
744 SET_FILE_BINARY(stdin); /* in case we're using it */
745 if (!f1in && !(f1in = fopen(f1name, "rb"))) {
746 fprintf(stderr, "%s: cannot open for reading\n", f1name);
747 return(2);
748 }
749 if (!strcmp(f2name, "-")) {
750 f2in = stdin;
751 f2name = stdin_name;
752 } else if (!(f2in = fopen(f2name, "rb"))) {
753 fprintf(stderr, "%s: cannot open for reading\n", f2name);
754 return(2);
755 }
756 /* load headers */
757 if ((typ1 = identify_type(f1name, f1in, &hdr1)) < 0)
758 return(2);
759 if ((typ2 = identify_type(f2name, f2in, &hdr2)) < 0)
760 return(2);
761 if (typ1 != typ2) {
762 if (report != REP_QUIET)
763 printf("%s: '%s' is %s and '%s' is %s\n",
764 progname, f1name, file_type[typ1],
765 f2name, file_type[typ2]);
766 return(1);
767 }
768 ign_header |= !has_header(typ1); /* check headers if indicated */
769 if (!ign_header && !headers_match())
770 return(1);
771 lu_done(&hdr1); lu_done(&hdr2);
772 if (!ign_header & (report >= REP_WARN)) {
773 if (typ1 == TYP_UNKNOWN)
774 printf("%s: warning - unrecognized format, comparing as binary\n",
775 progname);
776 if (lin1cnt != lin2cnt)
777 printf("%s: warning - headers are different lengths\n",
778 progname);
779 }
780 if (report >= REP_VERBOSE)
781 printf("%s: input file type is %s\n",
782 progname, file_type[typ1]);
783
784 switch (typ1) { /* compare based on type */
785 case TYP_BINARY:
786 case TYP_TMESH:
787 case TYP_OCTREE:
788 case TYP_RBFMESH:
789 case TYP_UNKNOWN:
790 return( !compare_binary() );
791 case TYP_TEXT:
792 case TYP_ASCII:
793 return( !compare_text() );
794 case TYP_RGBE:
795 case TYP_XYZE:
796 return( !compare_hdr() );
797 case TYP_FLOAT:
798 return( !compare_float() );
799 case TYP_DOUBLE:
800 return( !compare_double() );
801 }
802 return(1);
803 }