all repos — mgba @ 9de8f084ba55460b02d300c1dd8b8e6c56f691d5

mGBA Game Boy Advance Emulator

src/third-party/libpng/contrib/tools/pngcp.c (view raw)

   1/* pngcp.c
   2 *
   3 * Copyright (c) 2016 John Cunningham Bowler
   4 *
   5 * Last changed in libpng 1.6.24 [August 4, 2016]
   6 *
   7 * This code is released under the libpng license.
   8 * For conditions of distribution and use, see the disclaimer
   9 * and license in png.h
  10 *
  11 * This is an example of copying a PNG without changes using the png_read_png
  12 * and png_write_png interfaces.  A considerable number of options are provided
  13 * to manipulate the compression of the PNG data and other compressed chunks.
  14 *
  15 * For a more extensive example that uses the transforms see
  16 * contrib/libtests/pngimage.c in the libpng distribution.
  17 */
  18#include "pnglibconf.h" /* To find how libpng was configured. */
  19
  20#ifdef PNG_PNGCP_TIMING_SUPPORTED
  21   /* WARNING:
  22    *
  23    * This test is here to allow POSIX.1b extensions to be used if enabled in
  24    * the compile; specifically the code requires_POSIX_C_SOURCE support of
  25    * 199309L or later to enable clock_gettime use.
  26    *
  27    * IF this causes problems THEN compile with a strict ANSI C compiler and let
  28    * this code turn on the POSIX features that it minimally requires.
  29    *
  30    * IF this does not work there is probably a bug in your ANSI C compiler or
  31    * your POSIX implementation.
  32    */
  33#  define _POSIX_C_SOURCE 199309L
  34#else /* No timing support required */
  35#  define _POSIX_SOURCE 1
  36#endif
  37
  38#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H)
  39#  include <config.h>
  40#endif
  41
  42#include <stdio.h>
  43
  44/* Define the following to use this test against your installed libpng, rather
  45 * than the one being built here:
  46 */
  47#ifdef PNG_FREESTANDING_TESTS
  48#  include <png.h>
  49#else
  50#  include "../../png.h"
  51#endif
  52
  53#if PNG_LIBPNG_VER < 10700
  54   /* READ_PNG and WRITE_PNG were not defined, so: */
  55#  ifdef PNG_INFO_IMAGE_SUPPORTED
  56#     ifdef PNG_SEQUENTIAL_READ_SUPPORTED
  57#        define PNG_READ_PNG_SUPPORTED
  58#     endif /* SEQUENTIAL_READ */
  59#     ifdef PNG_WRITE_SUPPORTED
  60#        define PNG_WRITE_PNG_SUPPORTED
  61#     endif /* WRITE */
  62#  endif /* INFO_IMAGE */
  63#endif /* pre 1.7.0 */
  64
  65#if (defined(PNG_READ_PNG_SUPPORTED)) && (defined(PNG_WRITE_PNG_SUPPORTED))
  66#include <stdarg.h>
  67#include <stdlib.h>
  68#include <string.h>
  69#include <errno.h>
  70#include <limits.h>
  71#include <assert.h>
  72
  73#include <unistd.h>
  74#include <sys/stat.h>
  75
  76#include <zlib.h>
  77
  78#ifndef PNG_SETJMP_SUPPORTED
  79#  include <setjmp.h> /* because png.h did *not* include this */
  80#endif
  81
  82#ifdef __cplusplus
  83#  define voidcast(type, value) static_cast<type>(value)
  84#else
  85#  define voidcast(type, value) (value)
  86#endif /* __cplusplus */
  87
  88#ifdef __GNUC__
  89   /* Many versions of GCC erroneously report that local variables unmodified
  90    * within the scope of a setjmp may be clobbered.  This hacks round the
  91    * problem (sometimes) without harming other compilers.
  92    */
  93#  define gv volatile
  94#else
  95#  define gv
  96#endif
  97
  98/* 'CLOCK_PROCESS_CPUTIME_ID' is one of the clock timers for clock_gettime.  It
  99 * need not be supported even when clock_gettime is available.  It returns the
 100 * 'CPU' time the process has consumed.  'CPU' time is assumed to include time
 101 * when the CPU is actually blocked by a pending cache fill but not time
 102 * waiting for page faults.  The attempt is to get a measure of the actual time
 103 * the implementation takes to read a PNG ignoring the potentially very large IO
 104 * overhead.
 105 */
 106#ifdef PNG_PNGCP_TIMING_SUPPORTED
 107#  include <time.h>   /* clock_gettime and associated definitions */
 108#  ifndef CLOCK_PROCESS_CPUTIME_ID
 109      /* Prevent inclusion of the spurious code: */
 110#     undef PNG_PNGCP_TIMING_SUPPORTED
 111#  endif
 112#endif /* PNGCP_TIMING */
 113
 114/* So if the timing feature has been activated: */
 115
 116/* This structure is used to control the test of a single file. */
 117typedef enum
 118{
 119   VERBOSE,        /* switches on all messages */
 120   INFORMATION,
 121   WARNINGS,       /* switches on warnings */
 122   LIBPNG_WARNING,
 123   APP_WARNING,
 124   ERRORS,         /* just errors */
 125   APP_FAIL,       /* continuable error - no need to longjmp */
 126   LIBPNG_ERROR,   /* this and higher cause a longjmp */
 127   LIBPNG_BUG,     /* erroneous behavior in libpng */
 128   APP_ERROR,      /* such as out-of-memory in a callback */
 129   QUIET,          /* no normal messages */
 130   USER_ERROR,     /* such as file-not-found */
 131   INTERNAL_ERROR
 132} error_level;
 133#define LEVEL_MASK      0xf   /* where the level is in 'options' */
 134
 135#define STRICT          0x010 /* Fail on warnings as well as errors */
 136#define LOG             0x020 /* Log pass/fail to stdout */
 137#define CONTINUE        0x040 /* Continue on APP_FAIL errors */
 138#define SIZES           0x080 /* Report input and output sizes */
 139#define SEARCH          0x100 /* Search IDAT compression options */
 140#define NOWRITE         0x200 /* Do not write an output file */
 141#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
 142#  define IGNORE_INDEX  0x400 /* Ignore out of range palette indices (BAD!) */
 143#  ifdef PNG_GET_PALETTE_MAX_SUPPORTED
 144#     define FIX_INDEX  0x800 /* 'Fix' out of range palette indices (OK) */
 145#  endif /* GET_PALETTE_MAX */
 146#endif /* CHECK_FOR_INVALID_INDEX */
 147#define OPTION     0x80000000 /* Used for handling options */
 148#define LIST       0x80000001 /* Used for handling options */
 149
 150/* Result masks apply to the result bits in the 'results' field below; these
 151 * bits are simple 1U<<error_level.  A pass requires either nothing worse than
 152 * warnings (--relaxes) or nothing worse than information (--strict)
 153 */
 154#define RESULT_STRICT(r)   (((r) & ~((1U<<WARNINGS)-1)) == 0)
 155#define RESULT_RELAXED(r)  (((r) & ~((1U<<ERRORS)-1)) == 0)
 156
 157/* OPTION DEFINITIONS */
 158static const char range_lo[] = "low";
 159static const char range_hi[] = "high";
 160static const char all[] = "all";
 161#define RANGE(lo,hi) { range_lo, lo }, { range_hi, hi }
 162typedef struct value_list
 163{
 164   const char *name;  /* the command line name of the value */
 165   int         value; /* the actual value to use */
 166}  value_list;
 167
 168static const value_list
 169#ifdef PNG_SW_COMPRESS_png_level
 170vl_compression[] =
 171{
 172   /* Overall compression control.  The order controls the search order for
 173    * 'all'.  Since the search is for the smallest the order used is low memory
 174    * then high speed.
 175    */
 176   { "low-memory",      PNG_COMPRESSION_LOW_MEMORY },
 177   { "high-speed",      PNG_COMPRESSION_HIGH_SPEED },
 178   { "high-read-speed", PNG_COMPRESSION_HIGH_READ_SPEED },
 179   { "low",             PNG_COMPRESSION_LOW },
 180   { "medium",          PNG_COMPRESSION_MEDIUM },
 181   { "old",             PNG_COMPRESSION_COMPAT },
 182   { "high",            PNG_COMPRESSION_HIGH },
 183   { all, 0 }
 184},
 185#endif /* SW_COMPRESS_png_level */
 186
 187#if defined(PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED) ||\
 188    defined(PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED)
 189vl_strategy[] =
 190{
 191   /* This controls the order of search. */
 192   { "huffman", Z_HUFFMAN_ONLY },
 193   { "RLE", Z_RLE },
 194   { "fixed", Z_FIXED }, /* the remainder do window searchs */
 195   { "filtered", Z_FILTERED },
 196   { "default", Z_DEFAULT_STRATEGY },
 197   { all, 0 }
 198},
 199#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
 200vl_windowBits_text[] =
 201{
 202   { "default", MAX_WBITS/*from zlib*/ },
 203   { "minimum", 8 },
 204   RANGE(8, MAX_WBITS/*from zlib*/),
 205   { all, 0 }
 206},
 207#endif /* text compression */
 208vl_level[] =
 209{
 210   { "default", Z_DEFAULT_COMPRESSION /* this is -1 */ },
 211   { "none", Z_NO_COMPRESSION },
 212   { "speed", Z_BEST_SPEED },
 213   { "best", Z_BEST_COMPRESSION },
 214   { "0", Z_NO_COMPRESSION },
 215   RANGE(1, 9), /* this deliberately excludes '0' */
 216   { all, 0 }
 217},
 218vl_memLevel[] =
 219{
 220   { "max", MAX_MEM_LEVEL }, /* zlib maximum */
 221   { "1", 1 }, /* zlib minimum */
 222   { "default", 8 }, /* zlib default */
 223   { "2", 2 },
 224   { "3", 3 },
 225   { "4", 4 },
 226   { "5", 5 }, /* for explicit testing */
 227   RANGE(6, MAX_MEM_LEVEL/*zlib*/), /* exclude 5 and below: zlib bugs */
 228   { all, 0 }
 229},
 230#endif /* WRITE_CUSTOMIZE_*COMPRESSION */
 231#ifdef PNG_WRITE_FILTER_SUPPORTED
 232vl_filter[] =
 233{
 234   { all,      PNG_ALL_FILTERS   },
 235   { "off",    PNG_NO_FILTERS    },
 236   { "none",   PNG_FILTER_NONE   },
 237   { "sub",    PNG_FILTER_SUB    },
 238   { "up",     PNG_FILTER_UP     },
 239   { "avg",    PNG_FILTER_AVG    },
 240   { "paeth",  PNG_FILTER_PAETH  }
 241},
 242#endif /* WRITE_FILTER */
 243#ifdef PNG_PNGCP_TIMING_SUPPORTED
 244#  define PNGCP_TIME_READ  1
 245#  define PNGCP_TIME_WRITE 2
 246vl_time[] =
 247{
 248   { "both",  PNGCP_TIME_READ+PNGCP_TIME_WRITE },
 249   { "off",   0 },
 250   { "read",  PNGCP_TIME_READ },
 251   { "write", PNGCP_TIME_WRITE }
 252},
 253#endif /* PNGCP_TIMING */
 254vl_IDAT_size[] = /* for png_set_IDAT_size */
 255{
 256   { "default", 0x7FFFFFFF },
 257   { "minimal", 1 },
 258   RANGE(1, 0x7FFFFFFF)
 259},
 260#ifndef PNG_SW_IDAT_size
 261   /* Pre 1.7 API: */
 262#  define png_set_IDAT_size(p,v) png_set_compression_buffer_size(p, v)
 263#endif /* !SW_IDAT_size */
 264#define SL 8 /* stack limit in display, below */
 265vl_log_depth[] = { { "on", 1 }, { "off", 0 }, RANGE(0, SL) },
 266vl_on_off[] = { { "on", 1 }, { "off", 0 } };
 267
 268#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
 269static value_list
 270vl_windowBits_IDAT[] =
 271{
 272   { "default", MAX_WBITS },
 273   { "small", 9 },
 274   RANGE(8, MAX_WBITS), /* modified by set_windowBits_hi */
 275   { all, 0 }
 276};
 277#endif /* IDAT compression */
 278
 279typedef struct option
 280{
 281   const char       *name;         /* name of the option */
 282   png_uint_32       opt;          /* an option, or OPTION or LIST */
 283   png_byte          search;       /* Search on --search */
 284   png_byte          value_count;  /* length of the list of values: */
 285   const value_list *values;       /* values for OPTION or LIST */
 286}  option;
 287
 288static const option options[] =
 289{
 290   /* struct display options, these are set when the command line is read */
 291#  define S(n,v) { #n, v, 0, 2, vl_on_off },
 292   S(verbose,  VERBOSE)
 293   S(warnings, WARNINGS)
 294   S(errors,   ERRORS)
 295   S(quiet,    QUIET)
 296   S(strict,   STRICT)
 297   S(log,      LOG)
 298   S(continue, CONTINUE)
 299   S(sizes,    SIZES)
 300   S(search,   SEARCH)
 301   S(nowrite,  NOWRITE)
 302#  ifdef IGNORE_INDEX
 303      S(ignore-palette-index, IGNORE_INDEX)
 304#  endif /* IGNORE_INDEX */
 305#  ifdef FIX_INDEX
 306      S(fix-palette-index, FIX_INDEX)
 307#  endif /* FIX_INDEX */
 308#  undef S
 309
 310   /* OPTION settings, these and LIST settings are read on demand */
 311#  define VLNAME(name) vl_ ## name
 312#  define VLSIZE(name) voidcast(png_byte,\
 313                           (sizeof VLNAME(name))/(sizeof VLNAME(name)[0]))
 314#  define VL(oname, name, type, search)\
 315   { oname, type, search, VLSIZE(name), VLNAME(name) },
 316#  define VLO(oname, name, search) VL(oname, name, OPTION, search)
 317
 318#  ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
 319#     define VLCIDAT(name) VLO(#name, name, 1/*search*/)
 320#     ifdef PNG_SW_COMPRESS_level
 321#        define VLCiCCP(name) VLO("ICC-profile-" #name, name, 0/*search*/)
 322#     else
 323#        define VLCiCCP(name)
 324#     endif
 325#  else
 326#     define VLCIDAT(name)
 327#     define VLCiCCP(name)
 328#  endif /* WRITE_CUSTOMIZE_COMPRESSION */
 329
 330#  ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
 331#     define VLCzTXt(name) VLO("text-" #name, name, 0/*search*/)
 332#  else
 333#     define VLCzTXt(name)
 334#  endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */
 335
 336#  define VLC(name) VLCIDAT(name) VLCiCCP(name) VLCzTXt(name)
 337
 338#  ifdef PNG_SW_COMPRESS_png_level
 339      /* The libpng compression level isn't searched beause it justs sets the
 340       * other things that are searched!
 341       */
 342      VLO("compression", compression, 0)
 343      VLO("text-compression", compression, 0)
 344      VLO("ICC-profile-compression", compression, 0)
 345#  endif /* SW_COMPRESS_png_level */
 346   VLC(strategy)
 347   VLO("windowBits", windowBits_IDAT, 1)
 348#  ifdef PNG_SW_COMPRESS_windowBits
 349      VLO("ICC-profile-windowBits", windowBits_text/*sic*/, 0)
 350#  endif
 351   VLO("text-windowBits", windowBits_text, 0)
 352   VLC(level)
 353   VLC(memLevel)
 354   VLO("IDAT-size", IDAT_size, 0)
 355   VLO("log-depth", log_depth, 0)
 356
 357#  undef VLO
 358
 359   /* LIST settings */
 360#  define VLL(name, search) VL(#name, name, LIST, search)
 361#ifdef PNG_WRITE_FILTER_SUPPORTED
 362   VLL(filter, 0)
 363#endif /* WRITE_FILTER */
 364#ifdef PNG_PNGCP_TIMING_SUPPORTED
 365   VLL(time, 0)
 366#endif /* PNGCP_TIMING */
 367#  undef VLL
 368#  undef VL
 369};
 370
 371#ifdef __cplusplus
 372   static const size_t option_count((sizeof options)/(sizeof options[0]));
 373#else /* !__cplusplus */
 374#  define option_count ((sizeof options)/(sizeof options[0]))
 375#endif /* !__cplusplus */
 376
 377static const char *
 378cts(int ct)
 379{
 380   switch (ct)
 381   {
 382      case PNG_COLOR_TYPE_PALETTE:     return "P";
 383      case PNG_COLOR_TYPE_GRAY:        return "G";
 384      case PNG_COLOR_TYPE_GRAY_ALPHA:  return "GA";
 385      case PNG_COLOR_TYPE_RGB:         return "RGB";
 386      case PNG_COLOR_TYPE_RGB_ALPHA:   return "RGBA";
 387      default:                         return "INVALID";
 388   }
 389}
 390
 391struct display
 392{
 393   jmp_buf          error_return;      /* Where to go to on error */
 394   unsigned int     errset;            /* error_return is set */
 395
 396   const char      *operation;         /* What is happening */
 397   const char      *filename;          /* The name of the original file */
 398   const char      *output_file;       /* The name of the output file */
 399
 400   /* Used on both read and write: */
 401   FILE            *fp;
 402
 403   /* Used on a read, both the original read and when validating a written
 404    * image.
 405    */
 406   png_alloc_size_t read_size;
 407   png_structp      read_pp;
 408   png_infop        ip;
 409#  if PNG_LIBPNG_VER < 10700 && defined PNG_TEXT_SUPPORTED
 410      png_textp     text_ptr; /* stash of text chunks */
 411      int           num_text;
 412      int           text_stashed;
 413#  endif /* pre 1.7 */
 414
 415#  ifdef PNG_PNGCP_TIMING_SUPPORTED
 416      struct timespec   read_time;
 417      struct timespec   read_time_total;
 418      struct timespec   write_time;
 419      struct timespec   write_time_total;
 420#  endif /* PNGCP_TIMING */
 421
 422   /* Used to write a new image (the original info_ptr is used) */
 423#  define MAX_SIZE ((png_alloc_size_t)(-1))
 424   png_alloc_size_t write_size;
 425   png_alloc_size_t best_size;
 426   png_structp      write_pp;
 427
 428   /* Base file information */
 429   png_alloc_size_t size;
 430   png_uint_32      w;
 431   png_uint_32      h;
 432   int              bpp;
 433   png_byte         ct;
 434   int              no_warnings;       /* Do not output libpng warnings */
 435   int              min_windowBits;    /* The windowBits range is 8..8 */
 436
 437   /* Options handling */
 438   png_uint_32      results;             /* A mask of errors seen */
 439   png_uint_32      options;             /* See display_log below */
 440   png_byte         entry[option_count]; /* The selected entry+1 of an option
 441                                          * that appears on the command line, or
 442                                          * 0 if it was not given. */
 443   int              value[option_count]; /* Corresponding value */
 444
 445   /* Compression exhaustive testing */
 446   /* Temporary variables used only while testing a single collection of
 447    * settings:
 448    */
 449   unsigned int     csp;               /* next stack entry to use */
 450   unsigned int     nsp;               /* highest active entry+1 found so far */
 451
 452   /* Values used while iterating through all the combinations of settings for a
 453    * single file:
 454    */
 455   unsigned int     tsp;               /* nsp from the last run; this is the
 456                                        * index+1 of the highest active entry on
 457                                        * this run; this entry will be advanced.
 458                                        */
 459   int              opt_string_start;  /* Position in buffer for the first
 460                                        * searched option; non-zero if earlier
 461                                        * options were set on the command line.
 462                                        */
 463   struct stack
 464   {
 465      png_alloc_size_t best_size;      /* Best so far for this option */
 466      png_alloc_size_t lo_size;
 467      png_alloc_size_t hi_size;
 468      int              lo, hi;         /* For binary chop of a range */
 469      int              best_val;       /* Best value found so far */
 470      int              opt_string_end; /* End of the option string in 'curr' */
 471      png_byte         opt;            /* The option being tested */
 472      png_byte         entry;          /* The next value entry to be tested */
 473      png_byte         end;            /* This is the last entry */
 474   }                stack[SL];         /* Stack of entries being tested */
 475   char             curr[32*SL];       /* current options being tested */
 476   char             best[32*SL];       /* best options */
 477
 478   char             namebuf[FILENAME_MAX]; /* output file name */
 479};
 480
 481static void
 482display_init(struct display *dp)
 483   /* Call this only once right at the start to initialize the control
 484    * structure, the (struct buffer) lists are maintained across calls - the
 485    * memory is not freed.
 486    */
 487{
 488   memset(dp, 0, sizeof *dp);
 489   dp->operation = "internal error";
 490   dp->filename = "command line";
 491   dp->output_file = "no output file";
 492   dp->options = WARNINGS; /* default to !verbose, !quiet */
 493   dp->fp = NULL;
 494   dp->read_pp = NULL;
 495   dp->ip = NULL;
 496   dp->write_pp = NULL;
 497   dp->min_windowBits = -1; /* this is an OPTIND, so -1 won't match anything */
 498#  if PNG_LIBPNG_VER < 10700 && defined PNG_TEXT_SUPPORTED
 499      dp->text_ptr = NULL;
 500      dp->num_text = 0;
 501      dp->text_stashed = 0;
 502#  endif /* pre 1.7 */
 503}
 504
 505static void
 506display_clean_read(struct display *dp)
 507{
 508   if (dp->read_pp != NULL)
 509      png_destroy_read_struct(&dp->read_pp, NULL, NULL);
 510
 511   if (dp->fp != NULL)
 512   {
 513      FILE *fp = dp->fp;
 514      dp->fp = NULL;
 515      (void)fclose(fp);
 516   }
 517}
 518
 519static void
 520display_clean_write(struct display *dp)
 521{
 522   if (dp->fp != NULL)
 523   {
 524      FILE *fp = dp->fp;
 525      dp->fp = NULL;
 526      (void)fclose(fp);
 527   }
 528
 529   if (dp->write_pp != NULL)
 530      png_destroy_write_struct(&dp->write_pp, dp->tsp > 0 ? NULL : &dp->ip);
 531}
 532
 533static void
 534display_clean(struct display *dp)
 535{
 536   display_clean_read(dp);
 537   display_clean_write(dp);
 538   dp->output_file = NULL;
 539
 540#  if PNG_LIBPNG_VER < 10700 && defined PNG_TEXT_SUPPORTED
 541      /* This is actually created and used by the write code, but only
 542       * once; it has to be retained for subsequent writes of the same file.
 543       */
 544      if (dp->text_stashed)
 545      {
 546         dp->text_stashed = 0;
 547         dp->num_text = 0;
 548         free(dp->text_ptr);
 549         dp->text_ptr = NULL;
 550      }
 551#  endif /* pre 1.7 */
 552
 553   /* leave the filename for error detection */
 554   dp->results = 0; /* reset for next time */
 555}
 556
 557static void
 558display_destroy(struct display *dp)
 559{
 560   /* Release any memory held in the display. */
 561   display_clean(dp);
 562}
 563
 564static struct display *
 565get_dp(png_structp pp)
 566   /* The display pointer is always stored in the png_struct error pointer */
 567{
 568   struct display *dp = (struct display*)png_get_error_ptr(pp);
 569
 570   if (dp == NULL)
 571   {
 572      fprintf(stderr, "pngcp: internal error (no display)\n");
 573      exit(99); /* prevents a crash */
 574   }
 575
 576   return dp;
 577}
 578
 579/* error handling */
 580#ifdef __GNUC__
 581#  define VGATTR __attribute__((__format__ (__printf__,3,4)))
 582   /* Required to quiet GNUC warnings when the compiler sees a stdarg function
 583    * that calls one of the stdio v APIs.
 584    */
 585#else
 586#  define VGATTR
 587#endif
 588static void VGATTR
 589display_log(struct display *dp, error_level level, const char *fmt, ...)
 590   /* 'level' is as above, fmt is a stdio style format string.  This routine
 591    * does not return if level is above LIBPNG_WARNING
 592    */
 593{
 594   dp->results |= 1U << level;
 595
 596   if (level > (error_level)(dp->options & LEVEL_MASK))
 597   {
 598      const char *lp;
 599      va_list ap;
 600
 601      switch (level)
 602      {
 603         case INFORMATION:    lp = "information"; break;
 604         case LIBPNG_WARNING: lp = "warning(libpng)"; break;
 605         case APP_WARNING:    lp = "warning(pngcp)"; break;
 606         case APP_FAIL:       lp = "error(continuable)"; break;
 607         case LIBPNG_ERROR:   lp = "error(libpng)"; break;
 608         case LIBPNG_BUG:     lp = "bug(libpng)"; break;
 609         case APP_ERROR:      lp = "error(pngcp)"; break;
 610         case USER_ERROR:     lp = "error(user)"; break;
 611
 612         case INTERNAL_ERROR: /* anything unexpected is an internal error: */
 613         case VERBOSE: case WARNINGS: case ERRORS: case QUIET:
 614         default:             lp = "bug(pngcp)"; break;
 615      }
 616
 617      fprintf(stderr, "%s: %s: %s",
 618         dp->filename != NULL ? dp->filename : "<stdin>", lp, dp->operation);
 619
 620      fprintf(stderr, ": ");
 621
 622      va_start(ap, fmt);
 623      vfprintf(stderr, fmt, ap);
 624      va_end(ap);
 625
 626      fputc('\n', stderr);
 627   }
 628   /* else do not output any message */
 629
 630   /* Errors cause this routine to exit to the fail code */
 631   if (level > APP_FAIL || (level > ERRORS && !(dp->options & CONTINUE)))
 632   {
 633      if (dp->errset)
 634         longjmp(dp->error_return, level);
 635
 636      else
 637         exit(99);
 638   }
 639}
 640
 641#if PNG_LIBPNG_VER < 10700 && defined PNG_TEXT_SUPPORTED
 642static void
 643text_stash(struct display *dp)
 644{
 645   /* libpng 1.6 and earlier fixed a bug whereby text chunks were written
 646    * multiple times by png_write_png; the issue was that png_write_png passed
 647    * the same png_info to both png_write_info and png_write_end.  Rather than
 648    * fixing it by recording the information in the png_struct, or by recording
 649    * where to write the chunks, the fix made was to change the 'compression'
 650    * field of the chunk to invalid values, rendering the png_info somewhat
 651    * useless.
 652    *
 653    * The only fix for this given that we use the png_info more than once is to
 654    * make a copy of the text chunks and png_set_text it each time.  This adds a
 655    * text chunks, so they get replicated, but only the new set gets written
 656    * each time.  This uses memory like crazy but there is no way to delete the
 657    * useless chunks from the png_info.
 658    *
 659    * To make this slightly more efficient only the top level structure is
 660    * copied; since the old strings are actually preserved (in 1.6 and earlier)
 661    * this happens to work.
 662    */
 663   png_textp chunks = NULL;
 664
 665   dp->num_text = png_get_text(dp->write_pp, dp->ip, &chunks, NULL);
 666
 667   if (dp->num_text > 0)
 668   {
 669      dp->text_ptr = voidcast(png_textp, malloc(dp->num_text * sizeof *chunks));
 670
 671      if (dp->text_ptr == NULL)
 672         display_log(dp, APP_ERROR, "text chunks: stash malloc failed");
 673
 674      else
 675         memcpy(dp->text_ptr, chunks, dp->num_text * sizeof *chunks);
 676   }
 677
 678   dp->text_stashed = 1; /* regardless of whether there are chunks or not */
 679}
 680
 681#define text_stash(dp) if (!dp->text_stashed) text_stash(dp)
 682
 683static void
 684text_restore(struct display *dp)
 685{
 686   /* libpng makes a copy, so this is fine: */
 687   if (dp->text_ptr != NULL)
 688      png_set_text(dp->write_pp, dp->ip, dp->text_ptr, dp->num_text);
 689}
 690
 691#define text_restore(dp) if (dp->text_stashed) text_restore(dp)
 692
 693#else
 694#define text_stash(dp) ((void)0)
 695#define text_restore(dp) ((void)0)
 696#endif /* pre 1.7 */
 697
 698/* OPTIONS:
 699 *
 700 * The command handles options of the forms:
 701 *
 702 *    --option
 703 *       Turn an option on (Option)
 704 *    --no-option
 705 *       Turn an option off (Option)
 706 *    --option=value
 707 *       Set an option to a value (Value)
 708 *    --option=val1,val2,val3
 709 *       Set an option to a bitmask constructed from the values (List)
 710 */
 711static png_byte
 712option_index(struct display *dp, const char *opt, size_t len)
 713   /* Return the index (in options[]) of the given option, outputs an error if
 714    * it does not exist.  Takes the name of the option and a length (number of
 715    * characters in the name).
 716    */
 717{
 718   png_byte j;
 719
 720   for (j=0; j<option_count; ++j)
 721      if (strncmp(options[j].name, opt, len) == 0 && options[j].name[len] == 0)
 722         return j;
 723
 724   /* If the setjmp buffer is set the code is asking for an option index; this
 725    * is bad.  Otherwise this is the command line option parsing.
 726    */
 727   display_log(dp, dp->errset ? INTERNAL_ERROR : USER_ERROR,
 728         "%.*s: unknown option", (int)/*SAFE*/len, opt);
 729   abort(); /* NOT REACHED */
 730}
 731
 732/* This works for an option name (no quotes): */
 733#define OPTIND(dp, name) option_index(dp, #name, (sizeof #name)-1)
 734
 735static int
 736get_option(struct display *dp, const char *opt, int *value)
 737{
 738   const png_byte i = option_index(dp, opt, strlen(opt));
 739
 740   if (dp->entry[i]) /* option was set on command line */
 741   {
 742      *value = dp->value[i];
 743      return 1;
 744   }
 745
 746   else
 747      return 0;
 748}
 749
 750static int
 751set_opt_string_(struct display *dp, unsigned int sp, png_byte opt,
 752      const char *entry_name)
 753   /* Add the appropriate option string to dp->curr. */
 754{
 755   int offset, add;
 756
 757   if (sp > 0)
 758      offset = dp->stack[sp-1].opt_string_end;
 759
 760   else
 761      offset = dp->opt_string_start;
 762
 763   if (entry_name == range_lo)
 764      add = sprintf(dp->curr+offset, " --%s=%d", options[opt].name,
 765            dp->value[opt]);
 766
 767   else
 768      add = sprintf(dp->curr+offset, " --%s=%s", options[opt].name, entry_name);
 769
 770   if (add < 0)
 771      display_log(dp, INTERNAL_ERROR, "sprintf failed");
 772
 773   assert(offset+add < (int)/*SAFE*/sizeof dp->curr);
 774   return offset+add;
 775}
 776
 777static void
 778set_opt_string(struct display *dp, unsigned int sp)
 779   /* Add the appropriate option string to dp->curr. */
 780{
 781   dp->stack[sp].opt_string_end = set_opt_string_(dp, sp, dp->stack[sp].opt, 
 782      options[dp->stack[sp].opt].values[dp->stack[sp].entry].name);
 783}
 784
 785static void
 786record_opt(struct display *dp, png_byte opt, const char *entry_name)
 787   /* Record this option in dp->curr; called for an option not being searched,
 788    * the caller passes in the name of the value, or range_lo to use the
 789    * numerical value.
 790    */
 791{
 792   const unsigned int sp = dp->csp; /* stack entry of next searched option */
 793
 794   if (sp >= dp->tsp)
 795   {
 796      /* At top of stack; add the opt string for this entry to the previous
 797       * searched entry or the start of the dp->curr buffer if there is nothing
 798       * on the stack yet (sp == 0).
 799       */
 800      const int offset = set_opt_string_(dp, sp, opt, entry_name);
 801
 802      if (sp > 0)
 803         dp->stack[sp-1].opt_string_end = offset;
 804
 805      else
 806         dp->opt_string_start = offset;
 807   }
 808
 809   /* else do nothing: option already recorded */
 810}
 811
 812static int
 813opt_list_end(struct display *dp, png_byte opt, png_byte entry)
 814{
 815   if (options[opt].values[entry].name == range_lo)
 816      return entry+1U >= options[opt].value_count /* missing range_hi */ ||
 817         options[opt].values[entry+1U].name != range_hi /* likewise */ ||
 818         options[opt].values[entry+1U].value <= dp->value[opt] /* range end */;
 819
 820   else
 821      return entry+1U >= options[opt].value_count /* missing 'all' */ ||
 822         options[opt].values[entry+1U].name == all /* last entry */;
 823}
 824
 825static void
 826push_opt(struct display *dp, unsigned int sp, png_byte opt, int search)
 827   /* Push a new option onto the stack, initializing the new stack entry
 828    * appropriately; this does all the work of next_opt (setting end/nsp) for
 829    * the first entry in the list.
 830    */
 831{
 832   png_byte entry;
 833   const char *entry_name;
 834
 835   assert(sp == dp->tsp && sp < SL);
 836
 837   /* The starting entry is entry 0 unless there is a range in which case it is
 838    * the entry corresponding to range_lo:
 839    */
 840   entry = options[opt].value_count;
 841   assert(entry > 0U);
 842
 843   do
 844   {
 845      entry_name = options[opt].values[--entry].name;
 846      if (entry_name == range_lo)
 847         break;
 848   }
 849   while (entry > 0U);
 850
 851   dp->tsp = sp+1U;
 852   dp->stack[sp].best_size =
 853      dp->stack[sp].lo_size =
 854      dp->stack[sp].hi_size = MAX_SIZE;
 855
 856   if (search && entry_name == range_lo) /* search this range */
 857   {
 858      dp->stack[sp].lo = options[opt].values[entry].value;
 859      /* check for a mal-formed RANGE above: */
 860      assert(entry+1 < options[opt].value_count &&
 861             options[opt].values[entry+1].name == range_hi);
 862      dp->stack[sp].hi = options[opt].values[entry+1].value;
 863   }
 864
 865   else
 866   {
 867      /* next_opt will just iterate over the range. */
 868      dp->stack[sp].lo = INT_MAX;
 869      dp->stack[sp].hi = INT_MIN; /* Prevent range chop */
 870   }
 871
 872   dp->stack[sp].opt = opt;
 873   dp->stack[sp].entry = entry;
 874   dp->stack[sp].best_val = dp->value[opt] = options[opt].values[entry].value;
 875
 876   set_opt_string(dp, sp);
 877
 878   /* This works for the search case too; if the range has only one entry 'end'
 879    * will be marked here.
 880    */
 881   if (opt_list_end(dp, opt, entry))
 882   {
 883      dp->stack[sp].end = 1;
 884      /* Skip the warning if pngcp did this itself.  See the code in
 885       * set_windowBits_hi.
 886       */
 887      if (opt != dp->min_windowBits)
 888         display_log(dp, APP_WARNING, "%s: only testing one value",
 889               options[opt].name);
 890   }
 891
 892   else
 893   {
 894      dp->stack[sp].end = 0;
 895      dp->nsp = dp->tsp;
 896   }
 897
 898   /* Do a lazy cache of the text chunks for libpng 1.6 and earlier; this is
 899    * because they can only be written once(!) so if we are going to re-use the
 900    * png_info we need a copy.
 901    */
 902   text_stash(dp);
 903}
 904
 905static void
 906next_opt(struct display *dp, unsigned int sp)
 907   /* Return the next value for this option.  When called 'sp' is expected to be
 908    * the topmost stack entry - only the topmost entry changes each time round -
 909    * and there must be a valid entry to return.  next_opt will set dp->nsp to
 910    * sp+1 if more entries are available, otherwise it will not change it and
 911    * set dp->stack[s].end to true.
 912    */
 913{
 914   int search = 0;
 915   png_byte entry, opt;
 916   const char *entry_name;
 917
 918   /* dp->stack[sp] must be the top stack entry and it must be active: */
 919   assert(sp+1U == dp->tsp && !dp->stack[sp].end);
 920
 921   opt = dp->stack[sp].opt;
 922   entry = dp->stack[sp].entry;
 923   assert(entry+1U < options[opt].value_count);
 924   entry_name = options[opt].values[entry].name;
 925   assert(entry_name != NULL);
 926
 927   /* For ranges increment the value but don't change the entry, for all other
 928    * cases move to the next entry and load its value:
 929    */
 930   if (entry_name == range_lo) /* a range */
 931   {
 932      /* A range can be iterated over or searched.  The default iteration option
 933       * is indicated by hi < lo on the stack, otherwise the range being search
 934       * is [lo..hi] (inclusive).
 935       */
 936      if (dp->stack[sp].lo > dp->stack[sp].hi)
 937         dp->value[opt]++;
 938
 939      else
 940      {
 941         /* This is the best size found for this option value: */
 942         png_alloc_size_t best_size = dp->stack[sp].best_size;
 943         int lo = dp->stack[sp].lo;
 944         int hi = dp->stack[sp].hi;
 945         int val = dp->value[opt];
 946
 947         search = 1; /* end is determined here */
 948         assert(best_size < MAX_SIZE);
 949
 950         if (val == lo)
 951         {
 952            /* Finding the best for the low end of the range: */
 953            dp->stack[sp].lo_size = best_size;
 954            assert(hi > val);
 955
 956            if (hi == val+1) /* only 2 entries */
 957               dp->stack[sp].end = 1;
 958
 959            val = hi;
 960         }
 961
 962         else if (val == hi)
 963         {
 964            dp->stack[sp].hi_size = best_size;
 965            assert(val > lo+1); /* else 'end' set above */
 966
 967            if (val == lo+2) /* only three entries to test */
 968               dp->stack[sp].end = 1;
 969
 970            val = (lo + val)/2;
 971         }
 972
 973         else
 974         {
 975            png_alloc_size_t lo_size = dp->stack[sp].lo_size;
 976            png_alloc_size_t hi_size = dp->stack[sp].hi_size;
 977
 978            /* lo and hi should have been tested. */
 979            assert(lo_size < MAX_SIZE && hi_size < MAX_SIZE);
 980
 981            /* These cases arise with the 'probe' handling below when there is a
 982             * dip or peak in the size curve.
 983             */
 984            if (val < lo) /* probing a new lo */
 985            {
 986               /* Swap lo and val: */
 987               dp->stack[sp].lo = val;
 988               dp->stack[sp].lo_size = best_size;
 989               val = lo;
 990               best_size = lo_size;
 991               lo = dp->stack[sp].lo;
 992               lo_size = dp->stack[sp].lo_size;
 993            }
 994
 995            else if (val > hi) /* probing a new hi */
 996            {
 997               /* Swap hi and val: */
 998               dp->stack[sp].hi = val;
 999               dp->stack[sp].hi_size = best_size;
1000               val = hi;
1001               best_size = hi_size;
1002               hi = dp->stack[sp].hi;
1003               hi_size = dp->stack[sp].hi_size;
1004            }
1005
1006            /* The following should be true or something got messed up above. */
1007            assert(lo < val && val < hi);
1008
1009            /* If there are only four entries (lo, val, hi plus one more) just
1010             * test the remaining entry.
1011             */
1012            if (hi == lo+3)
1013            {
1014               /* Because of the 'probe' code val can either be lo+1 or hi-1; we
1015                * need to test the other.
1016                */
1017               val = lo + ((val == lo+1) ? 2 : 1);
1018               assert(lo < val && val < hi);
1019               dp->stack[sp].end = 1;
1020            }
1021
1022            else
1023            {
1024               /* There are at least 2 entries still untested between lo and hi,
1025                * i.e. hi >= lo+4.  'val' is the midpoint +/- 0.5
1026                *
1027                * Separate out the four easy cases when lo..val..hi are
1028                * monotonically decreased or (more weird) increasing:
1029                */
1030               assert(hi > lo+3);
1031
1032               if (lo_size <= best_size && best_size <= hi_size)
1033               {
1034                  /* Select the low range; testing this first favours the low
1035                   * range over the high range when everything comes out equal.
1036                   * Because of the probing 'val' may be lo+1.  In that case end
1037                   * the search and set 'val' to lo+2.
1038                   */
1039                  if (val == lo+1)
1040                  {
1041                     ++val;
1042                     dp->stack[sp].end = 1;
1043                  }
1044
1045                  else
1046                  {
1047                     dp->stack[sp].hi = hi = val;
1048                     dp->stack[sp].hi_size = best_size;
1049                     val = (lo + val) / 2;
1050                  }
1051               }
1052
1053               else if (lo_size >= best_size && best_size >= hi_size)
1054               {
1055                  /* Monotonically decreasing size; this is the expected case.
1056                   * Select the high end of the range.  As above, val may be
1057                   * hi-1.
1058                   */
1059                  if (val == hi-1)
1060                  {
1061                     --val;
1062                     dp->stack[sp].end = 1;
1063                  }
1064
1065                  else
1066                  {
1067                     dp->stack[sp].lo = lo = val;
1068                     dp->stack[sp].lo_size = best_size;
1069                     val = (val + hi) / 2;
1070                  }
1071               }
1072
1073               /* If both those tests failed 'best_size' is either greater than
1074                * or less than both lo_size and hi_size.  There is a peak or dip
1075                * in the curve of sizes from lo to hi and val is on the peak or
1076                * dip.
1077                *
1078                * Because the ranges being searched as so small (level is 1..9,
1079                * windowBits 8..15, memLevel 1..9) there will only be at most
1080                * three untested values between lo..val and val..hi, so solve
1081                * the problem by probing down from hi or up from lo, whichever
1082                * is the higher.
1083                *
1084                * This is the place where 'val' is set to outside the range
1085                * lo..hi, described as 'probing', though maybe 'narrowing' would
1086                * be more accurate.
1087                */
1088               else if (lo_size <= hi_size) /* down from hi */
1089               {
1090                  dp->stack[sp].hi = val;
1091                  dp->stack[sp].hi_size = best_size;
1092                  val = --hi;
1093               }
1094
1095               else /* up from low */
1096               {
1097                  dp->stack[sp].lo = val;
1098                  dp->stack[sp].lo_size = best_size;
1099                  val = ++lo;
1100               }
1101
1102               /* lo and hi are still the true range limits, check for the end
1103                * condition.
1104                */
1105               assert(hi > lo+1);
1106               if (hi <= lo+2)
1107                  dp->stack[sp].end = 1;
1108            }
1109         }
1110
1111         assert(val != dp->stack[sp].best_val); /* should be a new value */
1112         dp->value[opt] = val;
1113         dp->stack[sp].best_size = MAX_SIZE;
1114      }
1115   }
1116
1117   else
1118   {
1119      /* Increment 'entry' */
1120      dp->value[opt] = options[opt].values[++entry].value;
1121      dp->stack[sp].entry = entry;
1122   }
1123
1124   set_opt_string(dp, sp);
1125
1126   if (!search && opt_list_end(dp, opt, entry)) /* end of list */
1127      dp->stack[sp].end = 1;
1128
1129   else if (!dp->stack[sp].end) /* still active after all these tests */
1130      dp->nsp = dp->tsp;
1131}
1132
1133static int
1134compare_option(const struct display *dp, unsigned int sp)
1135{
1136   int opt = dp->stack[sp].opt;
1137
1138   /* If the best so far is numerically less than the current value the
1139    * current set of options is invariably worse.
1140    */
1141   if (dp->stack[sp].best_val < dp->value[opt])
1142      return -1;
1143
1144   /* Lists of options are searched out of numerical order (currently only
1145    * strategy), so only return +1 here when a range is being searched.
1146    */
1147   else if (dp->stack[sp].best_val > dp->value[opt])
1148   {
1149      if (dp->stack[sp].lo <= dp->stack[sp].hi /*searching*/)
1150         return 1;
1151
1152      else
1153         return -1;
1154   }
1155
1156   else
1157      return 0; /* match; current value is the best one */
1158}
1159
1160static int
1161advance_opt(struct display *dp, png_byte opt, int search)
1162{
1163   unsigned int sp = dp->csp++; /* my stack entry */
1164
1165   assert(sp >= dp->nsp); /* nsp starts off zero */
1166
1167   /* If the entry was active in the previous run dp->stack[sp] is already
1168    * set up and dp->tsp will be greater than sp, otherwise a new entry
1169    * needs to be created.
1170    *
1171    * dp->nsp is handled this way:
1172    *
1173    * 1) When an option is pushed onto the stack dp->nsp and dp->tsp are
1174    *    both set (by push_opt) to the next stack entry *unless* there is
1175    *    only one entry in the new list, in which case dp->stack[sp].end
1176    *    is set.
1177    *
1178    * 2) For the top stack entry next_opt is called.  The entry must be
1179    *    active (dp->stack[sp].end is not set) and either 'nsp' or 'end'
1180    *    will be updated as appropriate.
1181    *
1182    * 3) For lower stack entries nsp is set unless the stack entry is
1183    *    already at the end.  This means that when all the higher entries
1184    *    are popped this entry will be too.
1185    */
1186   if (sp >= dp->tsp)
1187   {
1188      push_opt(dp, sp, opt, search); /* This sets tsp to sp+1 */
1189      return 1; /* initialized */
1190   }
1191
1192   else
1193   {
1194      int ret = 0; /* unchanged */
1195
1196      /* An option that is already on the stack; update best_size and best_val
1197       * if appropriate.  On the first run there are no previous values and
1198       * dp->write_size will be MAX_SIZE, however on the first run dp->tsp
1199       * starts off as 0.
1200       */
1201      assert(dp->write_size > 0U && dp->write_size < MAX_SIZE);
1202
1203      if (dp->stack[sp].best_size > dp->write_size ||
1204          (dp->stack[sp].best_size == dp->write_size &&
1205           compare_option(dp, sp) > 0))
1206      {
1207         dp->stack[sp].best_size = dp->write_size;
1208         dp->stack[sp].best_val = dp->value[opt];
1209      }
1210
1211      if (sp+1U >= dp->tsp)
1212      {
1213         next_opt(dp, sp);
1214         ret = 1; /* advanced */
1215      }
1216
1217      else if (!dp->stack[sp].end) /* Active, not at top of stack */
1218         dp->nsp = sp+1U;
1219
1220      return ret; /* advanced || unchanged */
1221   }
1222}
1223
1224static int
1225getallopts_(struct display *dp, const png_byte opt, int *value, int record)
1226   /* Like getop but iterate over all the values if the option was set to "all".
1227    */
1228{
1229   if (dp->entry[opt]) /* option was set on command line */
1230   {
1231      /* Simple, single value, entries don't have a stack frame and have a fixed
1232       * value (it doesn't change once set on the command line).  Otherwise the
1233       * value (entry) selected from the command line is 'all':
1234       */
1235      const char *entry_name = options[opt].values[dp->entry[opt]-1].name;
1236
1237      if (entry_name == all)
1238         (void)advance_opt(dp, opt, 0/*do not search; iterate*/);
1239
1240      else if (record)
1241         record_opt(dp, opt, entry_name);
1242
1243      *value = dp->value[opt];
1244      return 1; /* set */
1245   }
1246
1247   else
1248      return 0; /* not set */
1249}
1250
1251static int
1252getallopts(struct display *dp, const char *opt_str, int *value)
1253{
1254   return getallopts_(dp, option_index(dp, opt_str, strlen(opt_str)), value, 0);
1255}
1256
1257static int
1258getsearchopts(struct display *dp, const char *opt_str, int *value)
1259   /* As above except that if the option was not set try a search */
1260{
1261   png_byte istrat;
1262   const png_byte opt = option_index(dp, opt_str, strlen(opt_str));
1263   int record = options[opt].search;
1264   const char *entry_name;
1265
1266   /* If it was set on the command line honour the setting, including 'all'
1267    * which will override the built in search:
1268    */
1269   if (getallopts_(dp, opt, value, record))
1270      return 1;
1271
1272   else if (!record) /* not a search option */
1273      return 0; /* unset and not searched */
1274
1275   /* Otherwise decide what to do here. */
1276   istrat = OPTIND(dp, strategy);
1277   entry_name = range_lo; /* record the value, not the name */
1278
1279   if (opt == istrat) /* search all strategies */
1280      (void)advance_opt(dp, opt, 0/*iterate*/), record=0;
1281
1282   else if (opt == OPTIND(dp, level))
1283   {
1284      /* Both RLE and HUFFMAN don't benefit from level increases */
1285      if (dp->value[istrat] == Z_RLE || dp->value[istrat] == Z_HUFFMAN_ONLY)
1286         dp->value[opt] = 1;
1287
1288      else /* fixed, filtered or default */
1289         (void)advance_opt(dp, opt, 1/*search*/), record=0;
1290   }
1291
1292   else if (opt == OPTIND(dp, windowBits))
1293   {
1294      /* Changing windowBits for strategies that do not search the window is
1295       * pointless.  Huffman-only does not search, RLE only searches backwards
1296       * one byte, so given that the maximum string length is 258, a windowBits
1297       * of 9 is always sufficient.
1298       */
1299      if (dp->value[istrat] == Z_HUFFMAN_ONLY)
1300         dp->value[opt] = 8;
1301
1302      else if (dp->value[istrat] == Z_RLE)
1303         dp->value[opt] = 9;
1304
1305      else /* fixed, filtered or default */
1306         (void)advance_opt(dp, opt, 1/*search*/), record=0;
1307   }
1308
1309   else if (opt == OPTIND(dp, memLevel))
1310   {
1311#     if 0
1312         (void)advance_opt(dp, opt, 0/*all*/), record=0;
1313#     else
1314         dp->value[opt] = MAX_MEM_LEVEL;
1315#     endif
1316   }
1317
1318   else /* something else */
1319      assert(0=="reached");
1320
1321   if (record)
1322      record_opt(dp, opt, entry_name);
1323
1324   /* One of the above searched options: */
1325   *value = dp->value[opt];
1326   return 1;
1327}
1328
1329static int
1330find_val(struct display *dp, png_byte opt, const char *str, size_t len)
1331   /* Like option_index but sets (index+i) of the entry in options[opt] that
1332    * matches str[0..len-1] into dp->entry[opt] as well as returning the actual
1333    * value.
1334    */
1335{
1336   int rlo = INT_MAX, rhi = INT_MIN;
1337   png_byte j, irange = 0;
1338
1339   for (j=1U; j<=options[opt].value_count; ++j)
1340   {
1341      if (strncmp(options[opt].values[j-1U].name, str, len) == 0 &&
1342          options[opt].values[j-1U].name[len] == 0)
1343      {
1344         dp->entry[opt] = j;
1345         return options[opt].values[j-1U].value;
1346      }
1347      else if (options[opt].values[j-1U].name == range_lo)
1348         rlo = options[opt].values[j-1U].value, irange = j;
1349      else if (options[opt].values[j-1U].name == range_hi)
1350         rhi = options[opt].values[j-1U].value;
1351   }
1352
1353   /* No match on the name, but there may be a range. */
1354   if (irange > 0)
1355   {
1356      char *ep = NULL;
1357      long l = strtol(str, &ep, 0);
1358
1359      if (ep == str+len && l >= rlo && l <= rhi)
1360      {
1361         dp->entry[opt] = irange; /* range_lo */
1362         return (int)/*SAFE*/l;
1363      }
1364   }
1365
1366   display_log(dp, dp->errset ? INTERNAL_ERROR : USER_ERROR,
1367         "%s: unknown value setting '%.*s'", options[opt].name,
1368         (int)/*SAFE*/len, str);
1369   abort(); /* NOT REACHED */
1370}
1371
1372static int
1373opt_check(struct display *dp, const char *arg)
1374{
1375   assert(dp->errset == 0);
1376
1377   if (arg != NULL && arg[0] == '-' && arg[1] == '-')
1378   {
1379      int i = 0, negate = (strncmp(arg+2, "no-", 3) == 0), val;
1380      png_byte j;
1381
1382      if (negate)
1383         arg += 5; /* --no- */
1384
1385      else
1386         arg += 2; /* -- */
1387
1388      /* Find the length (expect arg\0 or arg=) */
1389      while (arg[i] != 0 && arg[i] != '=') ++i;
1390
1391      /* So arg[0..i-1] is the argument name, this does not return if this isn't
1392       * a valid option name.
1393       */
1394      j = option_index(dp, arg, i);
1395
1396      /* It matcheth an option; check the remainder. */
1397      if (arg[i] == 0) /* no specified value, use the default */
1398      {
1399         val = options[j].values[negate].value;
1400         dp->entry[j] = (png_byte)/*SAFE*/(negate + 1U);
1401      }
1402
1403      else
1404      {
1405         const char *list = arg + (i+1);
1406
1407         /* Expect a single value here unless this is a list, in which case
1408          * multiple values are combined.
1409          */
1410         if (options[j].opt != LIST)
1411         {
1412            /* find_val sets 'dp->entry[j]' to a non-zero value: */
1413            val = find_val(dp, j, list, strlen(list));
1414
1415            if (negate)
1416            {
1417               if (options[j].opt < OPTION)
1418                  val = !val;
1419
1420               else
1421               {
1422                  display_log(dp, USER_ERROR,
1423                        "%.*s: option=arg cannot be negated", i, arg);
1424                  abort(); /* NOT REACHED */
1425               }
1426            }
1427         }
1428
1429         else /* multiple options separated by ',' characters */
1430         {
1431            /* --no-option negates list values from the default, which should
1432             * therefore be 'all'.  Notice that if the option list is empty in
1433             * this case nothing will be removed and therefore --no-option= is
1434             * the same as --option.
1435             */
1436            if (negate)
1437               val = options[j].values[0].value;
1438
1439            else
1440               val = 0;
1441
1442            while (*list != 0) /* allows option= which sets 0 */
1443            {
1444               /* A value is terminated by the end of the list or a ','
1445                * character.
1446                */
1447               int v, iv;
1448
1449               iv = 0; /* an index into 'list' */
1450               while (list[++iv] != 0 && list[iv] != ',') {}
1451
1452               v = find_val(dp, j, list, iv);
1453
1454               if (negate)
1455                  val &= ~v;
1456
1457               else
1458                  val |= v;
1459
1460               list += iv;
1461               if (*list != 0)
1462                  ++list; /* skip the ',' */
1463            }
1464         }
1465      }
1466
1467      /* 'val' is the new value, store it for use later and debugging: */
1468      dp->value[j] = val;
1469
1470      if (options[j].opt < LEVEL_MASK)
1471      {
1472         /* The handling for error levels is to set the level. */
1473         if (val) /* Set this level */
1474            dp->options = (dp->options & ~LEVEL_MASK) | options[j].opt;
1475
1476         else
1477            display_log(dp, USER_ERROR,
1478      "%.*s: messages cannot be turned off individually; set a message level",
1479                  i, arg);
1480      }
1481
1482      else if (options[j].opt < OPTION)
1483      {
1484         if (val)
1485            dp->options |= options[j].opt;
1486
1487         else
1488            dp->options &= ~options[j].opt;
1489      }
1490
1491      return 1; /* this is an option */
1492   }
1493
1494   else
1495      return 0; /* not an option */
1496}
1497
1498#ifdef PNG_PNGCP_TIMING_SUPPORTED
1499static void
1500set_timer(struct display *dp, struct timespec *timer)
1501{
1502   /* Do the timing using clock_gettime and the per-process timer. */
1503   if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, timer))
1504   {
1505      display_log(dp, APP_ERROR,
1506            "CLOCK_PROCESS_CPUTIME_ID: %s: timing disabled\n", strerror(errno));
1507      dp->value[OPTIND(dp,time)] = 0; /* i.e. off */
1508   }
1509}
1510
1511static void
1512start_timer(struct display *dp, int what)
1513{
1514   if ((dp->value[OPTIND(dp,time)] & what) != 0)
1515      set_timer(dp, what == PNGCP_TIME_READ ? &dp->read_time : &dp->write_time);
1516}
1517
1518static void
1519end_timer(struct display *dp, int what)
1520{
1521   if ((dp->value[OPTIND(dp,time)] & what) != 0)
1522   {
1523      struct timespec t, tmp;
1524
1525      set_timer(dp, &t);
1526
1527      if (what == PNGCP_TIME_READ)
1528         tmp = dp->read_time;
1529
1530      else
1531         tmp = dp->write_time;
1532
1533      t.tv_sec -= tmp.tv_sec;
1534      t.tv_nsec -= tmp.tv_nsec;
1535
1536      if (t.tv_nsec < 0)
1537      {
1538         --(t.tv_sec);
1539         t.tv_nsec += 1000000000L;
1540      }
1541
1542      if (what == PNGCP_TIME_READ)
1543         dp->read_time = t, tmp = dp->read_time_total;
1544
1545      else
1546         dp->write_time = t, tmp = dp->write_time_total;
1547
1548      tmp.tv_sec += t.tv_sec;
1549      tmp.tv_nsec += t.tv_nsec;
1550
1551      if (tmp.tv_nsec >= 1000000000L)
1552      {
1553         ++(tmp.tv_sec);
1554         tmp.tv_nsec -= 1000000000L;
1555      }
1556
1557      if (what == PNGCP_TIME_READ)
1558         dp->read_time_total = tmp;
1559
1560      else
1561         dp->write_time_total = tmp;
1562   }
1563}
1564
1565static void
1566print_time(const char *what, struct timespec t)
1567{
1568   printf("%s %.2lu.%.9ld", what, (unsigned long)t.tv_sec, t.tv_nsec);
1569}
1570#else /* !PNGCP_TIMING */
1571#define start_timer(dp, what) ((void)0)
1572#define end_timer(dp, what) ((void)0)
1573#endif /* !PNGCP_TIMING */
1574
1575/* The following is used in main to verify that the final argument is a
1576 * directory:
1577 */
1578static int
1579checkdir(const char *pathname)
1580{
1581   struct stat buf;
1582   return stat(pathname, &buf) == 0 && S_ISDIR(buf.st_mode);
1583}
1584
1585/* Work out whether a path is valid (if not a display_log occurs), a directory
1586 * (1 is returned) or a file *or* non-existent (0 is returned).
1587 *
1588 * Used for a write path.
1589 */
1590static int
1591isdir(struct display *dp, const char *pathname)
1592{
1593   if (pathname == NULL)
1594      return 0; /* stdout */
1595
1596   else if (pathname[0] == 0)
1597      return 1; /* empty string */
1598
1599   else
1600   {
1601      struct stat buf;
1602      int ret = stat(pathname, &buf);
1603
1604      if (ret == 0) /* the entry exists */
1605      {
1606         if (S_ISDIR(buf.st_mode))
1607            return 1;
1608
1609         /* Else expect an object that exists and can be written: */
1610         if (access(pathname, W_OK) != 0)
1611            display_log(dp, USER_ERROR, "%s: cannot be written (%s)", pathname,
1612                  strerror(errno));
1613
1614         return 0; /* file (exists, can be written) */
1615      }
1616
1617      else /* an error */
1618      {
1619         /* Non-existence is fine, other errors are not: */
1620         if (errno != ENOENT)
1621            display_log(dp, USER_ERROR, "%s: invalid output name (%s)",
1622                  pathname, strerror(errno));
1623
1624         return 0; /* file (does not exist) */
1625      }
1626   }
1627}
1628
1629static void
1630makename(struct display *dp, const char *dir, const char *infile)
1631{
1632   /* Make a name for an output file (and check it). */
1633   dp->namebuf[0] = 0;
1634
1635   if (dir == NULL || infile == NULL)
1636      display_log(dp, INTERNAL_ERROR, "NULL name to makename");
1637
1638   else
1639   {
1640      size_t dsize = strlen(dir);
1641
1642      if (dsize <= (sizeof dp->namebuf)-2) /* Allow for name + '/' + '\0' */
1643      {
1644         size_t isize = strlen(infile);
1645         size_t istart = isize-1;
1646
1647         /* This should fail before here: */
1648         if (infile[istart] == '/')
1649            display_log(dp, INTERNAL_ERROR, "infile with trailing /");
1650
1651         memcpy(dp->namebuf, dir, dsize);
1652         if (dsize > 0 && dp->namebuf[dsize-1] != '/')
1653            dp->namebuf[dsize++] = '/';
1654
1655         /* Find the rightmost non-/ character: */
1656         while (istart > 0 && infile[istart-1] != '/')
1657            --istart;
1658
1659         isize -= istart;
1660         infile += istart;
1661
1662         if (dsize+isize < (sizeof dp->namebuf)) /* dsize + infile + '\0' */
1663         {
1664            memcpy(dp->namebuf+dsize, infile, isize+1);
1665
1666            if (isdir(dp, dp->namebuf))
1667               display_log(dp, USER_ERROR, "%s: output file is a directory",
1668                     dp->namebuf);
1669         }
1670
1671         else
1672         {
1673            dp->namebuf[dsize] = 0; /* allowed for: -2 at start */
1674            display_log(dp, USER_ERROR, "%s%s: output file name too long",
1675                  dp->namebuf, infile);
1676         }
1677      }
1678
1679      else
1680         display_log(dp, USER_ERROR, "%s: output directory name too long", dir);
1681   }
1682}
1683
1684/* error handler callbacks for libpng */
1685static void PNGCBAPI
1686display_warning(png_structp pp, png_const_charp warning)
1687{
1688   struct display *dp = get_dp(pp);
1689
1690   /* This is used to prevent repeated warnings while searching */
1691   if (!dp->no_warnings)
1692      display_log(get_dp(pp), LIBPNG_WARNING, "%s", warning);
1693}
1694
1695static void PNGCBAPI
1696display_error(png_structp pp, png_const_charp error)
1697{
1698   struct display *dp = get_dp(pp);
1699
1700   display_log(dp, LIBPNG_ERROR, "%s", error);
1701}
1702
1703static void
1704display_start_read(struct display *dp, const char *filename)
1705{
1706   if (filename != NULL)
1707   {
1708      dp->filename = filename;
1709      dp->fp = fopen(filename, "rb");
1710   }
1711
1712   else
1713   {
1714      dp->filename = "<stdin>";
1715      dp->fp = stdin;
1716   }
1717
1718   dp->w = dp->h = 0U;
1719   dp->bpp = 0U;
1720   dp->size = 0U;
1721   dp->read_size = 0U;
1722
1723   if (dp->fp == NULL)
1724      display_log(dp, USER_ERROR, "file open failed (%s)", strerror(errno));
1725}
1726
1727static void PNGCBAPI
1728read_function(png_structp pp, png_bytep data, png_size_t size)
1729{
1730   struct display *dp = get_dp(pp);
1731
1732   if (size == 0U || fread(data, size, 1U, dp->fp) == 1U)
1733      dp->read_size += size;
1734
1735   else
1736   {
1737      if (feof(dp->fp))
1738         display_log(dp, LIBPNG_ERROR, "PNG file truncated");
1739      else
1740         display_log(dp, LIBPNG_ERROR, "PNG file read failed (%s)",
1741               strerror(errno));
1742   }
1743}
1744
1745static void
1746read_png(struct display *dp, const char *filename)
1747{
1748   display_clean_read(dp); /* safety */
1749   display_start_read(dp, filename);
1750
1751   dp->read_pp = png_create_read_struct(PNG_LIBPNG_VER_STRING, dp,
1752      display_error, display_warning);
1753   if (dp->read_pp == NULL)
1754      display_log(dp, LIBPNG_ERROR, "failed to create read struct");
1755
1756#  ifdef PNG_BENIGN_ERRORS_SUPPORTED
1757      png_set_benign_errors(dp->read_pp, 1/*allowed*/);
1758#  endif /* BENIGN_ERRORS */
1759
1760#  ifdef FIX_INDEX
1761      if ((dp->options & FIX_INDEX) != 0)
1762         png_set_check_for_invalid_index(dp->read_pp, 1/*on, no warning*/);
1763#     ifdef IGNORE_INDEX
1764         else
1765#     endif /* IGNORE_INDEX */
1766#  endif /* FIX_INDEX */
1767#  ifdef IGNORE_INDEX
1768      if ((dp->options & IGNORE_INDEX) != 0) /* DANGEROUS */
1769         png_set_check_for_invalid_index(dp->read_pp, -1/*off completely*/);
1770#  endif /* IGNORE_INDEX */
1771
1772   /* The png_read_png API requires us to make the info struct, but it does the
1773    * call to png_read_info.
1774    */
1775   dp->ip = png_create_info_struct(dp->read_pp);
1776   if (dp->ip == NULL)
1777      png_error(dp->read_pp, "failed to create info struct");
1778
1779   /* Set the IO handling */
1780   png_set_read_fn(dp->read_pp, dp, read_function);
1781
1782#  ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
1783      png_set_keep_unknown_chunks(dp->read_pp, PNG_HANDLE_CHUNK_ALWAYS, NULL,
1784            0);
1785#  endif /* HANDLE_AS_UNKNOWN */
1786
1787#  ifdef PNG_SET_USER_LIMITS_SUPPORTED
1788      /* Remove the user limits, if any */
1789      png_set_user_limits(dp->read_pp, 0x7fffffff, 0x7fffffff);
1790#  endif /* SET_USER_LIMITS */
1791
1792   /* Now read the PNG. */
1793   start_timer(dp, PNGCP_TIME_READ);
1794   png_read_png(dp->read_pp, dp->ip, 0U/*transforms*/, NULL/*params*/);
1795   end_timer(dp, PNGCP_TIME_READ);
1796   dp->w = png_get_image_width(dp->read_pp, dp->ip);
1797   dp->h = png_get_image_height(dp->read_pp, dp->ip);
1798   dp->ct = png_get_color_type(dp->read_pp, dp->ip);
1799   dp->bpp = png_get_bit_depth(dp->read_pp, dp->ip) *
1800             png_get_channels(dp->read_pp, dp->ip);
1801   {
1802      /* png_get_rowbytes should never return 0 because the value is set by the
1803       * first call to png_set_IHDR, which should have happened by now, but just
1804       * in case:
1805       */
1806      png_alloc_size_t rb = png_get_rowbytes(dp->read_pp, dp->ip);
1807
1808      if (rb == 0)
1809         png_error(dp->read_pp, "invalid row byte count from libpng");
1810
1811      /* The size calc can overflow. */
1812      if ((MAX_SIZE-dp->h)/rb < dp->h)
1813         png_error(dp->read_pp, "image too large");
1814
1815      dp->size = rb * dp->h + dp->h/*filter byte*/;
1816   }
1817
1818#ifdef FIX_INDEX
1819   if (dp->ct == PNG_COLOR_TYPE_PALETTE && (dp->options & FIX_INDEX) != 0)
1820   {
1821      int max = png_get_palette_max(dp->read_pp, dp->ip);
1822      png_colorp palette = NULL;
1823      int num = -1;
1824
1825      if (png_get_PLTE(dp->read_pp, dp->ip, &palette, &num) != PNG_INFO_PLTE
1826          || max < 0 || num <= 0 || palette == NULL)
1827         display_log(dp, LIBPNG_ERROR, "invalid png_get_PLTE result");
1828
1829      if (max >= num)
1830      {
1831         /* 'Fix' the palette. */
1832         int i;
1833         png_color newpal[256];
1834
1835         for (i=0; i<num; ++i)
1836            newpal[i] = palette[i];
1837
1838         /* Fill in any remainder with a warning color: */
1839         for (; i<=max; ++i)
1840         {
1841            newpal[i].red = 0xbe;
1842            newpal[i].green = 0xad;
1843            newpal[i].blue = 0xed;
1844         }
1845
1846         png_set_PLTE(dp->read_pp, dp->ip, newpal, i);
1847      }
1848   }
1849#endif /* FIX_INDEX */
1850
1851   display_clean_read(dp);
1852   dp->operation = "none";
1853}
1854
1855static void
1856display_start_write(struct display *dp, const char *filename)
1857{
1858   assert(dp->fp == NULL);
1859
1860   if ((dp->options & NOWRITE) != 0)
1861      dp->output_file = "<no write>";
1862
1863   else
1864   {
1865      if (filename != NULL)
1866      {
1867         dp->output_file = filename;
1868         dp->fp = fopen(filename, "wb");
1869      }
1870
1871      else
1872      {
1873         dp->output_file = "<stdout>";
1874         dp->fp = stdout;
1875      }
1876
1877      if (dp->fp == NULL)
1878         display_log(dp, USER_ERROR, "%s: file open failed (%s)",
1879               dp->output_file, strerror(errno));
1880   }
1881}
1882
1883static void PNGCBAPI
1884write_function(png_structp pp, png_bytep data, png_size_t size)
1885{
1886   struct display *dp = get_dp(pp);
1887
1888   /* The write fail is classed as a USER_ERROR, so --quiet does not turn it
1889    * off, this seems more likely to be correct.
1890    */
1891   if (dp->fp == NULL || fwrite(data, size, 1U, dp->fp) == 1U)
1892   {
1893      dp->write_size += size;
1894      if (dp->write_size < size || dp->write_size == MAX_SIZE)
1895         png_error(pp, "IDAT size overflow");
1896   }
1897
1898   else
1899      display_log(dp, USER_ERROR, "%s: PNG file write failed (%s)",
1900            dp->output_file, strerror(errno));
1901}
1902
1903/* Compression option, 'method' is never set: there is no choice.
1904 *
1905 * IMPORTANT: the order of the entries in this macro determines the preference
1906 * order when two different combos of two of these options produce an IDAT of
1907 * the same size.  The logic here is to put the things that affect the decoding
1908 * of the PNG image ahead of those that are relevant only to the encoding.
1909 */
1910#define SET_COMPRESSION\
1911   SET(strategy, strategy);\
1912   SET(windowBits, window_bits);\
1913   SET(level, level);\
1914   SET(memLevel, mem_level);
1915
1916#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
1917static void
1918search_compression(struct display *dp)
1919{
1920   /* Like set_compression below but use a more restricted search than 'all' */
1921   int val;
1922
1923#  define SET(name, func) if (getsearchopts(dp, #name, &val))\
1924      png_set_compression_ ## func(dp->write_pp, val);
1925   SET_COMPRESSION
1926#  undef SET
1927}
1928
1929static void
1930set_compression(struct display *dp)
1931{
1932   int val;
1933
1934#  define SET(name, func) if (getallopts(dp, #name, &val))\
1935      png_set_compression_ ## func(dp->write_pp, val);
1936   SET_COMPRESSION
1937#  undef SET
1938}
1939
1940#ifdef PNG_SW_COMPRESS_level /* 1.7.0+ */
1941static void
1942set_ICC_profile_compression(struct display *dp)
1943{
1944   int val;
1945
1946#  define SET(name, func) if (getallopts(dp, "ICC-profile-" #name, &val))\
1947      png_set_ICC_profile_compression_ ## func(dp->write_pp, val);
1948   SET_COMPRESSION
1949#  undef SET
1950}
1951#else
1952#  define set_ICC_profile_compression(dp) ((void)0)
1953#endif
1954#else
1955#  define search_compression(dp) ((void)0)
1956#  define set_compression(dp) ((void)0)
1957#  define set_ICC_profile_compression(dp) ((void)0)
1958#endif /* WRITE_CUSTOMIZE_COMPRESSION */
1959
1960#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
1961static void
1962set_text_compression(struct display *dp)
1963{
1964   int val;
1965
1966#  define SET(name, func) if (getallopts(dp, "text-" #name, &val))\
1967      png_set_text_compression_ ## func(dp->write_pp, val);
1968   SET_COMPRESSION
1969#  undef SET
1970}
1971#else
1972#  define set_text_compression(dp) ((void)0)
1973#endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */
1974
1975static void
1976write_png(struct display *dp, const char *destname)
1977{
1978   display_clean_write(dp); /* safety */
1979   display_start_write(dp, destname);
1980
1981   dp->write_pp = png_create_write_struct(PNG_LIBPNG_VER_STRING, dp,
1982      display_error, display_warning);
1983
1984   if (dp->write_pp == NULL)
1985      display_log(dp, LIBPNG_ERROR, "failed to create write png_struct");
1986
1987#  ifdef PNG_BENIGN_ERRORS_SUPPORTED
1988      png_set_benign_errors(dp->write_pp, 1/*allowed*/);
1989#  endif /* BENIGN_ERRORS */
1990
1991   png_set_write_fn(dp->write_pp, dp, write_function, NULL/*flush*/);
1992
1993#ifdef IGNORE_INDEX
1994   if ((dp->options & IGNORE_INDEX) != 0) /* DANGEROUS */
1995      png_set_check_for_invalid_index(dp->write_pp, -1/*off completely*/);
1996#endif /* IGNORE_INDEX */
1997
1998   /* Restore the text chunks when using libpng 1.6 or less; this is a macro
1999    * which expands to nothing in 1.7+  In earlier versions it tests
2000    * dp->text_stashed, which is only set (below) *after* the first write.
2001    */
2002   text_restore(dp);
2003
2004#  ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
2005      png_set_keep_unknown_chunks(dp->write_pp, PNG_HANDLE_CHUNK_ALWAYS, NULL,
2006            0);
2007#  endif /* HANDLE_AS_UNKNOWN */
2008
2009#  ifdef PNG_SET_USER_LIMITS_SUPPORTED
2010      /* Remove the user limits, if any */
2011      png_set_user_limits(dp->write_pp, 0x7fffffff, 0x7fffffff);
2012#  endif
2013
2014   /* OPTION HANDLING */
2015   /* compression outputs, IDAT and zTXt/iTXt: */
2016   dp->tsp = dp->nsp;
2017   dp->nsp = dp->csp = 0;
2018#  ifdef PNG_SW_COMPRESS_png_level
2019      {
2020         int val;
2021
2022         /* This sets everything, but then the following options just override
2023          * the specific settings for ICC profiles and text.
2024          */
2025         if (getallopts(dp, "compression", &val))
2026            png_set_compression(dp->write_pp, val);
2027
2028         if (getallopts(dp, "ICC-profile-compression", &val))
2029            png_set_ICC_profile_compression(dp->write_pp, val);
2030
2031         if (getallopts(dp, "text-compression", &val))
2032            png_set_text_compression(dp->write_pp, val);
2033      }
2034#  endif /* png_level support */
2035   if (dp->options & SEARCH)
2036      search_compression(dp);
2037   else
2038      set_compression(dp);
2039   set_ICC_profile_compression(dp);
2040   set_text_compression(dp);
2041
2042   {
2043      int val;
2044
2045      /* The permitted range is 1..0x7FFFFFFF, so the cast is safe */
2046      if (get_option(dp, "IDAT-size", &val))
2047         png_set_IDAT_size(dp->write_pp, val);
2048   }
2049
2050   /* filter handling */
2051#  ifdef PNG_WRITE_FILTER_SUPPORTED
2052      {
2053         int val;
2054
2055         if (get_option(dp, "filter", &val))
2056            png_set_filter(dp->write_pp, PNG_FILTER_TYPE_BASE, val);
2057      }
2058#  endif /* WRITE_FILTER */
2059
2060   /* This just uses the 'read' info_struct directly, it contains the image. */
2061   dp->write_size = 0U;
2062   start_timer(dp, PNGCP_TIME_WRITE);
2063   png_write_png(dp->write_pp, dp->ip, 0U/*transforms*/, NULL/*params*/);
2064   end_timer(dp, PNGCP_TIME_WRITE);
2065
2066   /* Make sure the file was written ok: */
2067   if (dp->fp != NULL)
2068   {
2069      FILE *fp = dp->fp;
2070      dp->fp = NULL;
2071      if (fclose(fp))
2072         display_log(dp, APP_ERROR, "%s: write failed (%s)",
2073               destname == NULL ? "stdout" : destname, strerror(errno));
2074   }
2075
2076   /* Clean it on the way out - if control returns to the caller then the
2077    * written_file contains the required data.
2078    */
2079   display_clean_write(dp);
2080   dp->operation = "none";
2081}
2082
2083static void
2084set_windowBits_hi(struct display *dp)
2085{
2086   /* windowBits is in the range 8..15 but zlib maps '8' to '9' so it is only
2087    * worth using if the data size is 256 byte or less.
2088    */
2089   int wb = MAX_WBITS; /* for large images */
2090   int i = VLSIZE(windowBits_IDAT);
2091
2092   while (wb > 8 && dp->size <= 1U<<(wb-1)) --wb;
2093
2094   while (--i >= 0) if (VLNAME(windowBits_IDAT)[i].name == range_hi) break;
2095
2096   assert(i > 1); /* vl_windowBits_IDAT always has a RANGE() */
2097   VLNAME(windowBits_IDAT)[i].value = wb;
2098
2099   assert(VLNAME(windowBits_IDAT)[--i].name == range_lo);
2100   VLNAME(windowBits_IDAT)[i].value = wb > 8 ? 9 : 8;
2101
2102   /* If wb == 8 then any search has been restricted to just one windowBits
2103    * entry.  Record that here to avoid producing a spurious app-level warning
2104    * above.
2105    */
2106   if (wb == 8)
2107      dp->min_windowBits = OPTIND(dp, windowBits);
2108}
2109
2110static int
2111better_options(const struct display *dp)
2112{
2113   /* Are these options better than the best found so far?  Normally the
2114    * options are tested in preference order, best first, however when doing a
2115    * search operation on a range the range values are tested out of order.  In
2116    * that case preferable options will get tested later.
2117    *
2118    * This function looks through the stack from the bottom up looking for an
2119    * option that does not match the current best value.  When it finds one it
2120    * checks to see if it is more or less desireable and returns true or false
2121    * as appropriate.
2122    *
2123    * Notice that this means that the order options are pushed onto the stack
2124    * conveys a priority; lower/earlier options are more important than later
2125    * ones.
2126    */
2127   unsigned int sp;
2128
2129   for (sp=0; sp<dp->csp; ++sp)
2130   {
2131      int c = compare_option(dp, sp);
2132
2133      if (c < 0)
2134         return 0; /* worse */
2135
2136      else if (c > 0)
2137         return 1; /* better */
2138   }
2139
2140   assert(0 && "unreached");
2141}
2142
2143static void
2144print_search_results(struct display *dp)
2145{
2146   assert(dp->filename != NULL);
2147   printf("%s [%ld x %ld %d bpp %s, %lu bytes] %lu -> %lu with '%s'\n",
2148      dp->filename, (unsigned long)dp->w, (unsigned long)dp->h, dp->bpp,
2149      cts(dp->ct), (unsigned long)dp->size, (unsigned long)dp->read_size,
2150      (unsigned long)dp->best_size, dp->best);
2151   fflush(stdout);
2152}
2153
2154static void
2155log_search(struct display *dp, unsigned int log_depth)
2156{
2157   /* Log, and reset, the search so far: */
2158   if (dp->nsp/*next entry to change*/ <= log_depth)
2159   {
2160      print_search_results(dp);
2161      /* Start again with this entry: */
2162      dp->best_size = MAX_SIZE;
2163   }
2164}
2165
2166static void
2167cp_one_file(struct display *dp, const char *filename, const char *destname)
2168{
2169   unsigned int log_depth;
2170
2171   dp->filename = filename;
2172   dp->operation = "read";
2173   dp->no_warnings = 0;
2174
2175   /* Read it then write it: */
2176   if (filename != NULL && access(filename, R_OK) != 0)
2177      display_log(dp, USER_ERROR, "%s: invalid file name (%s)",
2178            filename, strerror(errno));
2179
2180   read_png(dp, filename);
2181
2182   /* But 'destname' may be a directory. */
2183   dp->operation = "write";
2184
2185   /* Limit the upper end of the windowBits range for this file */
2186   set_windowBits_hi(dp);
2187
2188   /* For logging, depth to log: */
2189   {
2190      int val;
2191
2192      if (get_option(dp, "log-depth", &val) && val >= 0)
2193         log_depth = (unsigned int)/*SAFE*/val;
2194
2195      else
2196         log_depth = 0U;
2197   }
2198
2199   if (destname != NULL) /* else stdout */
2200   {
2201      if (isdir(dp, destname))
2202      {
2203         makename(dp, destname, filename);
2204         destname = dp->namebuf;
2205      }
2206
2207      else if (access(destname, W_OK) != 0 && errno != ENOENT)
2208         display_log(dp, USER_ERROR, "%s: invalid output name (%s)", destname,
2209               strerror(errno));
2210   }
2211
2212   dp->nsp = 0;
2213   dp->curr[0] = 0; /* acts as a flag for the caller */
2214   dp->opt_string_start = 0;
2215   dp->best[0] = 0; /* safety */
2216   dp->best_size = MAX_SIZE;
2217   write_png(dp, destname);
2218
2219   /* Initialize the 'best' fields: */
2220   strcpy(dp->best, dp->curr);
2221   dp->best_size = dp->write_size;
2222
2223   if (dp->nsp > 0) /* interating over lists */
2224   {
2225      char *tmpname, tmpbuf[(sizeof dp->namebuf) + 4];
2226      assert(dp->curr[0] == ' ' && dp->tsp > 0);
2227
2228      /* Cancel warnings on subsequent writes */
2229      log_search(dp, log_depth);
2230      dp->no_warnings = 1;
2231
2232      /* Make a temporary name for the subsequent tests: */
2233      if (destname != NULL)
2234      {
2235         strcpy(tmpbuf, destname);
2236         strcat(tmpbuf, ".tmp"); /* space for .tmp allocated above */
2237         tmpname = tmpbuf;
2238      }
2239
2240      else
2241         tmpname = NULL; /* stdout */
2242
2243      /* Loop to find the best option. */
2244      do
2245      {
2246         write_png(dp, tmpname);
2247
2248         /* And compare the sizes (the write function makes sure write_size
2249          * doesn't overflow.)
2250          */
2251         assert(dp->csp > 0);
2252
2253         if (dp->write_size < dp->best_size ||
2254             (dp->write_size == dp->best_size && better_options(dp)))
2255         {
2256            if (destname != NULL && rename(tmpname, destname) != 0)
2257               display_log(dp, APP_ERROR, "rename %s %s failed (%s)", tmpname,
2258                     destname, strerror(errno));
2259
2260            strcpy(dp->best, dp->curr);
2261            dp->best_size = dp->write_size;
2262         }
2263
2264         else if (tmpname != NULL && unlink(tmpname) != 0)
2265            display_log(dp, APP_WARNING, "unlink %s failed (%s)", tmpname,
2266                  strerror(errno));
2267
2268         log_search(dp, log_depth);
2269      }
2270      while (dp->nsp > 0);
2271
2272      /* Do this for the 'sizes' option so that it reports the correct size. */
2273      dp->write_size = dp->best_size;
2274   }
2275}
2276
2277static int
2278cppng(struct display *dp, const char *file, const char *gv dest)
2279   /* Exists solely to isolate the setjmp clobbers which some versions of GCC
2280    * erroneously generate.
2281    */
2282{
2283   int ret = setjmp(dp->error_return);
2284
2285   if (ret == 0)
2286   {
2287      dp->errset = 1;
2288      cp_one_file(dp, file, dest);
2289      dp->errset = 0;
2290      return 0;
2291   }
2292
2293   else
2294   {
2295      dp->errset = 0;
2296
2297      if (ret < ERRORS) /* shouldn't longjmp on warnings */
2298         display_log(dp, INTERNAL_ERROR, "unexpected return code %d", ret);
2299
2300      return ret;
2301   }
2302}
2303
2304int
2305main(const int argc, const char * const * const argv)
2306{
2307   /* For each file on the command line test it with a range of transforms */
2308   int option_end;
2309   struct display d;
2310
2311   display_init(&d);
2312
2313   d.operation = "options";
2314   for (option_end = 1;
2315        option_end < argc && opt_check(&d, argv[option_end]);
2316        ++option_end)
2317   {
2318   }
2319
2320   /* Do a quick check on the directory target case; when there are more than
2321    * two arguments the last one must be a directory.
2322    */
2323   if (!(d.options & NOWRITE) && option_end+2 < argc && !checkdir(argv[argc-1]))
2324   {
2325      fprintf(stderr,
2326            "pngcp: %s: directory required with more than two arguments\n",
2327            argv[argc-1]);
2328      return 99;
2329   }
2330
2331   {
2332      int errors = 0;
2333      int i = option_end;
2334
2335      /* Do this at least once; if there are no arguments stdin/stdout are used.
2336       */
2337      d.operation = "files";
2338      do
2339      {
2340         const char *infile = NULL;
2341         const char *outfile = NULL;
2342         int ret;
2343
2344         if (i < argc)
2345         {
2346            infile = argv[i++];
2347            if (!(d.options & NOWRITE) && i < argc)
2348               outfile = argv[argc-1];
2349         }
2350
2351         ret = cppng(&d, infile, outfile);
2352
2353         if (ret)
2354         {
2355            if (ret > QUIET) /* abort on user or internal error */
2356               return 99;
2357
2358            /* An error: the output is meaningless */
2359         }
2360
2361         else if (d.best[0] != 0)
2362         {
2363            /* This result may already have been output, in which case best_size
2364             * has been reset.
2365             */
2366            if (d.best_size < MAX_SIZE)
2367               print_search_results(&d);
2368         }
2369
2370         else if (d.options & SIZES)
2371         {
2372            printf("%s [%ld x %ld %d bpp %s, %lu bytes] %lu -> %lu [0x%lx]\n",
2373                  infile, (unsigned long)d.w, (unsigned long)d.h, d.bpp,
2374                  cts(d.ct), (unsigned long)d.size, (unsigned long)d.read_size,
2375                  (unsigned long)d.write_size, (unsigned long)d.results);
2376            fflush(stdout);
2377         }
2378
2379         /* Here on any return, including failures, except user/internal issues
2380          */
2381         {
2382            const int pass = (d.options & STRICT) ?
2383               RESULT_STRICT(d.results) : RESULT_RELAXED(d.results);
2384
2385            if (!pass)
2386               ++errors;
2387
2388            if (d.options & LOG)
2389            {
2390               int j;
2391
2392               printf("%s: pngcp", pass ? "PASS" : "FAIL");
2393
2394               for (j=1; j<option_end; ++j)
2395                  printf(" %s", argv[j]);
2396
2397               if (infile != NULL)
2398                  printf(" %s", infile);
2399
2400#              ifdef PNG_PNGCP_TIMING_SUPPORTED
2401                  /* When logging output the files for each file, if enabled. */
2402                  if ((d.value[OPTIND(&d,time)] & PNGCP_TIME_READ) != 0)
2403                     print_time(" read", d.read_time);
2404
2405                  if ((d.value[OPTIND(&d,time)] & PNGCP_TIME_WRITE) != 0)
2406                     print_time(" write", d.write_time);
2407#              endif /* PNGCP_TIMING */
2408
2409               printf("\n");
2410               fflush(stdout);
2411            }
2412         }
2413
2414         display_clean(&d);
2415      }
2416      while (i+!(d.options & NOWRITE) < argc);
2417         /* I.e. for write cases after the first time through the loop require
2418          * there to be at least two arguments left and for the last one to be a
2419          * directory (this was checked above).
2420          */
2421
2422      /* Release allocated memory */
2423      display_destroy(&d);
2424
2425#     ifdef PNG_PNGCP_TIMING_SUPPORTED
2426         {
2427            int output = 0;
2428
2429            if ((d.value[OPTIND(&d,time)] & PNGCP_TIME_READ) != 0)
2430               print_time("read", d.read_time_total), output = 1;
2431
2432            if ((d.value[OPTIND(&d,time)] & PNGCP_TIME_WRITE) != 0)
2433            {
2434               if (output) putchar(' ');
2435               print_time("write", d.write_time_total);
2436               output = 1;
2437            }
2438
2439            if (output) putchar('\n');
2440         }
2441#     endif /* PNGCP_TIMING */
2442
2443      return errors != 0;
2444   }
2445}
2446#else /* !READ_PNG || !WRITE_PNG */
2447int
2448main(void)
2449{
2450   fprintf(stderr, "pngcp: no support for png_read/write_image\n");
2451   return 77;
2452}
2453#endif /* !READ_PNG || !WRITE_PNG */