1/* $Id: tiffcmp.c 276 2010-06-30 12:18:30Z nijtmans $ */ 2 3/* 4 * Copyright (c) 1988-1997 Sam Leffler 5 * Copyright (c) 1991-1997 Silicon Graphics, Inc. 6 * 7 * Permission to use, copy, modify, distribute, and sell this software and 8 * its documentation for any purpose is hereby granted without fee, provided 9 * that (i) the above copyright notices and this permission notice appear in 10 * all copies of the software and related documentation, and (ii) the names of 11 * Sam Leffler and Silicon Graphics may not be used in any advertising or 12 * publicity relating to the software without the specific, prior written 13 * permission of Sam Leffler and Silicon Graphics. 14 * 15 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 17 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 18 * 19 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR 20 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, 21 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 22 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 23 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 24 * OF THIS SOFTWARE. 25 */ 26 27#include "tif_config.h" 28 29#include <stdio.h> 30#include <stdlib.h> 31#include <string.h> 32#include <math.h> 33 34#ifdef HAVE_UNISTD_H 35# include <unistd.h> 36#endif 37 38#include "tiffio.h" 39 40#ifndef HAVE_GETOPT 41extern int getopt(int, char**, char*); 42#endif 43 44static int stopondiff = 1; 45static int stoponfirsttag = 1; 46static uint16 bitspersample = 1; 47static uint16 samplesperpixel = 1; 48static uint16 sampleformat = SAMPLEFORMAT_UINT; 49static uint32 imagewidth; 50static uint32 imagelength; 51 52static void usage(void); 53static int tiffcmp(TIFF*, TIFF*); 54static int cmptags(TIFF*, TIFF*); 55static int ContigCompare(int, uint32, unsigned char*, unsigned char*, int); 56static int SeparateCompare(int, int, uint32, unsigned char*, unsigned char*); 57static void PrintIntDiff(uint32, int, uint32, uint32, uint32); 58static void PrintFloatDiff(uint32, int, uint32, double, double); 59 60static void leof(const char*, uint32, int); 61 62int 63main(int argc, char* argv[]) 64{ 65 TIFF *tif1, *tif2; 66 int c, dirnum; 67 extern int optind; 68 extern char* optarg; 69 70 while ((c = getopt(argc, argv, "ltz:")) != -1) 71 switch (c) { 72 case 'l': 73 stopondiff = 0; 74 break; 75 case 'z': 76 stopondiff = atoi(optarg); 77 break; 78 case 't': 79 stoponfirsttag = 0; 80 break; 81 case '?': 82 usage(); 83 /*NOTREACHED*/ 84 } 85 if (argc - optind < 2) 86 usage(); 87 tif1 = TIFFOpen(argv[optind], "r"); 88 if (tif1 == NULL) 89 return (-1); 90 tif2 = TIFFOpen(argv[optind+1], "r"); 91 if (tif2 == NULL) 92 return (-2); 93 dirnum = 0; 94 while (tiffcmp(tif1, tif2)) { 95 if (!TIFFReadDirectory(tif1)) { 96 if (!TIFFReadDirectory(tif2)) 97 break; 98 printf("No more directories for %s\n", 99 TIFFFileName(tif1)); 100 return (1); 101 } else if (!TIFFReadDirectory(tif2)) { 102 printf("No more directories for %s\n", 103 TIFFFileName(tif2)); 104 return (1); 105 } 106 printf("Directory %d:\n", ++dirnum); 107 } 108 109 TIFFClose(tif1); 110 TIFFClose(tif2); 111 return (0); 112} 113 114char* stuff[] = { 115"usage: tiffcmp [options] file1 file2", 116"where options are:", 117" -l list each byte of image data that differs between the files", 118" -z # list specified number of bytes that differs between the files", 119" -t ignore any differences in directory tags", 120NULL 121}; 122 123static void 124usage(void) 125{ 126 char buf[BUFSIZ]; 127 int i; 128 129 setbuf(stderr, buf); 130 fprintf(stderr, "%s\n\n", TIFFGetVersion()); 131 for (i = 0; stuff[i] != NULL; i++) 132 fprintf(stderr, "%s\n", stuff[i]); 133 exit(-1); 134} 135 136#define checkEOF(tif, row, sample) { \ 137 leof(TIFFFileName(tif), row, sample); \ 138 goto bad; \ 139} 140 141static int CheckShortTag(TIFF*, TIFF*, int, char*); 142static int CheckShort2Tag(TIFF*, TIFF*, int, char*); 143static int CheckShortArrayTag(TIFF*, TIFF*, int, char*); 144static int CheckLongTag(TIFF*, TIFF*, int, char*); 145static int CheckFloatTag(TIFF*, TIFF*, int, char*); 146static int CheckStringTag(TIFF*, TIFF*, int, char*); 147 148static int 149tiffcmp(TIFF* tif1, TIFF* tif2) 150{ 151 uint16 config1, config2; 152 tsize_t size1; 153 uint32 row; 154 tsample_t s; 155 unsigned char *buf1, *buf2; 156 157 if (!CheckShortTag(tif1, tif2, TIFFTAG_BITSPERSAMPLE, "BitsPerSample")) 158 return (0); 159 if (!CheckShortTag(tif1, tif2, TIFFTAG_SAMPLESPERPIXEL, "SamplesPerPixel")) 160 return (0); 161 if (!CheckLongTag(tif1, tif2, TIFFTAG_IMAGEWIDTH, "ImageWidth")) 162 return (0); 163 if (!cmptags(tif1, tif2)) 164 return (1); 165 (void) TIFFGetField(tif1, TIFFTAG_BITSPERSAMPLE, &bitspersample); 166 (void) TIFFGetField(tif1, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); 167 (void) TIFFGetField(tif1, TIFFTAG_SAMPLEFORMAT, &sampleformat); 168 (void) TIFFGetField(tif1, TIFFTAG_IMAGEWIDTH, &imagewidth); 169 (void) TIFFGetField(tif1, TIFFTAG_IMAGELENGTH, &imagelength); 170 (void) TIFFGetField(tif1, TIFFTAG_PLANARCONFIG, &config1); 171 (void) TIFFGetField(tif2, TIFFTAG_PLANARCONFIG, &config2); 172 buf1 = (unsigned char *)_TIFFmalloc(size1 = TIFFScanlineSize(tif1)); 173 buf2 = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(tif2)); 174 if (buf1 == NULL || buf2 == NULL) { 175 fprintf(stderr, "No space for scanline buffers\n"); 176 exit(-1); 177 } 178 if (config1 != config2 && bitspersample != 8 && samplesperpixel > 1) { 179 fprintf(stderr, 180"Can't handle different planar configuration w/ different bits/sample\n"); 181 goto bad; 182 } 183#define pack(a,b) ((a)<<8)|(b) 184 switch (pack(config1, config2)) { 185 case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG): 186 for (row = 0; row < imagelength; row++) { 187 if (TIFFReadScanline(tif2, buf2, row, 0) < 0) 188 checkEOF(tif2, row, -1) 189 for (s = 0; s < samplesperpixel; s++) { 190 if (TIFFReadScanline(tif1, buf1, row, s) < 0) 191 checkEOF(tif1, row, s) 192 if (SeparateCompare(1, s, row, buf2, buf1) < 0) 193 goto bad1; 194 } 195 } 196 break; 197 case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_SEPARATE): 198 for (row = 0; row < imagelength; row++) { 199 if (TIFFReadScanline(tif1, buf1, row, 0) < 0) 200 checkEOF(tif1, row, -1) 201 for (s = 0; s < samplesperpixel; s++) { 202 if (TIFFReadScanline(tif2, buf2, row, s) < 0) 203 checkEOF(tif2, row, s) 204 if (SeparateCompare(0, s, row, buf1, buf2) < 0) 205 goto bad1; 206 } 207 } 208 break; 209 case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE): 210 for (s = 0; s < samplesperpixel; s++) 211 for (row = 0; row < imagelength; row++) { 212 if (TIFFReadScanline(tif1, buf1, row, s) < 0) 213 checkEOF(tif1, row, s) 214 if (TIFFReadScanline(tif2, buf2, row, s) < 0) 215 checkEOF(tif2, row, s) 216 if (ContigCompare(s, row, buf1, buf2, size1) < 0) 217 goto bad1; 218 } 219 break; 220 case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_CONTIG): 221 for (row = 0; row < imagelength; row++) { 222 if (TIFFReadScanline(tif1, buf1, row, 0) < 0) 223 checkEOF(tif1, row, -1) 224 if (TIFFReadScanline(tif2, buf2, row, 0) < 0) 225 checkEOF(tif2, row, -1) 226 if (ContigCompare(-1, row, buf1, buf2, size1) < 0) 227 goto bad1; 228 } 229 break; 230 } 231 if (buf1) _TIFFfree(buf1); 232 if (buf2) _TIFFfree(buf2); 233 return (1); 234bad: 235 if (stopondiff) 236 exit(1); 237bad1: 238 if (buf1) _TIFFfree(buf1); 239 if (buf2) _TIFFfree(buf2); 240 return (0); 241} 242 243#define CmpShortField(tag, name) \ 244 if (!CheckShortTag(tif1, tif2, tag, name) && stoponfirsttag) return (0) 245#define CmpShortField2(tag, name) \ 246 if (!CheckShort2Tag(tif1, tif2, tag, name) && stoponfirsttag) return (0) 247#define CmpLongField(tag, name) \ 248 if (!CheckLongTag(tif1, tif2, tag, name) && stoponfirsttag) return (0) 249#define CmpFloatField(tag, name) \ 250 if (!CheckFloatTag(tif1, tif2, tag, name) && stoponfirsttag) return (0) 251#define CmpStringField(tag, name) \ 252 if (!CheckStringTag(tif1, tif2, tag, name) && stoponfirsttag) return (0) 253#define CmpShortArrayField(tag, name) \ 254 if (!CheckShortArrayTag(tif1, tif2, tag, name) && stoponfirsttag) return (0) 255 256static int 257cmptags(TIFF* tif1, TIFF* tif2) 258{ 259 CmpLongField(TIFFTAG_SUBFILETYPE, "SubFileType"); 260 CmpLongField(TIFFTAG_IMAGEWIDTH, "ImageWidth"); 261 CmpLongField(TIFFTAG_IMAGELENGTH, "ImageLength"); 262 CmpShortField(TIFFTAG_BITSPERSAMPLE, "BitsPerSample"); 263 CmpShortField(TIFFTAG_COMPRESSION, "Compression"); 264 CmpShortField(TIFFTAG_PREDICTOR, "Predictor"); 265 CmpShortField(TIFFTAG_PHOTOMETRIC, "PhotometricInterpretation"); 266 CmpShortField(TIFFTAG_THRESHHOLDING, "Thresholding"); 267 CmpShortField(TIFFTAG_FILLORDER, "FillOrder"); 268 CmpShortField(TIFFTAG_ORIENTATION, "Orientation"); 269 CmpShortField(TIFFTAG_SAMPLESPERPIXEL, "SamplesPerPixel"); 270 CmpShortField(TIFFTAG_MINSAMPLEVALUE, "MinSampleValue"); 271 CmpShortField(TIFFTAG_MAXSAMPLEVALUE, "MaxSampleValue"); 272 CmpShortField(TIFFTAG_SAMPLEFORMAT, "SampleFormat"); 273 CmpFloatField(TIFFTAG_XRESOLUTION, "XResolution"); 274 CmpFloatField(TIFFTAG_YRESOLUTION, "YResolution"); 275 CmpLongField(TIFFTAG_GROUP3OPTIONS, "Group3Options"); 276 CmpLongField(TIFFTAG_GROUP4OPTIONS, "Group4Options"); 277 CmpShortField(TIFFTAG_RESOLUTIONUNIT, "ResolutionUnit"); 278 CmpShortField(TIFFTAG_PLANARCONFIG, "PlanarConfiguration"); 279 CmpLongField(TIFFTAG_ROWSPERSTRIP, "RowsPerStrip"); 280 CmpFloatField(TIFFTAG_XPOSITION, "XPosition"); 281 CmpFloatField(TIFFTAG_YPOSITION, "YPosition"); 282 CmpShortField(TIFFTAG_GRAYRESPONSEUNIT, "GrayResponseUnit"); 283 CmpShortField(TIFFTAG_COLORRESPONSEUNIT, "ColorResponseUnit"); 284#ifdef notdef 285 { uint16 *graycurve; 286 CmpField(TIFFTAG_GRAYRESPONSECURVE, graycurve); 287 } 288 { uint16 *red, *green, *blue; 289 CmpField3(TIFFTAG_COLORRESPONSECURVE, red, green, blue); 290 } 291 { uint16 *red, *green, *blue; 292 CmpField3(TIFFTAG_COLORMAP, red, green, blue); 293 } 294#endif 295 CmpShortField2(TIFFTAG_PAGENUMBER, "PageNumber"); 296 CmpStringField(TIFFTAG_ARTIST, "Artist"); 297 CmpStringField(TIFFTAG_IMAGEDESCRIPTION,"ImageDescription"); 298 CmpStringField(TIFFTAG_MAKE, "Make"); 299 CmpStringField(TIFFTAG_MODEL, "Model"); 300 CmpStringField(TIFFTAG_SOFTWARE, "Software"); 301 CmpStringField(TIFFTAG_DATETIME, "DateTime"); 302 CmpStringField(TIFFTAG_HOSTCOMPUTER, "HostComputer"); 303 CmpStringField(TIFFTAG_PAGENAME, "PageName"); 304 CmpStringField(TIFFTAG_DOCUMENTNAME, "DocumentName"); 305 CmpShortField(TIFFTAG_MATTEING, "Matteing"); 306 CmpShortArrayField(TIFFTAG_EXTRASAMPLES,"ExtraSamples"); 307 return (1); 308} 309 310static int 311ContigCompare(int sample, uint32 row, 312 unsigned char* p1, unsigned char* p2, int size) 313{ 314 uint32 pix; 315 int ppb = 8 / bitspersample; 316 int samples_to_test; 317 318 if (memcmp(p1, p2, size) == 0) 319 return 0; 320 321 samples_to_test = (sample == -1) ? samplesperpixel : 1; 322 323 switch (bitspersample) { 324 case 1: case 2: case 4: case 8: 325 { 326 unsigned char *pix1 = p1, *pix2 = p2; 327 328 for (pix = 0; pix < imagewidth; pix += ppb) { 329 int s; 330 331 for(s = 0; s < samples_to_test; s++) { 332 if (*pix1 != *pix2) { 333 if( sample == -1 ) 334 PrintIntDiff(row, s, pix, *pix1, *pix2); 335 else 336 PrintIntDiff(row, sample, pix, *pix1, *pix2); 337 } 338 339 pix1++; 340 pix2++; 341 } 342 } 343 break; 344 } 345 case 16: 346 { 347 uint16 *pix1 = (uint16 *)p1, *pix2 = (uint16 *)p2; 348 349 for (pix = 0; pix < imagewidth; pix++) { 350 int s; 351 352 for(s = 0; s < samples_to_test; s++) { 353 if (*pix1 != *pix2) 354 PrintIntDiff(row, sample, pix, *pix1, *pix2); 355 356 pix1++; 357 pix2++; 358 } 359 } 360 break; 361 } 362 case 32: 363 if (sampleformat == SAMPLEFORMAT_UINT 364 || sampleformat == SAMPLEFORMAT_INT) { 365 uint32 *pix1 = (uint32 *)p1, *pix2 = (uint32 *)p2; 366 367 for (pix = 0; pix < imagewidth; pix++) { 368 int s; 369 370 for(s = 0; s < samples_to_test; s++) { 371 if (*pix1 != *pix2) { 372 PrintIntDiff(row, sample, pix, 373 *pix1, *pix2); 374 } 375 376 pix1++; 377 pix2++; 378 } 379 } 380 } else if (sampleformat == SAMPLEFORMAT_IEEEFP) { 381 float *pix1 = (float *)p1, *pix2 = (float *)p2; 382 383 for (pix = 0; pix < imagewidth; pix++) { 384 int s; 385 386 for(s = 0; s < samples_to_test; s++) { 387 if (fabs(*pix1 - *pix2) < 0.000000000001) { 388 PrintFloatDiff(row, sample, pix, 389 *pix1, *pix2); 390 } 391 392 pix1++; 393 pix2++; 394 } 395 } 396 } else { 397 fprintf(stderr, "Sample format %d is not supported.\n", 398 sampleformat); 399 return -1; 400 } 401 break; 402 default: 403 fprintf(stderr, "Bit depth %d is not supported.\n", bitspersample); 404 return -1; 405 } 406 407 return 0; 408} 409 410static void 411PrintIntDiff(uint32 row, int sample, uint32 pix, uint32 w1, uint32 w2) 412{ 413 if (sample < 0) 414 sample = 0; 415 switch (bitspersample) { 416 case 1: 417 case 2: 418 case 4: 419 { 420 int32 mask1, mask2, s; 421 422 mask1 = ~((-1) << bitspersample); 423 s = (8 - bitspersample); 424 mask2 = mask1 << s; 425 for (; mask2 && pix < imagewidth; 426 mask2 >>= bitspersample, s -= bitspersample, pix++) { 427 if ((w1 & mask2) ^ (w2 & mask2)) { 428 printf( 429 "Scanline %lu, pixel %lu, sample %d: %01x %01x\n", 430 (unsigned long) row, 431 (unsigned long) pix, 432 sample, 433 (unsigned int)((w1 >> s) & mask1), 434 (unsigned int)((w2 >> s) & mask1)); 435 if (--stopondiff == 0) 436 exit(1); 437 } 438 } 439 break; 440 } 441 case 8: 442 printf("Scanline %lu, pixel %lu, sample %d: %02x %02x\n", 443 (unsigned long) row, (unsigned long) pix, sample, 444 (unsigned int) w1, (unsigned int) w2); 445 if (--stopondiff == 0) 446 exit(1); 447 break; 448 case 16: 449 printf("Scanline %lu, pixel %lu, sample %d: %04x %04x\n", 450 (unsigned long) row, (unsigned long) pix, sample, 451 (unsigned int) w1, (unsigned int) w2); 452 if (--stopondiff == 0) 453 exit(1); 454 break; 455 case 32: 456 printf("Scanline %lu, pixel %lu, sample %d: %08x %08x\n", 457 (unsigned long) row, (unsigned long) pix, sample, 458 (unsigned int) w1, (unsigned int) w2); 459 if (--stopondiff == 0) 460 exit(1); 461 break; 462 default: 463 break; 464 } 465} 466 467static void 468PrintFloatDiff(uint32 row, int sample, uint32 pix, double w1, double w2) 469{ 470 if (sample < 0) 471 sample = 0; 472 switch (bitspersample) { 473 case 32: 474 printf("Scanline %lu, pixel %lu, sample %d: %g %g\n", 475 (long) row, (long) pix, sample, w1, w2); 476 if (--stopondiff == 0) 477 exit(1); 478 break; 479 default: 480 break; 481 } 482} 483 484static int 485SeparateCompare(int reversed, int sample, uint32 row, 486 unsigned char* cp1, unsigned char* p2) 487{ 488 uint32 npixels = imagewidth; 489 int pixel; 490 491 cp1 += sample; 492 for (pixel = 0; npixels-- > 0; pixel++, cp1 += samplesperpixel, p2++) { 493 if (*cp1 != *p2) { 494 printf("Scanline %lu, pixel %lu, sample %ld: ", 495 (long) row, (long) pixel, (long) sample); 496 if (reversed) 497 printf("%02x %02x\n", *p2, *cp1); 498 else 499 printf("%02x %02x\n", *cp1, *p2); 500 if (--stopondiff == 0) 501 exit(1); 502 } 503 } 504 505 return 0; 506} 507 508static int 509checkTag(TIFF* tif1, TIFF* tif2, int tag, char* name, void* p1, void* p2) 510{ 511 512 if (TIFFGetField(tif1, tag, p1)) { 513 if (!TIFFGetField(tif2, tag, p2)) { 514 printf("%s tag appears only in %s\n", 515 name, TIFFFileName(tif1)); 516 return (0); 517 } 518 return (1); 519 } else if (TIFFGetField(tif2, tag, p2)) { 520 printf("%s tag appears only in %s\n", name, TIFFFileName(tif2)); 521 return (0); 522 } 523 return (-1); 524} 525 526#define CHECK(cmp, fmt) { \ 527 switch (checkTag(tif1,tif2,tag,name,&v1,&v2)) { \ 528 case 1: if (cmp) \ 529 case -1: return (1); \ 530 printf(fmt, name, v1, v2); \ 531 } \ 532 return (0); \ 533} 534 535static int 536CheckShortTag(TIFF* tif1, TIFF* tif2, int tag, char* name) 537{ 538 uint16 v1, v2; 539 CHECK(v1 == v2, "%s: %u %u\n"); 540} 541 542static int 543CheckShort2Tag(TIFF* tif1, TIFF* tif2, int tag, char* name) 544{ 545 uint16 v11, v12, v21, v22; 546 547 if (TIFFGetField(tif1, tag, &v11, &v12)) { 548 if (!TIFFGetField(tif2, tag, &v21, &v22)) { 549 printf("%s tag appears only in %s\n", 550 name, TIFFFileName(tif1)); 551 return (0); 552 } 553 if (v11 == v21 && v12 == v22) 554 return (1); 555 printf("%s: <%u,%u> <%u,%u>\n", name, v11, v12, v21, v22); 556 } else if (TIFFGetField(tif2, tag, &v21, &v22)) 557 printf("%s tag appears only in %s\n", name, TIFFFileName(tif2)); 558 else 559 return (1); 560 return (0); 561} 562 563static int 564CheckShortArrayTag(TIFF* tif1, TIFF* tif2, int tag, char* name) 565{ 566 uint16 n1, *a1; 567 uint16 n2, *a2; 568 569 if (TIFFGetField(tif1, tag, &n1, &a1)) { 570 if (!TIFFGetField(tif2, tag, &n2, &a2)) { 571 printf("%s tag appears only in %s\n", 572 name, TIFFFileName(tif1)); 573 return (0); 574 } 575 if (n1 == n2) { 576 char* sep; 577 uint16 i; 578 579 if (memcmp(a1, a2, n1 * sizeof(uint16)) == 0) 580 return (1); 581 printf("%s: value mismatch, <%u:", name, n1); 582 sep = ""; 583 for (i = 0; i < n1; i++) 584 printf("%s%u", sep, a1[i]), sep = ","; 585 printf("> and <%u: ", n2); 586 sep = ""; 587 for (i = 0; i < n2; i++) 588 printf("%s%u", sep, a2[i]), sep = ","; 589 printf(">\n"); 590 } else 591 printf("%s: %u items in %s, %u items in %s", name, 592 n1, TIFFFileName(tif1), 593 n2, TIFFFileName(tif2) 594 ); 595 } else if (TIFFGetField(tif2, tag, &n2, &a2)) 596 printf("%s tag appears only in %s\n", name, TIFFFileName(tif2)); 597 else 598 return (1); 599 return (0); 600} 601 602static int 603CheckLongTag(TIFF* tif1, TIFF* tif2, int tag, char* name) 604{ 605 uint32 v1, v2; 606 CHECK(v1 == v2, "%s: %u %u\n"); 607} 608 609static int 610CheckFloatTag(TIFF* tif1, TIFF* tif2, int tag, char* name) 611{ 612 float v1, v2; 613 CHECK(v1 == v2, "%s: %g %g\n"); 614} 615 616static int 617CheckStringTag(TIFF* tif1, TIFF* tif2, int tag, char* name) 618{ 619 char *v1, *v2; 620 CHECK(strcmp(v1, v2) == 0, "%s: \"%s\" \"%s\"\n"); 621} 622 623static void 624leof(const char* name, uint32 row, int s) 625{ 626 627 printf("%s: EOF at scanline %lu", name, (unsigned long)row); 628 if (s >= 0) 629 printf(", sample %d", s); 630 printf("\n"); 631} 632 633/* vim: set ts=8 sts=8 sw=8 noet: */ 634/* 635 * Local Variables: 636 * mode: c 637 * c-basic-offset: 8 638 * fill-column: 78 639 * End: 640 */ 641