Home | History | Annotate | Download | only in tools
      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. */
    117 typedef 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 */
    158 static const char range_lo[] = "low";
    159 static const char range_hi[] = "high";
    160 static const char all[] = "all";
    161 #define RANGE(lo,hi) { range_lo, lo }, { range_hi, hi }
    162 typedef 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 
    168 static const value_list
    169 #ifdef PNG_SW_COMPRESS_png_level
    170 vl_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)
    189 vl_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
    200 vl_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 */
    208 vl_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 },
    218 vl_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
    232 vl_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
    246 vl_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 */
    254 vl_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 */
    265 vl_log_depth[] = { { "on", 1 }, { "off", 0 }, RANGE(0, SL) },
    266 vl_on_off[] = { { "on", 1 }, { "off", 0 } };
    267 
    268 #ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
    269 static value_list
    270 vl_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 
    279 typedef 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 
    288 static 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 
    377 static const char *
    378 cts(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 
    391 struct 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 
    481 static void
    482 display_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 
    505 static void
    506 display_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 
    519 static void
    520 display_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 
    533 static void
    534 display_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 
    557 static void
    558 display_destroy(struct display *dp)
    559 {
    560    /* Release any memory held in the display. */
    561    display_clean(dp);
    562 }
    563 
    564 static struct display *
    565 get_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
    588 static void VGATTR
    589 display_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
    642 static void
    643 text_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 
    683 static void
    684 text_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  */
    711 static png_byte
    712 option_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 
    735 static int
    736 get_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 
    750 static int
    751 set_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 
    777 static void
    778 set_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 
    785 static void
    786 record_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 
    812 static int
    813 opt_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 
    825 static void
    826 push_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 
    905 static void
    906 next_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 
   1133 static int
   1134 compare_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 
   1160 static int
   1161 advance_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 
   1224 static int
   1225 getallopts_(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 
   1251 static int
   1252 getallopts(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 
   1257 static int
   1258 getsearchopts(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 
   1329 static int
   1330 find_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 
   1372 static int
   1373 opt_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
   1499 static void
   1500 set_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 
   1511 static void
   1512 start_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 
   1518 static void
   1519 end_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 
   1565 static void
   1566 print_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  */
   1578 static int
   1579 checkdir(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  */
   1590 static int
   1591 isdir(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 
   1629 static void
   1630 makename(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 */
   1685 static void PNGCBAPI
   1686 display_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 
   1695 static void PNGCBAPI
   1696 display_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 
   1703 static void
   1704 display_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 
   1727 static void PNGCBAPI
   1728 read_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 
   1745 static void
   1746 read_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 
   1855 static void
   1856 display_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 
   1883 static void PNGCBAPI
   1884 write_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
   1917 static void
   1918 search_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 
   1929 static void
   1930 set_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+ */
   1941 static void
   1942 set_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
   1961 static void
   1962 set_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 
   1975 static void
   1976 write_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 
   2083 static void
   2084 set_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 
   2110 static int
   2111 better_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 
   2143 static void
   2144 print_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 
   2154 static void
   2155 log_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 
   2166 static void
   2167 cp_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 
   2277 static int
   2278 cppng(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 
   2304 int
   2305 main(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 */
   2447 int
   2448 main(void)
   2449 {
   2450    fprintf(stderr, "pngcp: no support for png_read/write_image\n");
   2451    return 77;
   2452 }
   2453 #endif /* !READ_PNG || !WRITE_PNG */
   2454