about summary refs log tree commit diff
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2013-09-28 22:24:33 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2013-09-28 22:24:33 +0000
commit2730bca5129bf0304d7860c49925f159e61473da (patch)
treebc10b0b5f2bb1968ea19b0ea912132d96adf6e75
parentee7ca90d04b4427ae7a9c940dbc2243f0746d04d (diff)
downloadnetpbm-mirror-2730bca5129bf0304d7860c49925f159e61473da.tar.gz
netpbm-mirror-2730bca5129bf0304d7860c49925f159e61473da.tar.xz
netpbm-mirror-2730bca5129bf0304d7860c49925f159e61473da.zip
Promote Development to make Release 10.64.00
git-svn-id: http://svn.code.sf.net/p/netpbm/code/advanced@2006 9d0c8265-081b-0410-96cb-a4ca84ce46f8
-rw-r--r--analyzer/pamsharpness.c18
-rw-r--r--analyzer/pamtilt.c2
-rw-r--r--analyzer/ppmhist.c52
-rw-r--r--buildtools/Makefile16
-rwxr-xr-xbuildtools/empty_depend19
-rw-r--r--buildtools/testrandom.c130
-rw-r--r--converter/other/fiasco/codec/coder.c2
-rw-r--r--converter/other/fiasco/codec/mwfa.c2
-rw-r--r--converter/other/fiasco/codec/tiling.c70
-rw-r--r--converter/other/fiasco/input/read.c2
-rw-r--r--converter/other/jbig/pnmtojbig.c2
-rw-r--r--converter/other/jpeg2000/libjasper/jpc/jpc_math.h2
-rw-r--r--converter/other/jpegtopnm.c2
-rw-r--r--converter/other/pamrgbatopng.c2
-rw-r--r--converter/other/pamtogif.c4
-rw-r--r--converter/other/pngtopam.c147
-rw-r--r--converter/other/pngx.c4
-rw-r--r--converter/other/pnmtopalm/palm.h8
-rw-r--r--converter/other/pnmtopalm/palmcolormap.c8
-rw-r--r--converter/other/pnmtopalm/pnmtopalm.c2
-rw-r--r--converter/other/pnmtopng.c2
-rw-r--r--converter/other/pstopnm.c2
-rw-r--r--converter/other/winicontopam.c4
-rw-r--r--converter/ppm/pcxtoppm.c6
-rw-r--r--converter/ppm/ppmtoilbm.c1828
-rw-r--r--converter/ppm/ppmtompeg/bitio.c2
-rw-r--r--converter/ppm/ppmtompeg/jrevdct.c2
-rw-r--r--doc/HISTORY12
-rw-r--r--doc/TESTS6
-rw-r--r--editor/pamscale.c10
-rw-r--r--editor/pamsistoaglyph.c17
-rw-r--r--editor/pnmnorm.c4
-rw-r--r--editor/pnmscalefixed.c6
-rw-r--r--editor/ppmdist.c27
-rw-r--r--lib/libpamd.c8
-rw-r--r--lib/libppmcmap.c45
-rw-r--r--lib/libppmd.c8
-rw-r--r--lib/util/mallocvar.c6
-rw-r--r--lib/util/nstring.c92
-rw-r--r--lib/util/vasprintf.c4
-rwxr-xr-xtest/Execute-Tests12
-rw-r--r--test/all-in-place.ok2
-rwxr-xr-x[-rw-r--r--]test/gif-quant-roundtrip.test0
-rwxr-xr-x[-rw-r--r--]test/pamchannel.test0
-rwxr-xr-x[-rw-r--r--]test/pgmcrater.test5
-rwxr-xr-x[-rw-r--r--]test/pgmnoise.test4
-rwxr-xr-x[-rw-r--r--]test/ppmforge.test5
-rwxr-xr-xtest/ppmhist.test2
-rwxr-xr-xtest/ppmpat.test5
-rwxr-xr-x[-rw-r--r--]test/ppmrough.test5
-rwxr-xr-x[-rw-r--r--]test/winicon-roundtrip.test0
-rw-r--r--version.mk4
52 files changed, 1459 insertions, 1170 deletions
diff --git a/analyzer/pamsharpness.c b/analyzer/pamsharpness.c
index 7a9acc6b..c5a97763 100644
--- a/analyzer/pamsharpness.c
+++ b/analyzer/pamsharpness.c
@@ -21,8 +21,9 @@
 #include <math.h>
 
 #include "pm_c_util.h"
-#include "pam.h"
+#include "mallocvar.h"
 #include "shhopt.h"
+#include "pam.h"
 
 struct cmdlineInfo {
     /* All the information the user supplied in the command line,
@@ -35,8 +36,8 @@ struct cmdlineInfo {
 
 
 static void
-parseCommandLine ( int argc, char ** argv,
-                   struct cmdlineInfo *cmdlineP ) {
+parseCommandLine(int argc, char ** argv,
+                 struct cmdlineInfo *cmdlineP) {
 /*----------------------------------------------------------------------------
    parse program command line described in Unix standard form by argc
    and argv.  Return the information in the options as *cmdlineP.  
@@ -47,7 +48,7 @@ parseCommandLine ( int argc, char ** argv,
    Note that the strings we return are stored in the storage that
    was passed to us as the argv array.  We also trash *argv.
 -----------------------------------------------------------------------------*/
-    optEntry *option_def = malloc(100*sizeof(optEntry));
+    optEntry * option_def;
         /* Instructions to pm_optParseOptions3 on how to parse our options.
          */
     optStruct3 opt;
@@ -56,6 +57,8 @@ parseCommandLine ( int argc, char ** argv,
 
     unsigned int contextSpec;
 
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
     option_def_index = 0;   /* incremented by OPTENT3 */
     OPTENT3(0, "context",       OPT_UINT,   &cmdlineP->context,       
             &contextSpec,         0 );
@@ -80,6 +83,8 @@ parseCommandLine ( int argc, char ** argv,
         cmdlineP->inputFilespec = "-";
     else
         cmdlineP->inputFilespec = argv[1];
+
+    free(option_def);
 }
 
 
@@ -89,13 +94,13 @@ computeSharpness(struct pam * const inpamP,
                  tuplen **    const tuplenarray,
                  double *     const sharpnessP) {
 
-    int row;
+    unsigned int row;
     double totsharp;
     
     totsharp = 0.0;
 
     for (row = 1; row < inpamP->height-1; ++row) {
-        int col;
+        unsigned int col;
         for (col = 1; col < inpamP->width-1; ++col) {
             int dy;
             for (dy = -1; dy <= 1; ++dy) {
@@ -150,5 +155,6 @@ main(int argc, char **argv) {
 
 	pnm_freepamarrayn(tuplenarray, &inpam);
     pm_close(ifP);
+
 	return 0;
 }
diff --git a/analyzer/pamtilt.c b/analyzer/pamtilt.c
index 8fa34791..e6a1b133 100644
--- a/analyzer/pamtilt.c
+++ b/analyzer/pamtilt.c
@@ -313,7 +313,7 @@ scoreAngle(const struct pam * const pamP,
 -----------------------------------------------------------------------------*/
     float  const radians = (float)angle/360 * 2 * M_PI;
     float  const dy      = hstep * tan(radians);
-        /* How much a line sinks due to the tilt when we move one sample
+        /* How much a line sinks because of the tilt when we move one sample
            ('hstep' columns of the image) to the right.
         */
     if (fabs(dy * hsamples) > pamP->height) {
diff --git a/analyzer/ppmhist.c b/analyzer/ppmhist.c
index 78e6d82a..2f6c9348 100644
--- a/analyzer/ppmhist.c
+++ b/analyzer/ppmhist.c
@@ -101,24 +101,60 @@ parseCommandLine(int argc, const char ** argv,
 
 
 static int
-countcompare(const void *ch1, const void *ch2) {
-    return ((colorhist_vector)ch2)->value - ((colorhist_vector)ch1)->value;
+cmpUint(unsigned int const a,
+        unsigned int const b) {
+/*----------------------------------------------------------------------------
+   Return 1 if 'a' > 'b'; -1 if 'a' is < 'b'; 0 if 'a' == 'b'.
+
+   I.e. what a libc qsort() comparison function returns.
+-----------------------------------------------------------------------------*/
+    return a > b ? 1 : a < b ? -1 : 0;
 }
 
 
+
+#ifndef LITERAL_FN_DEF_MATCH
+static qsort_comparison_fn countcompare;
+#endif
+
+
 static int
-rgbcompare(const void * arg1, const void * arg2) {
+countcompare(const void * const a,
+             const void * const b) {
+/*----------------------------------------------------------------------------
+   This is a 'qsort' collation function.
+-----------------------------------------------------------------------------*/
+    const struct colorhist_item * const histItem1P = a;
+    const struct colorhist_item * const histItem2P = b;
 
-    colorhist_vector const ch1 = (colorhist_vector) arg1;
-    colorhist_vector const ch2 = (colorhist_vector) arg2;
+    return cmpUint(histItem2P->value, histItem1P->value);
+}
+
+
+
+#ifndef LITERAL_FN_DEF_MATCH
+static qsort_comparison_fn rgbcompare;
+#endif
+
+static int
+rgbcompare(const void * const a,
+           const void * const b) {
+/*----------------------------------------------------------------------------
+   This is a 'qsort' collation function.
+-----------------------------------------------------------------------------*/
+    const struct colorhist_item * const histItem1P = a;
+    const struct colorhist_item * const histItem2P = b;
 
     int retval;
 
-    retval = (PPM_GETR(ch1->color) - PPM_GETR(ch2->color));
+    retval = cmpUint(PPM_GETR(histItem1P->color),
+                     PPM_GETR(histItem2P->color));
     if (retval == 0) {
-        retval = (PPM_GETG(ch1->color) - PPM_GETG(ch2->color));
+        retval = cmpUint(PPM_GETG(histItem1P->color),
+                         PPM_GETG(histItem2P->color));
         if (retval == 0)
-            retval = (PPM_GETB(ch1->color) - PPM_GETB(ch2->color));
+            retval = cmpUint(PPM_GETB(histItem1P->color),
+                             PPM_GETB(histItem2P->color));
     }
     return retval;
 }
diff --git a/buildtools/Makefile b/buildtools/Makefile
index 9c0ee778..e90feeca 100644
--- a/buildtools/Makefile
+++ b/buildtools/Makefile
@@ -9,11 +9,21 @@ include $(BUILDDIR)/config.mk
 MERGE_OBJECTS =
 
 # These are programs that are used by the make files:
-PROGS = libopt typegen endiangen
+BUILDPROGS = libopt typegen endiangen
+
+# Ideally, this directory would not contain anything but build tools, which
+# means they would all be built to run in the build environment, not the
+# target environment.  But we have no other convenient place for test tools,
+# so we put them here and build them for the target environment.
+TESTPROGS = testrandom
+
+PROGS = $(BUILDPROGS) $(TESTPROGS)
 
 all: $(PROGS)
 
-BINARIES =
+PORTBINARIES = $(TESTPROGS)
+BINARIES = $(PORTBINARIES)
+OBJECTS = $(BINARIES:%=%.o)
 SCRIPTS =
 
 OMIT_BUILDTOOL_RULE = 1
@@ -36,7 +46,7 @@ libopt.o: libopt.c
 typegen.o endiangen.o:%.o:%.c
 	$(CC_FOR_BUILD) -c -o $@ $(CFLAGS_FOR_BUILD) $<
 
-$(PROGS):%:%.o
+$(BUILDPROGS):%:%.o
 	$(LD_FOR_BUILD) -o $@ $(LDFLAGS_FOR_BUILD) $<
 
 distclean clean: cleanlocal
diff --git a/buildtools/empty_depend b/buildtools/empty_depend
deleted file mode 100755
index a4ba372c..00000000
--- a/buildtools/empty_depend
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/perl -w
-
-use strict;
-
-# This program turns every Makefile.depend file into an empty file,
-# so that dependencies in there can't make trouble for users trying to
-# build Netpbm.  They don't need dependencies anyway, since they're 
-# building everything and not modifying anything.
-
-# Developers should do 'make dep' to create real Makefile.depend files
-# before building
-
-my $mf_list = `find . -name Makefile.depend`;
-my @mf_list = split(/\s/, $mf_list);
-foreach (@mf_list) {
-    print "Emptying $_\n";
-    open(MF, ">$_");
-    close(MF);
-}
diff --git a/buildtools/testrandom.c b/buildtools/testrandom.c
new file mode 100644
index 00000000..3f65f0d2
--- /dev/null
+++ b/buildtools/testrandom.c
@@ -0,0 +1,130 @@
+/*=============================================================================
+                                   testrandom
+===============================================================================
+  Test for the random number generator type by generating 5 values with rand()
+  and comparing them against values in a table.
+
+  Currently only recognizes ISO glibc rand().
+
+  Options:
+    -q : quiet mode
+    -v : verbose mode : Use to generate values for new table 
+=============================================================================*/
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Exit values */
+#define EXIT_ERROR 1
+#define EXIT_UNKNOWN 80
+#define ISO_GLIBC 81
+/* 82-90: reserved */
+
+typedef enum {QUIET=0, NORMAL=1, VERBOSE=2} VerbosityLevel;
+
+/* On some Sun systems RAND_MAX is not defined */
+#ifndef RAND_MAX
+#define RAND_MAX 0
+#endif
+
+#define SEED 3791
+
+static struct { 
+    int          const type;
+        /* Exit value for this rand() function  */
+    int          const randMax;
+        /* Usually 0x7fffffff, sometimes 0x7fff */
+        /* Other values are possible; 0 means undefined */
+    unsigned int const res[5];
+        /* Sample values returned from our tests */
+    const char * const name;
+        /* Name for this rand() function */
+} rTable[2] = {
+    { ISO_GLIBC,  /* glibc rand() */ 
+      0x7fffffff, /* 31 bits */ 
+      { 217313873, 969144303, 1757357552, 1096307597, 818311031 },
+      "ISO C glibc rand() or equivalent" },
+    
+    /* Insert additional entries here */
+    
+    { 0,   /* terminating code */
+      0,
+      {0, 0, 0, 0, 0}, NULL  /* unknown type */}
+};
+
+
+
+static void
+parseCommandLine(int              const argc,
+                 const char *     const argv[],
+                 VerbosityLevel * const verbosityP) {
+
+    *verbosityP = NORMAL; /* Initial value */
+
+    if (argc == 2) {
+        if (argv[1][0] == '-' && argv[1][2] == '\0') {
+            switch ( argv[1][1] ) {
+            case 'v' : *verbosityP = VERBOSE; break;
+            case 'q' : *verbosityP = QUIET  ; break;
+            default :  fprintf (stderr,
+                                "Error: Unrecognized argument: %s\n", argv[1]);
+                exit (EXIT_ERROR);
+            }
+        } 
+    }
+    if (argc > 2 ) {
+        fprintf (stderr, "Error: Too many arguments.\n");
+        exit (EXIT_ERROR);
+    }
+}
+
+
+
+int
+main(int const argc, const char * const argv[]) {
+
+    unsigned int i;
+    unsigned int res[5];
+    VerbosityLevel verbosity;
+
+    parseCommandLine(argc, argv, &verbosity);
+
+    if (verbosity == VERBOSE) {
+        if (RAND_MAX > 0)
+            fprintf(stderr, "RAND_MAX = 0x%x (%d)\n", RAND_MAX, RAND_MAX);
+        else
+            fprintf(stderr, "RAND_MAX is undefined\n");
+    }
+
+    /* Set seed for pseudo-random number generator */
+    if (verbosity == VERBOSE)
+        fprintf(stderr, "Generating samples. Seed=%u\n", SEED);
+
+    srand(SEED);
+
+    /*  Generate five samples and store in array res[] */
+    for (i = 0; i < 5; ++i) {
+        res[i] = rand();
+        if (verbosity == VERBOSE)
+            fprintf (stderr, "%d\n",res[i]);
+    }
+
+    /*  Look for a match in table */
+    for (i = 0; rTable[i].type != 0; ++i) {
+        if (rTable[i].randMax == RAND_MAX && rTable[i].res[0] == res[0] &&
+            rTable[i].res[1] == res[1] &&    rTable[i].res[2] == res[2] &&
+            rTable[i].res[3] == res[3] &&    rTable[i].res[4] == res[4]) {
+            if (verbosity != QUIET)
+                fprintf(stderr,
+                        "Random number generator is %s.\n", rTable[i].name);
+
+            exit(rTable[i].type);
+        }
+    }
+    /* No matches */
+    if (verbosity != QUIET)   
+        fprintf(stderr, "Random number generator is of unknown type.\n");
+    exit(EXIT_UNKNOWN);
+}
+
+
+
diff --git a/converter/other/fiasco/codec/coder.c b/converter/other/fiasco/codec/coder.c
index f7abfd00..94e367dd 100644
--- a/converter/other/fiasco/codec/coder.c
+++ b/converter/other/fiasco/codec/coder.c
@@ -273,7 +273,7 @@ alloc_coder (char const * const * const inputname,
     if (c->options.lc_max_level >= wi->level - c->tiling->exponent)
     {
         message ("'max_level' changed from %d to %d "
-                 "due to image tiling level.",
+                 "because of image tiling level.",
                  c->options.lc_max_level, wi->level - c->tiling->exponent - 1);
         c->options.lc_max_level = wi->level - c->tiling->exponent - 1;
     }
diff --git a/converter/other/fiasco/codec/mwfa.c b/converter/other/fiasco/codec/mwfa.c
index c695f6bf..43a7dae2 100644
--- a/converter/other/fiasco/codec/mwfa.c
+++ b/converter/other/fiasco/codec/mwfa.c
@@ -438,7 +438,7 @@ find_B_frame_mc (word_t *mcpe, real_t price, range_t *range,
    else					/* local exhaustive search */
    {
       /*
-       *  Keep forward and backward mv due to time constraints
+       *  Keep forward and backward mv because of time constraints
        */
 
       ifx = fx;
diff --git a/converter/other/fiasco/codec/tiling.c b/converter/other/fiasco/codec/tiling.c
index 83eb8b29..89fe3111 100644
--- a/converter/other/fiasco/codec/tiling.c
+++ b/converter/other/fiasco/codec/tiling.c
@@ -29,22 +29,7 @@
 #include "wfalib.h"
 #include "tiling.h"
 
-/*****************************************************************************
 
-				prototypes
-  
-*****************************************************************************/
-
-static int
-cmpdecvar (const void *value1, const void *value2);
-static int
-cmpincvar (const void *value1, const void *value2);
-
-/*****************************************************************************
-
-				public code
-  
-*****************************************************************************/
 
 typedef struct var_list
 {
@@ -52,6 +37,38 @@ typedef struct var_list
    real_t variance;			/* variance of tile */
 } var_list_t;
 
+#ifndef LITERAL_FN_DEF_MATCH
+static qsort_comparison_fn cmpincvar;
+#endif
+
+static int
+cmpincvar(const void * const value1,
+          const void * const value2) {
+/*----------------------------------------------------------------------------
+  Sorts by increasing variances (quicksort sorting function)
+-----------------------------------------------------------------------------*/
+    return
+        ((var_list_t *) value1)->variance - ((var_list_t *) value2)->variance;
+}
+
+
+
+#ifndef LITERAL_FN_DEF_MATCH
+static qsort_comparison_fn cmpdecvar;
+#endif
+
+static int
+cmpdecvar(const void * const value1,
+          const void * const value2) {
+/*----------------------------------------------------------------------------
+  Sorts by decreasing variances (quicksort sorting function).
+-----------------------------------------------------------------------------*/
+    return
+        ((var_list_t *) value2)->variance - ((var_list_t *) value1)->variance;
+}
+
+
+
 tiling_t *
 alloc_tiling (fiasco_tiling_e method, unsigned tiling_exponent,
 	      unsigned image_level)
@@ -214,26 +231,3 @@ perform_tiling (const image_t *image, tiling_t *tiling)
    }
 }
 
-/*****************************************************************************
-
-				private code
-  
-*****************************************************************************/
-
-static int
-cmpincvar (const void *value1, const void *value2)
-/*
- *  Sorts by increasing variances (quicksort sorting function).
- */
-{
-  return ((var_list_t *) value1)->variance - ((var_list_t *) value2)->variance;
-}
-
-static int
-cmpdecvar (const void *value1, const void *value2)
-/*
- *  Sorts by decreasing variances (quicksort sorting function).
- */
-{
-  return ((var_list_t *) value2)->variance - ((var_list_t *) value1)->variance;
-}
diff --git a/converter/other/fiasco/input/read.c b/converter/other/fiasco/input/read.c
index 9ac204f6..e6e2d7e8 100644
--- a/converter/other/fiasco/input/read.c
+++ b/converter/other/fiasco/input/read.c
@@ -397,7 +397,7 @@ read_next_wfa (wfa_t *wfa, bitfile_t *input)
 
    /*
     *  Compute domain pool.
-    *  Large images have not been used due to image tiling.
+    *  Large images have not been used because of image tiling.
     */
    {
       unsigned state;
diff --git a/converter/other/jbig/pnmtojbig.c b/converter/other/jbig/pnmtojbig.c
index 9dbef3fa..f5188c7b 100644
--- a/converter/other/jbig/pnmtojbig.c
+++ b/converter/other/jbig/pnmtojbig.c
@@ -195,7 +195,7 @@ readPnm(FILE *            const fin,
     free(image);
     
     /* Invert the image if it is just one plane.  See top of this file
-       for an explanation why.  Due to the separate handling of PBM,
+       for an explanation why.  Because of the separate handling of PBM,
        this is for exceptional PGM files.  
     */
 
diff --git a/converter/other/jpeg2000/libjasper/jpc/jpc_math.h b/converter/other/jpeg2000/libjasper/jpc/jpc_math.h
index e343bab1..77df0c62 100644
--- a/converter/other/jpeg2000/libjasper/jpc/jpc_math.h
+++ b/converter/other/jpeg2000/libjasper/jpc/jpc_math.h
@@ -135,7 +135,7 @@
 #define	JPC_CEILDIVPOW2(x, y) \
 	(assert(x >= 0 && y >= 0), ((x) + (1 << (y)) - 1) >> (y))
 /* JPC_CEILDIVPOW2U is for unsigned arguments (JPC_CEILDIVPOW2 would generate
-   compiler warnings due to its superfluous >= 0 check)
+   compiler warnings because of its superfluous >= 0 check)
 */
 #define	JPC_CEILDIVPOW2U(x, y) \
 	(((x) + (1 << (y)) - 1) >> (y))
diff --git a/converter/other/jpegtopnm.c b/converter/other/jpegtopnm.c
index cbac0a09..f09cd04f 100644
--- a/converter/other/jpegtopnm.c
+++ b/converter/other/jpegtopnm.c
@@ -582,7 +582,7 @@ print_verbose_info_about_header(struct jpeg_decompress_struct const cinfo){
                colorspace_name(cinfo.jpeg_color_space));
 
     /* Note that raw information about marker, including marker type code,
-       was already printed by the jpeg library, due to the jpeg library
+       was already printed by the jpeg library, because of the jpeg library
        trace level >= 1.  Our job is to interpret it a little bit.
     */
     if (cinfo.marker_list)
diff --git a/converter/other/pamrgbatopng.c b/converter/other/pamrgbatopng.c
index 7a7a397a..07a5181b 100644
--- a/converter/other/pamrgbatopng.c
+++ b/converter/other/pamrgbatopng.c
@@ -1,6 +1,6 @@
 #include <stdio.h>
 #include <stdlib.h>
-/* Due to poor design of libpng, you must not #include <setjmp.h> before
+/* Because of poor design of libpng, you must not #include <setjmp.h> before
 <png.h>.  Compile failure results.
 */
 #include <png.h>
diff --git a/converter/other/pamtogif.c b/converter/other/pamtogif.c
index 5b9c219c..aabf7fc2 100644
--- a/converter/other/pamtogif.c
+++ b/converter/other/pamtogif.c
@@ -35,7 +35,7 @@ typedef int stringCode;
        changes throughout the image.
 
        A variable of this type sometimes has the value -1 instead of
-       a string code due to cheesy programming.
+       a string code because of cheesy programming.
 
        Ergo, this data structure must be signed and at least BITS bits
        wide plus sign bit.
@@ -893,7 +893,7 @@ lzw_create(FILE *       const ofP,
     
        Above that we use a table with 4096 slots plus 20% extra.
        When this is not enough the clear code is emitted.
-       Due to the extra 20% the table itself never fills up.
+       Because of the extra 20% the table itself never fills up.
        
        lzw.hsize and lzw.hshift stay constant through the image.
 
diff --git a/converter/other/pngtopam.c b/converter/other/pngtopam.c
index 14b38987..e6e68587 100644
--- a/converter/other/pngtopam.c
+++ b/converter/other/pngtopam.c
@@ -22,7 +22,7 @@
 #include <math.h>
 #include <float.h>
 #include <png.h>
-/* Due to a design error in png.h, you must not #include <setjmp.h> before
+/* Becaues of a design error in png.h, you must not #include <setjmp.h> before
    <png.h>.  If you do, png.h won't compile.
 */
 #include <setjmp.h>
@@ -38,15 +38,21 @@
 
 enum AlphaHandling {ALPHA_NONE, ALPHA_ONLY, ALPHA_MIX, ALPHA_IN};
 
+typedef struct {
+    bool needCorrection;
+    double gamma;
+} GammaCorrection;
+
 struct CmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
-    const char *inputFilespec;  /* '-' if stdin */
+    const char * inputFileName;  /* '-' if stdin */
     unsigned int verbose;
     enum AlphaHandling alpha;
     const char * background;
-    float gamma;  /* -1.0 means unspecified */
+    unsigned int gammaSpec;
+    float gamma;
     const char * text;
     unsigned int time;
     unsigned int byrow;
@@ -79,7 +85,7 @@ parseCommandLine(int                  argc,
     unsigned int option_def_index;
 
     unsigned int alphaSpec, alphapamSpec, mixSpec,
-        backgroundSpec, gammaSpec, textSpec;
+        backgroundSpec, textSpec;
 
     MALLOCARRAY(option_def, 100);
 
@@ -95,7 +101,7 @@ parseCommandLine(int                  argc,
     OPTENT3(0, "background",  OPT_STRING, &cmdlineP->background,
             &backgroundSpec,          0);
     OPTENT3(0, "gamma",       OPT_FLOAT,  &cmdlineP->gamma,
-            &gammaSpec,               0);
+            &cmdlineP->gammaSpec,     0);
     OPTENT3(0, "text",        OPT_STRING, &cmdlineP->text,
             &textSpec,                0);
     OPTENT3(0, "time",        OPT_FLAG,   NULL,                  
@@ -128,16 +134,13 @@ parseCommandLine(int                  argc,
     if (!backgroundSpec)
         cmdlineP->background = NULL;
 
-    if (!gammaSpec)
-        cmdlineP->gamma = -1.0;
-
     if (!textSpec)
         cmdlineP->text = NULL;
 
     if (argc-1 < 1)
-        cmdlineP->inputFilespec = "-";
+        cmdlineP->inputFileName = "-";
     else if (argc-1 == 1)
-        cmdlineP->inputFilespec = argv[1];
+        cmdlineP->inputFileName = argv[1];
     else
         pm_error("Program takes at most one argument: input file name.  "
             "you specified %d", argc-1);
@@ -199,29 +202,28 @@ pngColorEqual(pngcolor const comparand,
 
 
 static png_uint_16
-gammaCorrect(png_uint_16 const v,
-             float       const g,
-             png_uint_16 const maxval) {
+gammaCorrect(png_uint_16     const uncorrected,
+             GammaCorrection const gamma,
+             png_uint_16     const maxval) {
 
-    if (g != -1.0)
+    if (gamma.needCorrection) {
+        double const uncorrectedN = (double) uncorrected / maxval;
         return (png_uint_16)
-            ROUNDU(pow((double) v / maxval, (1.0 / g)) * maxval);
-    else
-        return v;
+            ROUNDU(pow(uncorrectedN, (1.0 / gamma.gamma)) * maxval);
+    } else
+        return uncorrected;
 }
 
 
 
 static pngcolor
-gammaCorrectColor(pngcolor    const color,
-                  double      const gamma,
-                  png_uint_16 const maxval) {
+gammaCorrectColor(pngcolor        const color,
+                  GammaCorrection const gamma,
+                  png_uint_16     const maxval) {
 
     pngcolor retval;
 
     retval.r = gammaCorrect(color.r, gamma, maxval);
-    retval.g = gammaCorrect(color.g, gamma, maxval);
-    retval.b = gammaCorrect(color.b, gamma, maxval);
 
     return retval;
 }
@@ -744,16 +746,16 @@ transColor(struct pngx * const pngxP) {
 
 
 static bool
-isTransparentColor(pngcolor      const color,
-                   struct pngx * const pngxP,
-                   double        const totalgamma) {
+isTransparentColor(pngcolor        const color,
+                   struct pngx *   const pngxP,
+                   GammaCorrection const gamma) {
 /*----------------------------------------------------------------------------
    Return TRUE iff pixels of color 'color' are supposed to be transparent
    everywhere they occur.  Assume it's an RGB image.
 
-   'color' has been gamma-corrected and 'totalgamma' is the gamma value that
-   was used for that (we need to know that because *pngxP identifies the
-   color that is supposed to be transparent in _not_ gamma-corrected form!).
+   'gamma' indicats what gamma correction has been applied to 'color' (we need
+   to know that because *pngxP identifies the color that is supposed to be
+   transparent in _not_ gamma-corrected form!).
 -----------------------------------------------------------------------------*/
     bool retval;
 
@@ -776,13 +778,13 @@ isTransparentColor(pngcolor      const color,
     
         switch (pngx_colorType(pngxP)) {
         case PNG_COLOR_TYPE_GRAY:
-            retval = color.r == gammaCorrect(transColor16.gray, totalgamma,
+            retval = color.r == gammaCorrect(transColor16.gray, gamma,
                                              pngxP->maxval);
             break;
         default: {
             pngcolor const transColor = pngcolorFrom16(transColor16);
             retval = pngColorEqual(color,
-                                   gammaCorrectColor(transColor, totalgamma,
+                                   gammaCorrectColor(transColor, gamma,
                                                      pngxP->maxval));
         }
         }
@@ -795,12 +797,32 @@ isTransparentColor(pngcolor      const color,
 
 
 static void
-setupGammaCorrection(struct pngx * const pngxP,
-                     float         const displaygamma,
-                     float *       const totalgammaP) {
+setupGammaCorrection(struct pngx *     const pngxP,
+                     bool              const screenGammaIsKnown,
+                     float             const screenGamma,
+                     GammaCorrection * const gammaCorrectionP) {
+/*----------------------------------------------------------------------------
+   Set up to have values from the PNG gamma-corrected.
 
-    if (displaygamma == -1.0)
-        *totalgammaP = -1.0;
+   Return as *gammaCorrectionP the correction necessary and tell the
+   libpng image reader *pngxP to do that same correction - on the pixels
+   only, as it can't do it on anything else (hence, Caller will have to
+   use *gammaCorrectionP to do it).
+
+   'screenGammaIsKnown' means we know what the screen gamma is, and it is
+   'screenGamma'.  If we don't know what the screen gamma is, gamma 
+   correction is not possible, so we set up for no gamma correction.
+
+   The gamma correction we ordain is a combination of the image gamma,
+   recorded in the PNG input and represented by *pngxP, and the screen gamma.
+
+   Note that "screen gamma" is a characteristic of both the display and the
+   viewing conditions.  There are also "display gamma" and "viewing gamma,"
+   respectively, but we don't care about the breakdown.  In a dimly lit room,
+   viewing gamma is 1 and screen gamma is the same as the display gamma.
+-----------------------------------------------------------------------------*/
+    if (!screenGammaIsKnown)
+        gammaCorrectionP->needCorrection = false;
     else {
         float imageGamma;
         if (pngx_chunkIsPresent(pngxP, PNG_INFO_gAMA))
@@ -811,23 +833,26 @@ setupGammaCorrection(struct pngx * const pngxP,
             imageGamma = 1.0;
         }
 
-        if (fabs(displaygamma * imageGamma - 1.0) < .01) {
-            *totalgammaP = -1.0;
+        if (fabs(screenGamma * imageGamma - 1.0) < .01) {
+            gammaCorrectionP->needCorrection = false;
             if (verbose)
                 pm_message("image gamma %4.2f matches "
-                           "display gamma %4.2f.  No conversion.",
-                           imageGamma, displaygamma);
+                           "screen gamma %4.2f.  No conversion.",
+                           imageGamma, screenGamma);
         } else {
-            pngx_setGamma(pngxP, displaygamma, imageGamma);
-            *totalgammaP = imageGamma * displaygamma;
+            pngx_setGamma(pngxP, screenGamma, imageGamma);
+
+            gammaCorrectionP->needCorrection = true;
+            gammaCorrectionP->gamma = imageGamma * screenGamma;
             /* In case of gamma-corrections, sBIT's as in the
                PNG-file are not valid anymore 
             */
             pngx_removeChunk(pngxP, PNG_INFO_sBIT);
             if (verbose)
                 pm_message("image gamma is %4.2f, "
-                           "converted for display gamma of %4.2f",
-                           imageGamma, displaygamma);
+                           "display gamma is %4.2f; "
+                           "combined gamma is %4.2f",
+                           imageGamma, screenGamma, gammaCorrectionP->gamma);
         }
     }
 }
@@ -1152,11 +1177,11 @@ determineOutputType(struct pngx *       const pngxP,
 
 
 static void
-getBackgroundColor(struct pngx * const pngxP,
-                   const char *  const requestedColor,
-                   float         const totalgamma,
-                   xelval        const maxval,
-                   pngcolor *    const bgColorP) {
+getBackgroundColor(struct pngx *   const pngxP,
+                   const char *    const requestedColor,
+                   GammaCorrection const gamma,
+                   xelval          const maxval,
+                   pngcolor *      const bgColorP) {
 /*----------------------------------------------------------------------------
    Figure out what the background color should be.  If the user requested
    a particular color ('requestedColor' not null), that's the one.
@@ -1183,14 +1208,14 @@ getBackgroundColor(struct pngx * const pngxP,
         case PNG_COLOR_TYPE_GRAY:
         case PNG_COLOR_TYPE_GRAY_ALPHA:
             bgColorP->r = bgColorP->g = bgColorP->b = 
-                gammaCorrect(background.gray, totalgamma, pngxP->maxval);
+                gammaCorrect(background.gray, gamma, pngxP->maxval);
             break;
         case PNG_COLOR_TYPE_PALETTE: {
             struct pngx_plte const palette = pngx_plte(pngxP);
             png_color const rawBgcolor = 
                 palette.palette[background.index];
             *bgColorP = gammaCorrectColor(pngcolorFromByte(rawBgcolor),
-                                          totalgamma, pngxP->maxval);
+                                          gamma, pngxP->maxval);
         }
         break;
         case PNG_COLOR_TYPE_RGB:
@@ -1198,7 +1223,7 @@ getBackgroundColor(struct pngx * const pngxP,
             png_color_16 const rawBgcolor = background;
             
             *bgColorP = gammaCorrectColor(pngcolorFrom16(rawBgcolor),
-                                          totalgamma, pngxP->maxval);
+                                          gamma, pngxP->maxval);
         }
         break;
         }
@@ -1262,7 +1287,7 @@ makeTupleRow(const struct pam *  const pamP,
              const png_byte *    const pngRasterRow,
              pngcolor            const bgColor,
              enum AlphaHandling  const alphaHandling,
-             double              const totalgamma) {
+             GammaCorrection     const gamma) {
 /*----------------------------------------------------------------------------
    Convert a raster row as supplied by libpng, at 'pngRasterRow' and
    described by *pngxP, to a libpam-style tuple row at 'tupleRow'.
@@ -1284,7 +1309,7 @@ makeTupleRow(const struct pam *  const pamP,
             fgColor.r = fgColor.g = fgColor.b = GET_PNG_VAL(pngPixelP);
             setTuple(pamP, tuplerow[col], fgColor, bgColor, alphaHandling,
                      pngxP,
-                     isTransparentColor(fgColor, pngxP, totalgamma) ?
+                     isTransparentColor(fgColor, pngxP, gamma) ?
                      0 : pngxP->maxval);
         }
         break;
@@ -1324,7 +1349,7 @@ makeTupleRow(const struct pam *  const pamP,
             fgColor.b = GET_PNG_VAL(pngPixelP);
             setTuple(pamP, tuplerow[col], fgColor, bgColor, alphaHandling,
                      pngxP,
-                     isTransparentColor(fgColor, pngxP, totalgamma) ?
+                     isTransparentColor(fgColor, pngxP, gamma) ?
                      0 : pngxP->maxval);
         }
         break;
@@ -1382,7 +1407,7 @@ writeNetpbm(struct pam *        const pamP,
             Reader *            const rasterReaderP,
             pngcolor            const bgColor,
             enum AlphaHandling  const alphaHandling,
-            double              const totalgamma) {
+            GammaCorrection     const gamma) {
 /*----------------------------------------------------------------------------
    Write a Netpbm image of either the image or the alpha mask, according to
    'alphaHandling' that is in the PNG image described by *pngxP, reading
@@ -1410,7 +1435,7 @@ writeNetpbm(struct pam *        const pamP,
         assert(pngRow);
 
         makeTupleRow(pamP, tuplerow, pngxP, pngRow, bgColor,
-                     alphaHandling, totalgamma);
+                     alphaHandling, gamma);
 
         pnm_writepamrow(pamP, tuplerow);
     }
@@ -1427,7 +1452,7 @@ convertpng(FILE *             const ifP,
 
     Reader * rasterReaderP;
     pngcolor bgColor;
-    float totalgamma;
+    GammaCorrection gamma;
     struct pam pam;
     jmp_buf jmpbuf;
     struct pngx * pngxP;
@@ -1451,11 +1476,11 @@ convertpng(FILE *             const ifP,
 
     warnNonsquarePixels(pngxP, errorLevelP);
 
-    setupGammaCorrection(pngxP, cmdline.gamma, &totalgamma);
+    setupGammaCorrection(pngxP, cmdline.gammaSpec, cmdline.gamma, &gamma);
 
     setupSignificantBits(pngxP, cmdline.alpha, errorLevelP);
 
-    getBackgroundColor(pngxP, cmdline.background, totalgamma, pngxP->maxval,
+    getBackgroundColor(pngxP, cmdline.background, gamma, pngxP->maxval,
                        &bgColor);
   
     pam.size        = sizeof(pam);
@@ -1473,7 +1498,7 @@ convertpng(FILE *             const ifP,
         reader_createRowByRow(pngxP, ifP) : reader_createAllAtOnce(pngxP, ifP);
 
     writeNetpbm(&pam, pngxP, rasterReaderP, bgColor,
-                cmdline.alpha, totalgamma);
+                cmdline.alpha, gamma);
 
     reader_destroy(rasterReaderP);
 
@@ -1500,7 +1525,7 @@ main(int argc, const char *argv[]) {
 
     verbose = cmdline.verbose;
 
-    ifP = pm_openr(cmdline.inputFilespec);
+    ifP = pm_openr(cmdline.inputFileName);
 
     if (cmdline.text)
         tfP = pm_openw(cmdline.text);
diff --git a/converter/other/pngx.c b/converter/other/pngx.c
index b33f5ab8..8d7b7c70 100644
--- a/converter/other/pngx.c
+++ b/converter/other/pngx.c
@@ -357,10 +357,10 @@ pngx_setGama(struct pngx * const pngxP,
 
 void
 pngx_setGamma(struct pngx * const pngxP,
-              float         const displayGamma,
+              float         const screenGamma,
               float         const imageGamma) {
 
-    png_set_gamma(pngxP->png_ptr, displayGamma, imageGamma);
+    png_set_gamma(pngxP->png_ptr, screenGamma, imageGamma);
 }
 
 
diff --git a/converter/other/pnmtopalm/palm.h b/converter/other/pnmtopalm/palm.h
index 170c8cec..718a66cf 100644
--- a/converter/other/pnmtopalm/palm.h
+++ b/converter/other/pnmtopalm/palm.h
@@ -44,13 +44,9 @@ typedef struct {
 
 typedef Colormap_s * Colormap;
 
-int
-palmcolor_compare_indices(const void * const p1,
-                          const void * const p2);
+qsort_comparison_fn palmcolor_compare_indices;
 
-int
-palmcolor_compare_colors(const void * const p1,
-                         const void * const p2);
+qsort_comparison_fn palmcolor_compare_colors;
 
 Colormap
 palmcolor_build_custom_8bit_colormap(unsigned int const rows,
diff --git a/converter/other/pnmtopalm/palmcolormap.c b/converter/other/pnmtopalm/palmcolormap.c
index a1a1cec1..0f47558c 100644
--- a/converter/other/pnmtopalm/palmcolormap.c
+++ b/converter/other/pnmtopalm/palmcolormap.c
@@ -10,7 +10,9 @@
 int
 palmcolor_compare_indices(const void * const p1,
                           const void * const p2) {
-
+/*----------------------------------------------------------------------------
+   This is a 'qsort' collation function.
+-----------------------------------------------------------------------------*/
     if ((*((Color) p1) & 0xFF000000) < (*((Color) p2) & 0xFF000000))
         return -1;
     else if ((*((Color) p1) & 0xFF000000) > (*((Color) p2) & 0xFF000000))
@@ -24,7 +26,9 @@ palmcolor_compare_indices(const void * const p1,
 int
 palmcolor_compare_colors(const void * const p1,
                          const void * const p2) {
-
+/*----------------------------------------------------------------------------
+   This is a 'qsort' collation function.
+-----------------------------------------------------------------------------*/
     unsigned long const val1 = *((const unsigned long *) p1) & 0xFFFFFF;
     unsigned long const val2 = *((const unsigned long *) p2) & 0xFFFFFF;
 
diff --git a/converter/other/pnmtopalm/pnmtopalm.c b/converter/other/pnmtopalm/pnmtopalm.c
index 6d34bb9b..67a17e54 100644
--- a/converter/other/pnmtopalm/pnmtopalm.c
+++ b/converter/other/pnmtopalm/pnmtopalm.c
@@ -497,7 +497,7 @@ writeDummy() {
    Write a dummy Palm Bitmap header.  This is a 16 byte header, of
    type version 1 and with (only) pixelSize set to 0xFF.
 
-   An old viewer will see this as invalid due to the pixelSize, and stop
+   An old viewer will see this as invalid because of the pixelSize, and stop
    reading the stream.  A new viewer will recognize this for what it is
    (a dummy header designed to stop old viewers from reading further in
    the stream) and continue reading the stream.  Presumably, what follows
diff --git a/converter/other/pnmtopng.c b/converter/other/pnmtopng.c
index bcb94612..154ca279 100644
--- a/converter/other/pnmtopng.c
+++ b/converter/other/pnmtopng.c
@@ -59,7 +59,7 @@
 #include <string.h> /* strcat() */
 #include <limits.h>
 #include <png.h>
-/* Due to a design error in png.h, you must not #include <setjmp.h> before
+/* Because of a design error in png.h, you must not #include <setjmp.h> before
    <png.h>.  If you do, png.h won't compile.
 */
 #include <setjmp.h> 
diff --git a/converter/other/pstopnm.c b/converter/other/pstopnm.c
index 3704841b..f4081464 100644
--- a/converter/other/pstopnm.c
+++ b/converter/other/pstopnm.c
@@ -883,7 +883,7 @@ executeGhostscript(char                    const pstrans[],
                 pm_error("Ghostscript failed.  Exit code=%d\n", 
                          WEXITSTATUS(gsTermStatus));
             else if (WIFSIGNALED(gsTermStatus))
-                pm_error("Ghostscript process died due to a signal %d.",
+                pm_error("Ghostscript process died because of a signal %d.",
                          WTERMSIG(gsTermStatus));
             else 
                 pm_error("Ghostscript process died with exit code %d", 
diff --git a/converter/other/winicontopam.c b/converter/other/winicontopam.c
index 9bee8b3c..f41a8db3 100644
--- a/converter/other/winicontopam.c
+++ b/converter/other/winicontopam.c
@@ -182,6 +182,10 @@ u32_xx(const unsigned char * const buf,
 
 
 
+#ifndef LITERAL_FN_DEF_MATCH
+static qsort_comparison_fn cmpfn;
+#endif
+
 static int
 cmpfn(const void * const aP,
       const void * const bP) {
diff --git a/converter/ppm/pcxtoppm.c b/converter/ppm/pcxtoppm.c
index 8b8ee7d5..e252ba22 100644
--- a/converter/ppm/pcxtoppm.c
+++ b/converter/ppm/pcxtoppm.c
@@ -129,9 +129,9 @@ struct pcxHeader {
     short Planes;
     short BitsPerPixel;
     short BytesPerLine;
-        /* Number of decompressed bytes each plane of each row of the image 
-           takes.  Due to padding (this is always an even number), there may
-           be garbage on the right end that isn't part of the image.
+        /* Number of decompressed bytes each plane of each row of the image
+           takes.  Because of padding (this is always an even number), there
+           may be garbage on the right end that isn't part of the image.
         */
     short PaletteInfo;
     short HorizontalResolution;
diff --git a/converter/ppm/ppmtoilbm.c b/converter/ppm/ppmtoilbm.c
index 69784b37..e1144579 100644
--- a/converter/ppm/ppmtoilbm.c
+++ b/converter/ppm/ppmtoilbm.c
@@ -106,31 +106,6 @@
 
 #define INT16MAX 32767
 
-static void put_big_short ARGS((short s));
-static void put_big_long ARGS((long l));
-#define put_byte(b)     (void)(putc((unsigned char)(b), stdout))
-static void write_bytes ARGS((unsigned char *buffer, int bytes));
-static void ppm_to_ham ARGS((FILE *fp, int cols, int rows, int maxval, pixel *colormap, int colors, int cmapmaxval, int hamplanes));
-static void ppm_to_deep ARGS((FILE *fp, int cols, int rows, int maxval, int bitspercolor));
-static void ppm_to_dcol ARGS((FILE *fp, int cols, int rows, int maxval, DirectColor *dcol));
-static void ppm_to_rgb8 ARGS((FILE *fp, int cols, int rows, int maxval));
-static void ppm_to_rgbn ARGS((FILE *fp, int cols, int rows, int maxval));
-static void ppm_to_std ARGS((FILE *fp, int cols, int rows, int maxval, pixel *colormap, int colors, int cmapmaxval, int maxcolors, int nPlanes));
-static void ppm_to_cmap ARGS((pixel *colormap, int colors, int maxval));
-static void write_bmhd ARGS((int cols, int rows, int nPlanes));
-static void write_cmap ARGS((pixel *colormap, int colors, int maxval));
-static long encode_row ARGS((FILE *outfile, rawtype *rawrow, int cols, int nPlanes));
-static long encode_maskrow ARGS((FILE *outfile, rawtype *rawrow, int cols));
-static int compress_row ARGS((int bytes));
-static void store_bodyrow ARGS((unsigned char *row, int len));
-static int runbyte1 ARGS((int bytes));
-static pixel * next_pixrow ARGS((FILE *fp, int row));
-static int * make_val_table ARGS((int oldmaxval, int newmaxval));
-static void init_read ARGS((FILE *fp, int *colsP, int *rowsP, pixval *maxvalP, int *formatP, int readall));
-static void write_body_rows ARGS((void));
-static void write_camg ARGS((void));
-static int  length_of_text_chunks ARGS((void));
-static void write_text_chunks ARGS((void));
 #define PAD(n)      (ODD(n) ? 1 : 0)    /* pad to a word */
 
 
@@ -183,25 +158,430 @@ static short gen_camg = 0;      /* write CAMG chunk */
 #define WORSTCOMPR(bytes)       ((bytes) + (bytes)/128 + 1)
 #define DO_COMPRESS             (compmethod != cmpNone)
 
+#define NEWDEPTH(pix, table) PPM_ASSIGN((pix), (table)[PPM_GETR(pix)], (table)[PPM_GETG(pix)], (table)[PPM_GETB(pix)])
 
-/***** parse options and figure out what kind of ILBM to write *****/
+#define putByte(b)     (void)(putc((unsigned char)(b), stdout))
 
-static int get_int_val ARGS((char *string, char *option, int bot, int top));
-static int get_compr_method ARGS((char *string));
-static int get_mask_type ARGS((char *string));
-static int get_hammap_mode ARGS((char *string));
 
 
+/************ other utility functions ************/
 
-#define NEWDEPTH(pix, table) PPM_ASSIGN((pix), (table)[PPM_GETR(pix)], (table)[PPM_GETG(pix)], (table)[PPM_GETB(pix)])
 
 
 static void
-report_too_many_colors(int         const ifmode,
-                       int         const maxplanes,
-                       int         const hamplanes,
-                       DirectColor const dcol,
-                       int         const deepbits) {
+writeBytes(unsigned char * const buffer,
+           int             const bytes) {
+
+    if( fwrite(buffer, 1, bytes, stdout) != bytes )
+        pm_error("write error");
+}
+
+
+
+static int *
+makeValTable(int const oldmaxval,
+             int const newmaxval) {
+
+    unsigned int i;
+    int * table;
+
+    MALLOCARRAY_NOFAIL(table, oldmaxval + 1);
+    for (i = 0; i <= oldmaxval; ++i)
+        table[i] = ROUNDDIV(i * newmaxval, oldmaxval);
+
+    return table;
+}
+
+
+
+static int  gFormat;
+static int  gCols;
+static int  gMaxval;
+
+static void
+initRead(FILE *   const fp,
+         int *    const colsP,
+         int *    const rowsP,
+         pixval * const maxvalP,
+         int *    const formatP,
+         int      const readall) {
+
+    ppm_readppminit(fp, colsP, rowsP, maxvalP, formatP);
+
+    if( *rowsP >INT16MAX || *colsP >INT16MAX )
+      pm_error ("Input image is too large.");
+
+    if( readall ) {
+        int row;
+
+        pixels = ppm_allocarray(*colsP, *rowsP);
+        for( row = 0; row < *rowsP; row++ )
+            ppm_readppmrow(fp, pixels[row], *colsP, *maxvalP, *formatP);
+        /* pixels = ppm_readppm(fp, colsP, rowsP, maxvalP); */
+    }
+    else {
+        pixrow = ppm_allocrow(*colsP);
+    }
+    gCols = *colsP;
+    gMaxval = *maxvalP;
+    gFormat = *formatP;
+}
+
+
+
+static pixel *
+nextPixrow(FILE * const fp,
+           int    const row) {
+
+    if( pixels )
+        pixrow = pixels[row];
+    else {
+        ppm_readppmrow(fp, pixrow, gCols, gMaxval, gFormat);
+    }
+    if( maskrow ) {
+        int col;
+
+        if( maskfile )
+            pbm_readpbmrow(maskfile, maskrow, maskcols, maskformat);
+        else {
+            for( col = 0; col < gCols; col++ )
+                maskrow[col] = PBM_BLACK;
+        }
+        if( transpColor ) {
+            for( col = 0; col < gCols; col++ )
+                if( PPM_EQUAL(pixrow[col], *transpColor) )
+                    maskrow[col] = PBM_WHITE;
+        }
+    }
+    return pixrow;
+}
+
+
+
+/************ ILBM functions ************/
+
+
+
+static int
+lengthOfTextChunks(void) {
+
+    int len, n;
+
+    len = 0;
+    if( anno_chunk ) {
+        n = strlen(anno_chunk);
+        len += 4 + 4 + n + PAD(n);      /* ID chunksize text */
+    }
+    if( auth_chunk ) {
+        n = strlen(auth_chunk);
+        len += 4 + 4 + n + PAD(n);      /* ID chunksize text */
+    }
+    if( name_chunk ) {
+        n = strlen(name_chunk);
+        len += 4 + 4 + n + PAD(n);      /* ID chunksize text */
+    }
+    if( copyr_chunk ) {
+        n = strlen(copyr_chunk);
+        len += 4 + 4 + n + PAD(n);      /* ID chunksize text */
+    }
+    if( text_chunk ) {
+        n = strlen(text_chunk);
+        len += 4 + 4 + n + PAD(n);      /* ID chunksize text */
+    }
+    return len;
+}
+
+
+
+static void
+writeTextChunks(void) {
+
+    int n;
+
+    if( anno_chunk ) {
+        n = strlen(anno_chunk);
+        pm_writebiglong(stdout, ID_ANNO);
+        pm_writebiglong(stdout, n);
+        writeBytes((unsigned char *)anno_chunk, n);
+        if( ODD(n) )
+            putByte(0);
+    }
+    if( auth_chunk ) {
+        n = strlen(auth_chunk);
+        pm_writebiglong(stdout, ID_AUTH);
+        pm_writebiglong(stdout, n);
+        writeBytes((unsigned char *)auth_chunk, n);
+        if( ODD(n) )
+            putByte(0);
+    }
+    if( copyr_chunk ) {
+        n = strlen(copyr_chunk);
+        pm_writebiglong(stdout, ID_copy);
+        pm_writebiglong(stdout, n);
+        writeBytes((unsigned char *)copyr_chunk, n);
+        if( ODD(n) )
+            putByte(0);
+    }
+    if( name_chunk ) {
+        n = strlen(name_chunk);
+        pm_writebiglong(stdout, ID_NAME);
+        pm_writebiglong(stdout, n);
+        writeBytes((unsigned char *)name_chunk, n);
+        if( ODD(n) )
+            putByte(0);
+    }
+    if( text_chunk ) {
+        n = strlen(text_chunk);
+        pm_writebiglong(stdout, ID_TEXT);
+        pm_writebiglong(stdout, n);
+        writeBytes((unsigned char *)text_chunk, n);
+        if( ODD(n) )
+            putByte(0);
+    }
+}
+
+
+static void
+writeCmap(pixel * const colormap,
+          int     const colors,
+          int     const maxval) {
+
+    int cmapsize, i;
+
+    cmapsize = 3 * colors;
+
+    /* write colormap */
+    pm_writebiglong(stdout, ID_CMAP);
+    pm_writebiglong(stdout, cmapsize);
+    if( maxval != MAXCOLVAL ) {
+        int *table;
+        pm_message("maxval is not %d - automatically rescaling colors", 
+                   MAXCOLVAL);
+        table = makeValTable(maxval, MAXCOLVAL);
+        for( i = 0; i < colors; i++ ) {
+            putByte(table[PPM_GETR(colormap[i])]);
+            putByte(table[PPM_GETG(colormap[i])]);
+            putByte(table[PPM_GETB(colormap[i])]);
+        }
+        free(table);
+    }
+    else {
+        for( i = 0; i < colors; i++ ) {
+            putByte(PPM_GETR(colormap[i]));
+            putByte(PPM_GETG(colormap[i]));
+            putByte(PPM_GETB(colormap[i]));
+        }
+    }
+    if( ODD(cmapsize) )
+        putByte(0);
+}
+
+
+
+static void
+writeBmhd(int const cols,
+          int const rows,
+          int const nPlanes) {
+
+    unsigned char xasp, yasp;
+
+    xasp = 10;  /* initial value */
+    yasp = 10;  /* initial value */
+
+    if( viewportmodes & vmLACE )
+        xasp *= 2;
+    if( viewportmodes & vmHIRES )
+        yasp *= 2;
+
+    pm_writebiglong(stdout, ID_BMHD);
+    pm_writebiglong(stdout, BitMapHeaderSize);
+
+    pm_writebigshort(stdout, cols);
+    pm_writebigshort(stdout, rows);
+    pm_writebigshort(stdout, 0);                       /* x-offset */
+    pm_writebigshort(stdout, 0);                       /* y-offset */
+    putByte(nPlanes);                      /* no of planes */
+    putByte(maskmethod);                   /* masking */
+    putByte(compmethod);                   /* compression */
+    putByte(BMHD_FLAGS_CMAPOK);            /* flags */
+    if( maskmethod == mskHasTransparentColor )
+        pm_writebigshort(stdout, transpIndex);
+    else
+        pm_writebigshort(stdout, 0);
+    putByte(xasp);                         /* x-aspect */
+    putByte(yasp);                         /* y-aspect */
+    pm_writebigshort(stdout, cols);                    /* pageWidth */
+    pm_writebigshort(stdout, rows);                    /* pageHeight */
+}
+
+
+
+/************ compression ************/
+
+
+
+static int
+runbyte1(int const size) {
+
+/* runbyte1 algorithm by Robert A. Knop (rknop@mop.caltech.edu) */
+
+    int in,out,count,hold;
+    unsigned char *inbuf = coded_rowbuf;
+    unsigned char *outbuf = compr_rowbuf;
+
+
+    in=out=0;
+    while( in<size ) {
+        if( (in<size-1) && (inbuf[in]==inbuf[in+1]) ) {    
+            /*Begin replicate run*/
+            for( count=0, hold=in; 
+                 in < size && inbuf[in] == inbuf[hold] && count < 128; 
+                 in++, count++)
+                ;
+            outbuf[out++]=(unsigned char)(char)(-count+1);
+            outbuf[out++]=inbuf[hold];
+        }
+        else {  /*Do a literal run*/
+            hold=out; out++; count=0;
+            while( ((in>=size-2)&&(in<size)) || 
+                   ((in<size-2) && ((inbuf[in]!=inbuf[in+1])
+                                    ||(inbuf[in]!=inbuf[in+2]))) ) {
+                outbuf[out++]=inbuf[in++];
+                if( ++count>=128 )
+                    break;
+            }
+            outbuf[hold]=count-1;
+        }
+    }
+    return(out);
+}
+
+
+
+static void
+storeBodyrow(unsigned char * const row,
+             int             const len) {
+
+    int idx;
+
+    idx = cur_block->used;  /* initial value */
+
+    if (idx >= ROWS_PER_BLOCK) {
+        MALLOCVAR_NOFAIL(cur_block->next);
+        cur_block = cur_block->next;
+        cur_block->used = idx = 0;
+        cur_block->next = NULL;
+    }
+    MALLOCARRAY_NOFAIL(cur_block->row[idx], len);
+    cur_block->len[idx] = len;
+    memcpy(cur_block->row[idx], row, len);
+    ++cur_block->used;
+}
+
+
+
+static int
+compressRow(int const bytes) {
+
+    int newbytes;
+
+    switch( compmethod ) {
+        case cmpByteRun1:
+            newbytes = runbyte1(bytes);
+            break;
+        default:
+            pm_error("compressRow(): unknown compression method %d", 
+                     compmethod);
+    }
+    storeBodyrow(compr_rowbuf, newbytes);
+
+    return newbytes;
+}
+
+
+
+static const unsigned char bitmask[] = {1, 2, 4, 8, 16, 32, 64, 128};
+
+
+
+static long
+encodeRow(FILE *    const outfile,
+              /* if non-NULL, write uncompressed row to this file */
+          rawtype * const rawrow,
+          int       const cols,
+          int       const nPlanes) {
+
+    /* encode algorithm by Johan Widen (jw@jwdata.se) */
+
+    int plane, bytes;
+    long retbytes = 0;
+
+    bytes = RowBytes(cols);
+
+    /* Encode and write raw bytes in plane-interleaved form. */
+    for( plane = 0; plane < nPlanes; plane++ ) {
+        register int col, cbit;
+        register rawtype *rp;
+        register unsigned char *cp;
+        int mask;
+
+        mask = 1 << plane;
+        cbit = -1;
+        cp = coded_rowbuf-1;
+        rp = rawrow;
+        for( col = 0; col < cols; col++, cbit--, rp++ ) {
+            if( cbit < 0 ) {
+                cbit = 7;
+                *++cp = 0;
+            }
+            if( *rp & mask )
+                *cp |= bitmask[cbit];
+        }
+        if( outfile ) {
+            writeBytes(coded_rowbuf, bytes);
+            retbytes += bytes;
+        }
+        else
+            retbytes += compressRow(bytes);
+    }
+    return retbytes;
+}
+
+
+
+static long
+encodeMaskrow(FILE *    const ofP,
+              rawtype * const rawrow,
+              int       const cols) {
+
+    int col;
+
+    for( col = 0; col < cols; col++ ) {
+        if( maskrow[col] == PBM_BLACK )
+            rawrow[col] = 1;
+        else
+            rawrow[col] = 0;
+    }
+    return encodeRow(ofP, rawrow, cols, 1);
+}
+
+
+
+static void
+writeCamg(void) {
+    pm_writebiglong(stdout, ID_CAMG);
+    pm_writebiglong(stdout, CAMGChunkSize);
+    pm_writebiglong(stdout, viewportmodes);
+}
+
+
+
+static void
+reportTooManyColors(int         const ifmode,
+                    int         const maxplanes,
+                    int         const hamplanes,
+                    DirectColor const dcol,
+                    int         const deepbits) {
     
     int const maxcolors = 1 << maxplanes;
 
@@ -237,17 +617,19 @@ report_too_many_colors(int         const ifmode,
 }
 
 
+
 static int
-get_int_val(string, option, bot, top)
-    char *string, *option;
-    int bot, top;
-{
+getIntVal(const char * const string,
+          const char * const option,
+          int          const bot,
+          int          const top) {
+
     int val;
 
-    if( sscanf(string, "%d", &val) != 1 )
+    if (sscanf(string, "%d", &val) != 1 )
         pm_error("option \"%s\" needs integer argument", option);
 
-    if( val < bot || val > top )
+    if (val < bot || val > top)
         pm_error("option \"%s\" argument value out of range (%d..%d)", 
                  option, bot, top);
 
@@ -255,10 +637,10 @@ get_int_val(string, option, bot, top)
 }
 
 
+
 static int
-get_compr_method(string)
-    char *string;
-{
+getComprMethod(const char * const string) {
+
     int retval;
     if( pm_keymatch(string, "none", 1) || pm_keymatch(string, "0", 1) )
         retval = cmpNone;
@@ -271,10 +653,10 @@ get_compr_method(string)
 }
 
 
+
 static int
-get_mask_type(string)
-    char *string;
-{
+getMaskType(const char * const string) {
+
     int retval;
 
     if( pm_keymatch(string, "none", 1) || pm_keymatch(string, "0", 1) )
@@ -297,10 +679,10 @@ get_mask_type(string)
 }
 
 
+
 static int
-get_hammap_mode(string)
-    char *string;
-{
+getHammapMode(const char * const string) {
+
     int retval;
 
     if( pm_keymatch(string, "grey", 1) || pm_keymatch(string, "gray", 1) )
@@ -320,14 +702,16 @@ get_hammap_mode(string)
 }
 
 
+
 /************ colormap file ************/
 
+
+
 static void
-ppm_to_cmap(colorrow, colors, maxval)
-    pixel *colorrow;
-    int colors;
-    int maxval;
-{
+ppmToCmap(pixel * const colorrow,
+          int     const colors,
+          int     const maxval) {
+
     int formsize, cmapsize;
 
     cmapsize = colors * 3;
@@ -336,27 +720,21 @@ ppm_to_cmap(colorrow, colors, maxval)
         4 +                                 /* ILBM */
         4 + 4 + BitMapHeaderSize +          /* BMHD size header */
         4 + 4 + cmapsize + PAD(cmapsize) +  /* CMAP size colormap */
-        length_of_text_chunks();
+        lengthOfTextChunks();
 
-    put_big_long(ID_FORM);
-    put_big_long(formsize);
-    put_big_long(ID_ILBM);
+    pm_writebiglong(stdout, ID_FORM);
+    pm_writebiglong(stdout, formsize);
+    pm_writebiglong(stdout, ID_ILBM);
 
-    write_bmhd(0, 0, 0);
-    write_text_chunks();
-    write_cmap(colorrow, colors, maxval);
+    writeBmhd(0, 0, 0);
+    writeTextChunks();
+    writeCmap(colorrow, colors, maxval);
 }
 
-/************ HAM ************/
 
-static long 
-do_ham_body     ARGS((FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval,
-                pixval hammaxval, int nPlanes, pixel *cmap, int colors));
 
+/************ HAM ************/
 
-static int hcmp (const void *va, const void *vb);
-static pixel *compute_ham_cmap ARGS((int cols, int rows, int maxval, 
-                                     int maxcolors, int *colorsP, int hbits));
 
 
 typedef struct {
@@ -365,20 +743,33 @@ typedef struct {
 } hentry;
 
 
+
+#ifndef LITERAL_FN_DEF_MATCH
+static qsort_comparison_fn hcmp;
+#endif
+
 static int
-hcmp(const void *va, const void *vb)
-{
-    return(((hentry *)vb)->count - ((hentry *)va)->count);  
-        /* reverse sort, highest count first */
+hcmp(const void * const a,
+     const void * const b) {
+
+    /* reverse sort, highest count first */
+
+    const hentry * const vaP = a;
+    const hentry * const vbP = b;
+
+    return(vbP->count - vaP->count);  
 }
 
 
+
 static pixel *
-compute_ham_cmap(cols, rows, maxval, maxcolors, colorsP, hbits)
-    int cols, rows, maxval, maxcolors;
-    int *colorsP;
-    int hbits;
-{
+computeHamCmap(int   const cols,
+               int   const rows,
+               int   const maxval,
+               int   const maxcolors,
+               int * const colorsP,
+               int   const hbits) {
+
     int colors;
     hentry *hmap;
     pixel *cmap;
@@ -405,7 +796,7 @@ compute_ham_cmap(cols, rows, maxval, maxcolors, colorsP, hbits)
         }
     }
 
-    htable = make_val_table(maxval, hmaxval);
+    htable = makeValTable(maxval, hmaxval);
     for( row = 0; row < rows; row++ ) {
         unsigned int col;
         for( col = 0; col < cols; ++col) {
@@ -485,167 +876,38 @@ out:
 }
 
 
-static void
-ppm_to_ham(fp, cols, rows, maxval, colormap, colors, cmapmaxval, hamplanes)
-    FILE *fp;
-    int cols, rows, maxval;
-    pixel *colormap;
-    int colors, cmapmaxval, hamplanes;
-{
-    int hamcolors, nPlanes, i, hammaxval;
-    long oldsize, bodysize, formsize, cmapsize;
-    int *table = NULL;
 
-    if( maskmethod == mskHasTransparentColor ) {
-        pm_message("masking method '%s' not usable with HAM - "
-                   "using '%s' instead",
-                   mskNAME[mskHasTransparentColor], mskNAME[mskHasMask]);
-        maskmethod = mskHasMask;
-    }
-
-    hamcolors = 1 << (hamplanes-2);
-    hammaxval = pm_bitstomaxval(hamplanes-2);
-
-    if( colors == 0 ) {
-        /* no colormap, make our own */
-        switch( hammapmode ) {
-            case HAMMODE_GRAY:
-                colors = hamcolors;
-                MALLOCARRAY_NOFAIL(colormap, colors);
-#ifdef DEBUG
-                pm_message("generating grayscale colormap");
-#endif
-                table = make_val_table(hammaxval, MAXCOLVAL);
-                for( i = 0; i < colors; i++ )
-                    PPM_ASSIGN(colormap[i], table[i], table[i], table[i]);
-                free(table);
-                cmapmaxval = MAXCOLVAL;
-                break;
-            case HAMMODE_FIXED: {
-                int entries, val;
-                double step;
-
-#ifdef DEBUG
-                pm_message("generating rgb colormap");
-#endif
-                /* generate a colormap of 7 "rays" in an RGB color cube:
-                        r, g, b, r+g, r+b, g+b, r+g+b
-                   we need one colormap entry for black, so the number of
-                   entries per ray is (maxcolors-1)/7 */
+static void
+writeBodyRows(void) {
 
-                entries = (hamcolors-1)/7;
-                colors = 7*entries+1;
-                MALLOCARRAY_NOFAIL(colormap, colors);
-                step = (double)MAXCOLVAL / (double)entries;
+    bodyblock *b;
+    int i;
+    long total = 0;
 
-                PPM_ASSIGN(colormap[0], 0, 0, 0);
-                for( i = 1; i <= entries; i++ ) {
-                    val = (int)((double)i * step);
-                    PPM_ASSIGN(colormap[          i], val,   0,   0); /* r */
-                    PPM_ASSIGN(colormap[  entries+i],   0, val,   0); /* g */
-                    PPM_ASSIGN(colormap[2*entries+i],   0,   0, val); /* b */
-                    PPM_ASSIGN(colormap[3*entries+i], val, val,   0); /* r+g */
-                    PPM_ASSIGN(colormap[4*entries+i], val,   0, val); /* r+b */
-                    PPM_ASSIGN(colormap[5*entries+i],   0, val, val); /* g+b */
-                    PPM_ASSIGN(colormap[6*entries+i], val, val, val); /*r+g+b*/
-                }
-                cmapmaxval = MAXCOLVAL;
-            }
-            break;
-            case HAMMODE_RGB4:
-                colormap = compute_ham_cmap(cols, rows, maxval, hamcolors, 
-                                            &colors, 4);
-                cmapmaxval = 15;
-                break;
-            case HAMMODE_RGB5:
-                colormap = compute_ham_cmap(cols, rows, maxval, 
-                                            hamcolors, &colors, 5);
-                cmapmaxval = 31;
-                break;
-            default:
-                pm_error("ppm_to_ham(): unknown hammapmode - can't happen");
-        }
-    }
-    else {
-        hammapmode = HAMMODE_MAPFILE;
-        if( colors > hamcolors ) {
-            pm_message("colormap too large - using first %d colors", 
-                       hamcolors);
-            colors = hamcolors;
+    for( b = &firstblock; b != NULL; b = b->next ) {
+        for( i = 0; i < b->used; i++ ) {
+            writeBytes(b->row[i], b->len[i]);
+            total += b->len[i];
         }
     }
-
-    if( cmapmaxval != maxval ) {
-        int i, *table;
-        pixel *newcmap;
-
-        newcmap = ppm_allocrow(colors);
-        table = make_val_table(cmapmaxval, maxval);
-        for( i = 0; i < colors; i++ )
-            PPM_ASSIGN(newcmap[i], 
-                       table[PPM_GETR(colormap[i])], 
-                       table[PPM_GETG(colormap[i])], 
-                       table[PPM_GETB(colormap[i])]);
-        free(table);
-        ppm_freerow(colormap);
-        colormap = newcmap;
-    }
-    if( sortcmap )
-        ppm_sortcolorrow(colormap, colors, PPM_STDSORT);
-
-    nPlanes = hamplanes;
-    cmapsize = colors * 3;
-
-    bodysize = oldsize = rows * TOTALPLANES(nPlanes) * RowBytes(cols);
-    if( DO_COMPRESS ) {
-        bodysize = do_ham_body(fp, NULL, cols, rows, maxval, 
-                               hammaxval, nPlanes, colormap, colors);
-        /*bodysize = do_ham_body(fp, NULL, cols, 
-          rows, maxval, hammaxval, nPlanes, colbits, nocolor);*/
-        if( bodysize > oldsize )
-            pm_message("warning - %s compression increases BODY size "
-                       "by %ld%%", 
-                       cmpNAME[compmethod], 100*(bodysize-oldsize)/oldsize);
-        else
-            pm_message("BODY compression (%s): %ld%%", 
-                       cmpNAME[compmethod], 100*(oldsize-bodysize)/oldsize);
-    }
-
-
-    formsize =
-        4 +                                 /* ILBM */
-        4 + 4 + BitMapHeaderSize +          /* BMHD size header */
-        4 + 4 + CAMGChunkSize +             /* CAMG size viewportmodes */
-        4 + 4 + cmapsize + PAD(cmapsize) +  /* CMAP size colormap */
-        4 + 4 + bodysize + PAD(bodysize) +  /* BODY size data */
-        length_of_text_chunks();
-
-    put_big_long(ID_FORM);
-    put_big_long(formsize);
-    put_big_long(ID_ILBM);
-
-    write_bmhd(cols, rows, nPlanes);
-    write_text_chunks();
-    write_camg();       /* HAM requires CAMG chunk */
-    write_cmap(colormap, colors, maxval);
-
-    /* write body */
-    put_big_long(ID_BODY);
-    put_big_long(bodysize);
-    if( DO_COMPRESS )
-        write_body_rows();
-    else
-        do_ham_body(fp, NULL, cols, rows, maxval, hammaxval, 
-                    nPlanes, colormap, colors);
+    if( ODD(total) )
+        putByte(0);
 }
 
 
+
 static long
-do_ham_body(FILE *ifP, FILE *ofp, int cols, int rows,
-            pixval maxval, pixval hammaxval, int nPlanes,
-            pixel *colormap, int colors)
-{
-    register int col, row, i;
+doHamBody(FILE *  const ifP,
+          FILE *  const ofP,
+          int     const cols,
+          int     const rows,
+          pixval  const maxval,
+          pixval  const hammaxval,
+          int     const nPlanes,
+          pixel * const colormap,
+          int     const colors) {
+
+    int col, row, i;
     rawtype *raw_rowbuf;
     ppm_fs_info *fi = NULL;
     colorhash_table cht, cht2;
@@ -665,7 +927,7 @@ do_ham_body(FILE *ifP, FILE *ofp, int cols, int rows,
     hamcode_green = HAMCODE_GREEN << colbits;
     hamcode_blue  = HAMCODE_BLUE << colbits;
 
-    itoh = make_val_table(maxval, hammaxval);
+    itoh = makeValTable(maxval, hammaxval);
 
     if( floyd )
         fi = ppm_fs_init(cols, maxval, 0);
@@ -677,7 +939,7 @@ do_ham_body(FILE *ifP, FILE *ofp, int cols, int rows,
         pixel *prow;
 
         noprev = 1;
-        prow = next_pixrow(ifP, row);
+        prow = nextPixrow(ifP, row);
         for( col = ppm_fs_startrow(fi, prow); 
              col < cols; 
              col = ppm_fs_next(fi, col) ) {
@@ -790,13 +1052,13 @@ do_ham_body(FILE *ifP, FILE *ofp, int cols, int rows,
             }
             ppm_fs_update3(fi, col, upr, upg, upb);
         }
-        bodysize += encode_row(ofp, raw_rowbuf, cols, nPlanes);
+        bodysize += encodeRow(ofP, raw_rowbuf, cols, nPlanes);
         if( maskmethod == mskHasMask )
-            bodysize += encode_maskrow(ofp, raw_rowbuf, cols);
+            bodysize += encodeMaskrow(ofP, raw_rowbuf, cols);
         ppm_fs_endrow(fi);
     }
-    if( ofp && ODD(bodysize) )
-        put_byte(0);
+    if( ofP && ODD(bodysize) )
+        putByte(0);
 
     free(itoh);
 
@@ -808,34 +1070,132 @@ do_ham_body(FILE *ifP, FILE *ofp, int cols, int rows,
 }
 
 
-/************ deep (24-bit) ************/
-
-static long do_deep_body      ARGS((FILE *ifP, FILE *ofp, 
-                                    int cols, int rows, 
-                                    pixval maxval, int bitspercolor));
 
 static void
-ppm_to_deep(fp, cols, rows, maxval, bitspercolor)
-    FILE *fp;
-    int cols, rows, maxval, bitspercolor;
-{
-    int nPlanes;
-    long bodysize, oldsize, formsize;
+ppmToHam(FILE *  const ifP,
+         int     const cols,
+         int     const rows,
+         int     const maxval,
+         pixel * const colormapArg,
+         int     const colorsArg,
+         int     const cmapmaxvalArg,
+         int     const hamplanes) {
+
+    int hamcolors, nPlanes, i, hammaxval;
+    long oldsize, bodysize, formsize, cmapsize;
+    int * table;
+    int colors;
+    pixel * colormap;
+    int cmapmaxval;
+
+    table = NULL;  /* initial value */
+    colors = colorsArg;  /* initial value*/
+    colormap = colormapArg;  /* initial value */
+    cmapmaxval = cmapmaxvalArg;  /* initial value */
 
     if( maskmethod == mskHasTransparentColor ) {
-        pm_message("masking method '%s' not usable with deep ILBM - "
+        pm_message("masking method '%s' not usable with HAM - "
                    "using '%s' instead",
-                    mskNAME[mskHasTransparentColor], mskNAME[mskHasMask]);
+                   mskNAME[mskHasTransparentColor], mskNAME[mskHasMask]);
         maskmethod = mskHasMask;
     }
 
-    nPlanes = 3*bitspercolor;
+    hamcolors = 1 << (hamplanes-2);
+    hammaxval = pm_bitstomaxval(hamplanes-2);
+
+    if( colors == 0 ) {
+        /* no colormap, make our own */
+        switch( hammapmode ) {
+            case HAMMODE_GRAY:
+                colors = hamcolors;
+                MALLOCARRAY_NOFAIL(colormap, colors);
+                table = makeValTable(hammaxval, MAXCOLVAL);
+                for( i = 0; i < colors; i++ )
+                    PPM_ASSIGN(colormap[i], table[i], table[i], table[i]);
+                free(table);
+                cmapmaxval = MAXCOLVAL;
+                break;
+            case HAMMODE_FIXED: {
+                int entries, val;
+                double step;
+
+                /* generate a colormap of 7 "rays" in an RGB color cube:
+                        r, g, b, r+g, r+b, g+b, r+g+b
+                   we need one colormap entry for black, so the number of
+                   entries per ray is (maxcolors-1)/7 */
+
+                entries = (hamcolors-1)/7;
+                colors = 7*entries+1;
+                MALLOCARRAY_NOFAIL(colormap, colors);
+                step = (double)MAXCOLVAL / (double)entries;
+
+                PPM_ASSIGN(colormap[0], 0, 0, 0);
+                for( i = 1; i <= entries; i++ ) {
+                    val = (int)((double)i * step);
+                    PPM_ASSIGN(colormap[          i], val,   0,   0); /* r */
+                    PPM_ASSIGN(colormap[  entries+i],   0, val,   0); /* g */
+                    PPM_ASSIGN(colormap[2*entries+i],   0,   0, val); /* b */
+                    PPM_ASSIGN(colormap[3*entries+i], val, val,   0); /* r+g */
+                    PPM_ASSIGN(colormap[4*entries+i], val,   0, val); /* r+b */
+                    PPM_ASSIGN(colormap[5*entries+i],   0, val, val); /* g+b */
+                    PPM_ASSIGN(colormap[6*entries+i], val, val, val); /*r+g+b*/
+                }
+                cmapmaxval = MAXCOLVAL;
+            }
+            break;
+            case HAMMODE_RGB4:
+                colormap = computeHamCmap(cols, rows, maxval, hamcolors, 
+                                          &colors, 4);
+                cmapmaxval = 15;
+                break;
+            case HAMMODE_RGB5:
+                colormap = computeHamCmap(cols, rows, maxval, 
+                                          hamcolors, &colors, 5);
+                cmapmaxval = 31;
+                break;
+            default:
+                pm_error("ppm_to_ham(): unknown hammapmode - can't happen");
+        }
+    }
+    else {
+        hammapmode = HAMMODE_MAPFILE;
+        if( colors > hamcolors ) {
+            pm_message("colormap too large - using first %d colors", 
+                       hamcolors);
+            colors = hamcolors;
+        }
+    }
+
+    if( cmapmaxval != maxval ) {
+        int i, *table;
+        pixel *newcmap;
+
+        newcmap = ppm_allocrow(colors);
+        table = makeValTable(cmapmaxval, maxval);
+        for( i = 0; i < colors; i++ )
+            PPM_ASSIGN(newcmap[i], 
+                       table[PPM_GETR(colormap[i])], 
+                       table[PPM_GETG(colormap[i])], 
+                       table[PPM_GETB(colormap[i])]);
+        free(table);
+        ppm_freerow(colormap);
+        colormap = newcmap;
+    }
+    if( sortcmap )
+        ppm_sortcolorrow(colormap, colors, PPM_STDSORT);
+
+    nPlanes = hamplanes;
+    cmapsize = colors * 3;
 
     bodysize = oldsize = rows * TOTALPLANES(nPlanes) * RowBytes(cols);
     if( DO_COMPRESS ) {
-        bodysize = do_deep_body(fp, NULL, cols, rows, maxval, bitspercolor);
+        bodysize = doHamBody(ifP, NULL, cols, rows, maxval, 
+                               hammaxval, nPlanes, colormap, colors);
+        /*bodysize = doHamBody(ifP, NULL, cols, 
+          rows, maxval, hammaxval, nPlanes, colbits, nocolor);*/
         if( bodysize > oldsize )
-            pm_message("warning - %s compression increases BODY size by %ld%%",
+            pm_message("warning - %s compression increases BODY size "
+                       "by %ld%%", 
                        cmpNAME[compmethod], 100*(bodysize-oldsize)/oldsize);
         else
             pm_message("BODY compression (%s): %ld%%", 
@@ -846,35 +1206,45 @@ ppm_to_deep(fp, cols, rows, maxval, bitspercolor)
     formsize =
         4 +                                 /* ILBM */
         4 + 4 + BitMapHeaderSize +          /* BMHD size header */
+        4 + 4 + CAMGChunkSize +             /* CAMG size viewportmodes */
+        4 + 4 + cmapsize + PAD(cmapsize) +  /* CMAP size colormap */
         4 + 4 + bodysize + PAD(bodysize) +  /* BODY size data */
-        length_of_text_chunks();
-    if( gen_camg )
-        formsize += 4 + 4 + CAMGChunkSize;  /* CAMG size viewportmodes */
+        lengthOfTextChunks();
 
-    put_big_long(ID_FORM);
-    put_big_long(formsize);
-    put_big_long(ID_ILBM);
+    pm_writebiglong(stdout, ID_FORM);
+    pm_writebiglong(stdout, formsize);
+    pm_writebiglong(stdout, ID_ILBM);
 
-    write_bmhd(cols, rows, nPlanes);
-    write_text_chunks();
-    if( gen_camg )
-        write_camg();
+    writeBmhd(cols, rows, nPlanes);
+    writeTextChunks();
+    writeCamg();       /* HAM requires CAMG chunk */
+    writeCmap(colormap, colors, maxval);
 
     /* write body */
-    put_big_long(ID_BODY);
-    put_big_long(bodysize);
+    pm_writebiglong(stdout, ID_BODY);
+    pm_writebiglong(stdout, bodysize);
     if( DO_COMPRESS )
-        write_body_rows();
+        writeBodyRows();
     else
-        do_deep_body(fp, stdout, cols, rows, maxval, bitspercolor);
+        doHamBody(ifP, NULL, cols, rows, maxval, hammaxval, 
+                  nPlanes, colormap, colors);
 }
 
 
+
+/************ deep (24-bit) ************/
+
+
+
 static long
-do_deep_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, 
-             int bitspercolor)
-{
-    register int row, col;
+doDeepBody(FILE * const ifP,
+           FILE * const ofP,
+           int    const cols,
+           int    const rows,
+           pixval const maxval, 
+           int    const bitspercolor) {
+
+    int row, col;
     pixel *pP;
     int *table = NULL;
     long bodysize = 0;
@@ -889,11 +1259,11 @@ do_deep_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval,
     if( maxval != newmaxval ) {
         pm_message("maxval is not %d - automatically rescaling colors", 
                    newmaxval);
-        table = make_val_table(maxval, newmaxval);
+        table = makeValTable(maxval, newmaxval);
     }
 
     for( row = 0; row < rows; row++ ) {
-        pP = next_pixrow(ifP, row);
+        pP = nextPixrow(ifP, row);
         if( table ) {
             for( col = 0; col < cols; col++, pP++ ) {
                 redbuf[col]     = table[PPM_GETR(*pP)];
@@ -908,14 +1278,14 @@ do_deep_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval,
                 bluebuf[col]    = PPM_GETB(*pP);
             }
         }
-        bodysize += encode_row(ofp, redbuf,   cols, bitspercolor);
-        bodysize += encode_row(ofp, greenbuf, cols, bitspercolor);
-        bodysize += encode_row(ofp, bluebuf,  cols, bitspercolor);
+        bodysize += encodeRow(ofP, redbuf,   cols, bitspercolor);
+        bodysize += encodeRow(ofP, greenbuf, cols, bitspercolor);
+        bodysize += encodeRow(ofP, bluebuf,  cols, bitspercolor);
         if( maskmethod == mskHasMask )
-            bodysize += encode_maskrow(ofp, redbuf, cols);
+            bodysize += encodeMaskrow(ofP, redbuf, cols);
     }
-    if( ofp && ODD(bodysize) )
-        put_byte(0);
+    if( ofP && ODD(bodysize) )
+        putByte(0);
 
     /* clean up */
     if( table )
@@ -928,83 +1298,78 @@ do_deep_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval,
 }
 
 
-/************ direct color ************/
-
-static long do_dcol_body      ARGS((FILE *ifP, FILE *ofp, int cols, int rows, 
-                                    pixval maxval, DirectColor *dcol));
 
 static void
-ppm_to_dcol(fp, cols, rows, maxval, dcol)
-    FILE *fp;
-    int cols, rows, maxval;
-    DirectColor *dcol;
-{
+ppmToDeep(FILE * const ifP,
+          int    const cols,
+          int    const rows,
+          int    const maxval,
+          int    const bitspercolor) {
+
     int nPlanes;
     long bodysize, oldsize, formsize;
 
     if( maskmethod == mskHasTransparentColor ) {
         pm_message("masking method '%s' not usable with deep ILBM - "
                    "using '%s' instead",
-                   mskNAME[mskHasTransparentColor], mskNAME[mskHasMask]);
+                    mskNAME[mskHasTransparentColor], mskNAME[mskHasMask]);
         maskmethod = mskHasMask;
     }
 
-    nPlanes = dcol->r + dcol->g + dcol->b;
+    nPlanes = 3*bitspercolor;
 
     bodysize = oldsize = rows * TOTALPLANES(nPlanes) * RowBytes(cols);
     if( DO_COMPRESS ) {
-        bodysize = do_dcol_body(fp, NULL, cols, rows, maxval, dcol);
+        bodysize = doDeepBody(ifP, NULL, cols, rows, maxval, bitspercolor);
         if( bodysize > oldsize )
             pm_message("warning - %s compression increases BODY size by %ld%%",
-                       cmpNAME[compmethod], 
-                       100*(bodysize-oldsize)/oldsize);
+                       cmpNAME[compmethod], 100*(bodysize-oldsize)/oldsize);
         else
-            pm_message("BODY compression (%s): %ld%%", cmpNAME[compmethod], 
-                       100*(oldsize-bodysize)/oldsize);
+            pm_message("BODY compression (%s): %ld%%", 
+                       cmpNAME[compmethod], 100*(oldsize-bodysize)/oldsize);
     }
 
-
     formsize =
         4 +                                 /* ILBM */
         4 + 4 + BitMapHeaderSize +          /* BMHD size header */
-        4 + 4 + DirectColorSize +           /* DCOL size dcol */
         4 + 4 + bodysize + PAD(bodysize) +  /* BODY size data */
-        length_of_text_chunks();
+        lengthOfTextChunks();
     if( gen_camg )
         formsize += 4 + 4 + CAMGChunkSize;  /* CAMG size viewportmodes */
 
-    put_big_long(ID_FORM);
-    put_big_long(formsize);
-    put_big_long(ID_ILBM);
-
-    write_bmhd(cols, rows, nPlanes);
-    write_text_chunks();
-
-    put_big_long(ID_DCOL);
-    put_big_long(DirectColorSize);
-    put_byte(dcol->r);
-    put_byte(dcol->g);
-    put_byte(dcol->b);
-    put_byte(0);    /* pad */
+    pm_writebiglong(stdout, ID_FORM);
+    pm_writebiglong(stdout, formsize);
+    pm_writebiglong(stdout, ID_ILBM);
 
+    writeBmhd(cols, rows, nPlanes);
+    writeTextChunks();
     if( gen_camg )
-        write_camg();
+        writeCamg();
 
     /* write body */
-    put_big_long(ID_BODY);
-    put_big_long(bodysize);
+    pm_writebiglong(stdout, ID_BODY);
+    pm_writebiglong(stdout, bodysize);
     if( DO_COMPRESS )
-        write_body_rows();
+        writeBodyRows();
     else
-        do_dcol_body(fp, stdout, cols, rows, maxval, dcol);
+        doDeepBody(ifP, stdout, cols, rows, maxval, bitspercolor);
 }
 
 
+
+/************ direct color ************/
+
+
+
 static long
-do_dcol_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval, 
-             DirectColor *dcol)
-{
-    register int row, col;
+doDcolBody(FILE *        const ifP,
+           FILE *        const ofP,
+           int           const cols,
+           int           const rows,
+           pixval        const maxval, 
+           DirectColor * const dcol) {
+
+    int row, col;
     pixel *pP;
     long bodysize = 0;
     rawtype *redbuf, *greenbuf, *bluebuf;
@@ -1014,25 +1379,25 @@ do_dcol_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval,
     MALLOCARRAY_NOFAIL(greenbuf, cols);
     MALLOCARRAY_NOFAIL(bluebuf,  cols);
 
-    redtable   = make_val_table(maxval, pm_bitstomaxval(dcol->r));
-    greentable = make_val_table(maxval, pm_bitstomaxval(dcol->g));
-    bluetable  = make_val_table(maxval, pm_bitstomaxval(dcol->b));
+    redtable   = makeValTable(maxval, pm_bitstomaxval(dcol->r));
+    greentable = makeValTable(maxval, pm_bitstomaxval(dcol->g));
+    bluetable  = makeValTable(maxval, pm_bitstomaxval(dcol->b));
 
     for( row = 0; row < rows; row++ ) {
-        pP = next_pixrow(ifP, row);
+        pP = nextPixrow(ifP, row);
         for( col = 0; col < cols; col++, pP++ ) {
             redbuf[col]   = redtable[PPM_GETR(*pP)];
             greenbuf[col] = greentable[PPM_GETG(*pP)];
             bluebuf[col]  = bluetable[PPM_GETB(*pP)];
         }
-        bodysize += encode_row(ofp, redbuf,   cols, dcol->r);
-        bodysize += encode_row(ofp, greenbuf, cols, dcol->g);
-        bodysize += encode_row(ofp, bluebuf,  cols, dcol->b);
+        bodysize += encodeRow(ofP, redbuf,   cols, dcol->r);
+        bodysize += encodeRow(ofP, greenbuf, cols, dcol->g);
+        bodysize += encodeRow(ofP, bluebuf,  cols, dcol->b);
         if( maskmethod == mskHasMask )
-            bodysize += encode_maskrow(ofp, redbuf, cols);
+            bodysize += encodeMaskrow(ofP, redbuf, cols);
     }
-    if( ofp && ODD(bodysize) )
-        put_byte(0);
+    if( ofP && ODD(bodysize) )
+        putByte(0);
 
     /* clean up */
     free(redtable);
@@ -1046,104 +1411,91 @@ do_dcol_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval,
 }
 
 
-/************ normal colormapped ************/
-
-static long do_std_body     ARGS((FILE *ifP, FILE *ofp, int cols, int rows, 
-                                  pixval maxval, pixel *colormap, 
-                                  int colors, int nPlanes));
 
 static void
-ppm_to_std(fp, cols, rows, maxval, colormap, colors, cmapmaxval, 
-           maxcolors, nPlanes)
-    FILE *fp;
-    int cols, rows, maxval;
-    pixel *colormap;
-    int cmapmaxval, colors, maxcolors, nPlanes;
-{
-    long formsize, cmapsize, bodysize, oldsize;
+ppmToDcol(FILE *        const ifP,
+          int           const cols,
+          int           const rows,
+          int           const maxval,
+          DirectColor * const dcol) {
 
-    if( maskmethod == mskHasTransparentColor ) {
-        if( transpColor ) {
-            transpIndex = 
-                ppm_addtocolorrow(colormap, &colors, maxcolors, transpColor);
-        }
-        else
-        if( colors < maxcolors )
-            transpIndex = colors;
+    int nPlanes;
+    long bodysize, oldsize, formsize;
 
-        if( transpIndex < 0 ) {
-            pm_message("too many colors for masking method '%s' - "
-                       "using '%s' instead",
-                       mskNAME[mskHasTransparentColor], mskNAME[mskHasMask]);
-            maskmethod = mskHasMask;
-        }
+    if( maskmethod == mskHasTransparentColor ) {
+        pm_message("masking method '%s' not usable with deep ILBM - "
+                   "using '%s' instead",
+                   mskNAME[mskHasTransparentColor], mskNAME[mskHasMask]);
+        maskmethod = mskHasMask;
     }
 
-    if( cmapmaxval != maxval ) {
-        int i, *table;
-        pixel *newcmap;
-
-        newcmap = ppm_allocrow(colors);
-        table = make_val_table(cmapmaxval, maxval);
-        for (i = 0; i < colors; ++i)
-            PPM_ASSIGN(newcmap[i], 
-                       table[PPM_GETR(colormap[i])], 
-                       table[PPM_GETG(colormap[i])], 
-                       table[PPM_GETB(colormap[i])]);
-        free(table);
-        colormap = newcmap;
-    }
-    if( sortcmap )
-        ppm_sortcolorrow(colormap, colors, PPM_STDSORT);
+    nPlanes = dcol->r + dcol->g + dcol->b;
 
     bodysize = oldsize = rows * TOTALPLANES(nPlanes) * RowBytes(cols);
     if( DO_COMPRESS ) {
-        bodysize = do_std_body(fp, NULL, cols, rows, maxval, colormap, 
-                               colors, nPlanes);
+        bodysize = doDcolBody(ifP, NULL, cols, rows, maxval, dcol);
         if( bodysize > oldsize )
             pm_message("warning - %s compression increases BODY size by %ld%%",
-                       cmpNAME[compmethod], 100*(bodysize-oldsize)/oldsize);
+                       cmpNAME[compmethod], 
+                       100*(bodysize-oldsize)/oldsize);
         else
-            pm_message("BODY compression (%s): %ld%%", 
-                       cmpNAME[compmethod], 100*(oldsize-bodysize)/oldsize);
+            pm_message("BODY compression (%s): %ld%%", cmpNAME[compmethod], 
+                       100*(oldsize-bodysize)/oldsize);
     }
 
-    cmapsize = colors * 3;
 
     formsize =
         4 +                                 /* ILBM */
         4 + 4 + BitMapHeaderSize +          /* BMHD size header */
-        4 + 4 + cmapsize + PAD(cmapsize) +  /* CMAP size colormap */
+        4 + 4 + DirectColorSize +           /* DCOL size dcol */
         4 + 4 + bodysize + PAD(bodysize) +  /* BODY size data */
-        length_of_text_chunks();
+        lengthOfTextChunks();
     if( gen_camg )
         formsize += 4 + 4 + CAMGChunkSize;  /* CAMG size viewportmodes */
 
-    put_big_long(ID_FORM);
-    put_big_long(formsize);
-    put_big_long(ID_ILBM);
+    pm_writebiglong(stdout, ID_FORM);
+    pm_writebiglong(stdout, formsize);
+    pm_writebiglong(stdout, ID_ILBM);
+
+    writeBmhd(cols, rows, nPlanes);
+    writeTextChunks();
+
+    pm_writebiglong(stdout, ID_DCOL);
+    pm_writebiglong(stdout, DirectColorSize);
+    putByte(dcol->r);
+    putByte(dcol->g);
+    putByte(dcol->b);
+    putByte(0);    /* pad */
 
-    write_bmhd(cols, rows, nPlanes);
-    write_text_chunks();
     if( gen_camg )
-        write_camg();
-    write_cmap(colormap, colors, maxval);
+        writeCamg();
 
     /* write body */
-    put_big_long(ID_BODY);
-    put_big_long(bodysize);
+    pm_writebiglong(stdout, ID_BODY);
+    pm_writebiglong(stdout, bodysize);
     if( DO_COMPRESS )
-        write_body_rows();
+        writeBodyRows();
     else
-        do_std_body(fp, stdout, cols, rows, maxval, colormap, colors, nPlanes);
+        doDcolBody(ifP, stdout, cols, rows, maxval, dcol);
 }
 
 
+
+/************ normal colormapped ************/
+
+
+
 static long
-do_std_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval,
-            pixel *colormap, int colors, int nPlanes)
-{
-    register int row, col, i;
+doStdBody(FILE *  const ifP,
+          FILE *  const ofP,
+          int     const cols,
+          int     const rows,
+          pixval  const maxval,
+          pixel * const colormap,
+          int     const colors,
+          int     const nPlanes) {
+
+    int row, col, i;
     pixel *pP;
     rawtype *raw_rowbuf;
     ppm_fs_info *fi = NULL;
@@ -1158,7 +1510,7 @@ do_std_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval,
 
     for( row = 0; row < rows; row++ ) {
         pixel *prow;
-        prow = next_pixrow(ifP, row);
+        prow = nextPixrow(ifP, row);
 
         for( col = ppm_fs_startrow(fi, prow); 
              col < cols; 
@@ -1188,13 +1540,13 @@ do_std_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval,
             raw_rowbuf[col] = i;
             ppm_fs_update(fi, col, &colormap[i]);
         }
-        bodysize += encode_row(ofp, raw_rowbuf, cols, nPlanes);
+        bodysize += encodeRow(ofP, raw_rowbuf, cols, nPlanes);
         if( maskmethod == mskHasMask )
-            bodysize += encode_maskrow(ofp, raw_rowbuf, cols);
+            bodysize += encodeMaskrow(ofP, raw_rowbuf, cols);
         ppm_fs_endrow(fi);
     }
-    if( ofp && ODD(bodysize) )
-        put_byte(0);
+    if( ofP && ODD(bodysize) )
+        putByte(0);
 
     /* clean up */
     ppm_freecolorhash(cht);
@@ -1204,14 +1556,117 @@ do_std_body(FILE *ifP, FILE *ofp, int cols, int rows, pixval maxval,
     return bodysize;
 }
 
+
+
+static void
+ppmToStd(FILE *  const ifP,
+         int     const cols,
+         int     const rows,
+         int     const maxval,
+         pixel * const colormapArg,
+         int     const colorsArg,
+         int     const cmapmaxvalArg, 
+         int     const maxcolors,
+         int     const nPlanes) {
+
+    long formsize, cmapsize, bodysize, oldsize;
+
+    int colors;
+    pixel * colormap;
+    int cmapmaxval;
+
+    colors = colorsArg;  /* initial value */
+    colormap = colormapArg;  /* initial value */
+    cmapmaxval = cmapmaxvalArg;  /* initial value */
+
+    if( maskmethod == mskHasTransparentColor ) {
+        if( transpColor ) {
+            transpIndex = 
+                ppm_addtocolorrow(colormap, &colors, maxcolors, transpColor);
+        }
+        else
+        if( colors < maxcolors )
+            transpIndex = colors;
+
+        if( transpIndex < 0 ) {
+            pm_message("too many colors for masking method '%s' - "
+                       "using '%s' instead",
+                       mskNAME[mskHasTransparentColor], mskNAME[mskHasMask]);
+            maskmethod = mskHasMask;
+        }
+    }
+
+    if( cmapmaxval != maxval ) {
+        int i, *table;
+        pixel *newcmap;
+
+        newcmap = ppm_allocrow(colors);
+        table = makeValTable(cmapmaxval, maxval);
+        for (i = 0; i < colors; ++i)
+            PPM_ASSIGN(newcmap[i], 
+                       table[PPM_GETR(colormap[i])], 
+                       table[PPM_GETG(colormap[i])], 
+                       table[PPM_GETB(colormap[i])]);
+        free(table);
+        colormap = newcmap;
+    }
+    if( sortcmap )
+        ppm_sortcolorrow(colormap, colors, PPM_STDSORT);
+
+    bodysize = oldsize = rows * TOTALPLANES(nPlanes) * RowBytes(cols);
+    if( DO_COMPRESS ) {
+        bodysize = doStdBody(ifP, NULL, cols, rows, maxval, colormap, 
+                             colors, nPlanes);
+        if( bodysize > oldsize )
+            pm_message("warning - %s compression increases BODY size by %ld%%",
+                       cmpNAME[compmethod], 100*(bodysize-oldsize)/oldsize);
+        else
+            pm_message("BODY compression (%s): %ld%%", 
+                       cmpNAME[compmethod], 100*(oldsize-bodysize)/oldsize);
+    }
+
+    cmapsize = colors * 3;
+
+    formsize =
+        4 +                                 /* ILBM */
+        4 + 4 + BitMapHeaderSize +          /* BMHD size header */
+        4 + 4 + cmapsize + PAD(cmapsize) +  /* CMAP size colormap */
+        4 + 4 + bodysize + PAD(bodysize) +  /* BODY size data */
+        lengthOfTextChunks();
+    if( gen_camg )
+        formsize += 4 + 4 + CAMGChunkSize;  /* CAMG size viewportmodes */
+
+    pm_writebiglong(stdout, ID_FORM);
+    pm_writebiglong(stdout, formsize);
+    pm_writebiglong(stdout, ID_ILBM);
+
+    writeBmhd(cols, rows, nPlanes);
+    writeTextChunks();
+    if( gen_camg )
+        writeCamg();
+    writeCmap(colormap, colors, maxval);
+
+    /* write body */
+    pm_writebiglong(stdout, ID_BODY);
+    pm_writebiglong(stdout, bodysize);
+    if( DO_COMPRESS )
+        writeBodyRows();
+    else
+        doStdBody(ifP, stdout, cols, rows, maxval, colormap, colors, nPlanes);
+}
+
+
+
 /************ RGB8 ************/
 
+
+
 static void
-ppm_to_rgb8(ifP, cols, rows, maxval)
-    FILE *ifP;
-    int cols, rows;
-    int maxval;
-{
+ppmToRgb8(FILE * const ifP,
+          int    const cols,
+          int    const rows,
+          int    const maxval) {
+
     long bodysize, oldsize, formsize;
     pixel *pP;
     int *table = NULL;
@@ -1224,13 +1679,13 @@ ppm_to_rgb8(ifP, cols, rows, maxval)
 
     if( maxval != 255 ) {
         pm_message("maxval is not 255 - automatically rescaling colors");
-        table = make_val_table(maxval, 255);
+        table = makeValTable(maxval, 255);
     }
 
     oldsize = cols * rows * 4;
     bodysize = 0;
     for( row = 0; row < rows; row++ ) {
-        pP = next_pixrow(ifP, row);
+        pP = nextPixrow(ifP, row);
         compr_len = 0;
         for( col1 = 0; col1 < cols; col1 = col2 ) {
             col2 = col1 + 1;
@@ -1264,7 +1719,7 @@ ppm_to_rgb8(ifP, cols, rows, maxval)
                 ++compr_len;
             }
         }
-        store_bodyrow(compr_row, compr_len);
+        storeBodyrow(compr_row, compr_len);
         bodysize += compr_len;
     }
 
@@ -1275,31 +1730,34 @@ ppm_to_rgb8(ifP, cols, rows, maxval)
         4 + 4 + BitMapHeaderSize +          /* BMHD size header */
         4 + 4 + CAMGChunkSize +             /* CAMG size viewportmode */
         4 + 4 + bodysize + PAD(bodysize) +  /* BODY size data */
-        length_of_text_chunks();
+        lengthOfTextChunks();
 
     /* write header */
-    put_big_long(ID_FORM);
-    put_big_long(formsize);
-    put_big_long(ID_RGB8);
+    pm_writebiglong(stdout, ID_FORM);
+    pm_writebiglong(stdout, formsize);
+    pm_writebiglong(stdout, ID_RGB8);
 
-    write_bmhd(cols, rows, 25);
-    write_text_chunks();
-    write_camg();               /* RGB8 requires CAMG chunk */
+    writeBmhd(cols, rows, 25);
+    writeTextChunks();
+    writeCamg();               /* RGB8 requires CAMG chunk */
 
-    put_big_long(ID_BODY);
-    put_big_long(bodysize);
-    write_body_rows();
+    pm_writebiglong(stdout, ID_BODY);
+    pm_writebiglong(stdout, bodysize);
+    writeBodyRows();
 }
 
 
+
 /************ RGBN ************/
 
+
+
 static void
-ppm_to_rgbn(ifP, cols, rows, maxval)
-    FILE *ifP;
-    int cols, rows;
-    int maxval;
-{
+ppmToRgbn(FILE * const ifP,
+          int    const cols,
+          int    const rows,
+          int    const maxval) {
+
     long bodysize, oldsize, formsize;
     pixel *pP;
     int *table = NULL;
@@ -1312,13 +1770,13 @@ ppm_to_rgbn(ifP, cols, rows, maxval)
 
     if( maxval != 15 ) {
         pm_message("maxval is not 15 - automatically rescaling colors");
-        table = make_val_table(maxval, 15);
+        table = makeValTable(maxval, 15);
     }
 
     oldsize = cols * rows * 2;
     bodysize = 0;
     for( row = 0; row < rows; row++ ) {
-        pP = next_pixrow(ifP, row);
+        pP = nextPixrow(ifP, row);
         compr_len = 0;
         for( col1 = 0; col1 < cols; col1 = col2 ) {
             col2 = col1 + 1;
@@ -1368,7 +1826,7 @@ ppm_to_rgbn(ifP, cols, rows, maxval)
                 }
             }
         }
-        store_bodyrow(compr_row, compr_len);
+        storeBodyrow(compr_row, compr_len);
         bodysize += compr_len;
     }
 
@@ -1379,30 +1837,33 @@ ppm_to_rgbn(ifP, cols, rows, maxval)
         4 + 4 + BitMapHeaderSize +          /* BMHD size header */
         4 + 4 + CAMGChunkSize +             /* CAMG size viewportmode */
         4 + 4 + bodysize + PAD(bodysize) +  /* BODY size data */
-        length_of_text_chunks();
+        lengthOfTextChunks();
 
     /* write header */
-    put_big_long(ID_FORM);
-    put_big_long(formsize);
-    put_big_long(ID_RGBN);
+    pm_writebiglong(stdout, ID_FORM);
+    pm_writebiglong(stdout, formsize);
+    pm_writebiglong(stdout, ID_RGBN);
 
-    write_bmhd(cols, rows, 13);
-    write_text_chunks();
-    write_camg();               /* RGBN requires CAMG chunk */
+    writeBmhd(cols, rows, 13);
+    writeTextChunks();
+    writeCamg();               /* RGBN requires CAMG chunk */
 
-    put_big_long(ID_BODY);
-    put_big_long(bodysize);
-    write_body_rows();
+    pm_writebiglong(stdout, ID_BODY);
+    pm_writebiglong(stdout, bodysize);
+    writeBodyRows();
 }
 
 
+
 /************ multipalette ************/
 
+
+
 #ifdef ILBM_PCHG
 static pixel *ppmslice[2];  /* need 2 for laced ILBMs, else 1 */
 
-void ppm_to_pchg()
-{
+void
+ppmToPchg() {
 /*
     read first slice
     build a colormap from this slice
@@ -1431,432 +1892,6 @@ void ppm_to_pchg()
 #endif
 
 
-/************ ILBM functions ************/
-
-static int
-length_of_text_chunks ARGS((void))
-{
-    int len, n;
-
-    len = 0;
-    if( anno_chunk ) {
-        n = strlen(anno_chunk);
-        len += 4 + 4 + n + PAD(n);      /* ID chunksize text */
-    }
-    if( auth_chunk ) {
-        n = strlen(auth_chunk);
-        len += 4 + 4 + n + PAD(n);      /* ID chunksize text */
-    }
-    if( name_chunk ) {
-        n = strlen(name_chunk);
-        len += 4 + 4 + n + PAD(n);      /* ID chunksize text */
-    }
-    if( copyr_chunk ) {
-        n = strlen(copyr_chunk);
-        len += 4 + 4 + n + PAD(n);      /* ID chunksize text */
-    }
-    if( text_chunk ) {
-        n = strlen(text_chunk);
-        len += 4 + 4 + n + PAD(n);      /* ID chunksize text */
-    }
-    return len;
-}
-
-
-static void
-write_text_chunks ARGS((void))
-{
-    int n;
-
-    if( anno_chunk ) {
-        n = strlen(anno_chunk);
-        put_big_long(ID_ANNO);
-        put_big_long(n);
-        write_bytes((unsigned char *)anno_chunk, n);
-        if( ODD(n) )
-            put_byte(0);
-    }
-    if( auth_chunk ) {
-        n = strlen(auth_chunk);
-        put_big_long(ID_AUTH);
-        put_big_long(n);
-        write_bytes((unsigned char *)auth_chunk, n);
-        if( ODD(n) )
-            put_byte(0);
-    }
-    if( copyr_chunk ) {
-        n = strlen(copyr_chunk);
-        put_big_long(ID_copy);
-        put_big_long(n);
-        write_bytes((unsigned char *)copyr_chunk, n);
-        if( ODD(n) )
-            put_byte(0);
-    }
-    if( name_chunk ) {
-        n = strlen(name_chunk);
-        put_big_long(ID_NAME);
-        put_big_long(n);
-        write_bytes((unsigned char *)name_chunk, n);
-        if( ODD(n) )
-            put_byte(0);
-    }
-    if( text_chunk ) {
-        n = strlen(text_chunk);
-        put_big_long(ID_TEXT);
-        put_big_long(n);
-        write_bytes((unsigned char *)text_chunk, n);
-        if( ODD(n) )
-            put_byte(0);
-    }
-}
-
-
-static void
-write_cmap(colormap, colors, maxval)
-    pixel *colormap;
-    int colors, maxval;
-{
-    int cmapsize, i;
-
-    cmapsize = 3 * colors;
-
-    /* write colormap */
-    put_big_long(ID_CMAP);
-    put_big_long(cmapsize);
-    if( maxval != MAXCOLVAL ) {
-        int *table;
-        pm_message("maxval is not %d - automatically rescaling colors", 
-                   MAXCOLVAL);
-        table = make_val_table(maxval, MAXCOLVAL);
-        for( i = 0; i < colors; i++ ) {
-            put_byte(table[PPM_GETR(colormap[i])]);
-            put_byte(table[PPM_GETG(colormap[i])]);
-            put_byte(table[PPM_GETB(colormap[i])]);
-        }
-        free(table);
-    }
-    else {
-        for( i = 0; i < colors; i++ ) {
-            put_byte(PPM_GETR(colormap[i]));
-            put_byte(PPM_GETG(colormap[i]));
-            put_byte(PPM_GETB(colormap[i]));
-        }
-    }
-    if( ODD(cmapsize) )
-        put_byte(0);
-}
-
-
-static void
-write_bmhd(cols, rows, nPlanes)
-    int cols, rows, nPlanes;
-{
-    unsigned char xasp = 10, yasp = 10;
-
-    if( viewportmodes & vmLACE )
-        xasp *= 2;
-    if( viewportmodes & vmHIRES )
-        yasp *= 2;
-
-    put_big_long(ID_BMHD);
-    put_big_long(BitMapHeaderSize);
-
-    put_big_short(cols);
-    put_big_short(rows);
-    put_big_short(0);                       /* x-offset */
-    put_big_short(0);                       /* y-offset */
-    put_byte(nPlanes);                      /* no of planes */
-    put_byte(maskmethod);                   /* masking */
-    put_byte(compmethod);                   /* compression */
-    put_byte(BMHD_FLAGS_CMAPOK);            /* flags */
-    if( maskmethod == mskHasTransparentColor )
-        put_big_short(transpIndex);
-    else
-        put_big_short(0);
-    put_byte(xasp);                         /* x-aspect */
-    put_byte(yasp);                         /* y-aspect */
-    put_big_short(cols);                    /* pageWidth */
-    put_big_short(rows);                    /* pageHeight */
-}
-
-
-/* encode algorithm by Johan Widen (jw@jwdata.se) */
-static const unsigned char bitmask[] = {1, 2, 4, 8, 16, 32, 64, 128};
-
-static long
-encode_row(outfile, rawrow, cols, nPlanes)
-    FILE *outfile;  /* if non-NULL, write uncompressed row to this file */
-    rawtype *rawrow;
-    int cols, nPlanes;
-{
-    int plane, bytes;
-    long retbytes = 0;
-
-    bytes = RowBytes(cols);
-
-    /* Encode and write raw bytes in plane-interleaved form. */
-    for( plane = 0; plane < nPlanes; plane++ ) {
-        register int col, cbit;
-        register rawtype *rp;
-        register unsigned char *cp;
-        int mask;
-
-        mask = 1 << plane;
-        cbit = -1;
-        cp = coded_rowbuf-1;
-        rp = rawrow;
-        for( col = 0; col < cols; col++, cbit--, rp++ ) {
-            if( cbit < 0 ) {
-                cbit = 7;
-                *++cp = 0;
-            }
-            if( *rp & mask )
-                *cp |= bitmask[cbit];
-        }
-        if( outfile ) {
-            write_bytes(coded_rowbuf, bytes);
-            retbytes += bytes;
-        }
-        else
-            retbytes += compress_row(bytes);
-    }
-    return retbytes;
-}
-
-
-static long
-encode_maskrow(ofp, rawrow, cols)
-    FILE *ofp;
-    rawtype *rawrow;
-    int cols;
-{
-    int col;
-
-    for( col = 0; col < cols; col++ ) {
-        if( maskrow[col] == PBM_BLACK )
-            rawrow[col] = 1;
-        else
-            rawrow[col] = 0;
-    }
-    return encode_row(ofp, rawrow, cols, 1);
-}
-
-
-static int
-compress_row(bytes)
-    int bytes;
-{
-    int newbytes;
-
-    switch( compmethod ) {
-        case cmpByteRun1:
-            newbytes = runbyte1(bytes);
-            break;
-        default:
-            pm_error("compress_row(): unknown compression method %d", 
-                     compmethod);
-    }
-    store_bodyrow(compr_rowbuf, newbytes);
-
-    return newbytes;
-}
-
-
-static void
-store_bodyrow(row, len)
-    unsigned char *row;
-    int len;
-{
-    int idx = cur_block->used;
-    if( idx >= ROWS_PER_BLOCK ) {
-        MALLOCVAR_NOFAIL(cur_block->next);
-        cur_block = cur_block->next;
-        cur_block->used = idx = 0;
-        cur_block->next = NULL;
-    }
-    MALLOCARRAY_NOFAIL(cur_block->row[idx], len);
-    cur_block->len[idx] = len;
-    memcpy(cur_block->row[idx], row, len);
-    cur_block->used++;
-}
-
-
-static void
-write_body_rows ARGS((void))
-{
-    bodyblock *b;
-    int i;
-    long total = 0;
-
-    for( b = &firstblock; b != NULL; b = b->next ) {
-        for( i = 0; i < b->used; i++ ) {
-            write_bytes(b->row[i], b->len[i]);
-            total += b->len[i];
-        }
-    }
-    if( ODD(total) )
-        put_byte(0);
-}
-
-
-static void
-write_camg ARGS((void))
-{
-    put_big_long(ID_CAMG);
-    put_big_long(CAMGChunkSize);
-    put_big_long(viewportmodes);
-}
-
-
-/************ compression ************/
-
-
-/* runbyte1 algorithm by Robert A. Knop (rknop@mop.caltech.edu) */
-static int
-runbyte1(size)
-   int size;
-{
-    int in,out,count,hold;
-    register unsigned char *inbuf = coded_rowbuf;
-    register unsigned char *outbuf = compr_rowbuf;
-
-
-    in=out=0;
-    while( in<size ) {
-        if( (in<size-1) && (inbuf[in]==inbuf[in+1]) ) {    
-            /*Begin replicate run*/
-            for( count=0, hold=in; 
-                 in < size && inbuf[in] == inbuf[hold] && count < 128; 
-                 in++, count++)
-                ;
-            outbuf[out++]=(unsigned char)(char)(-count+1);
-            outbuf[out++]=inbuf[hold];
-        }
-        else {  /*Do a literal run*/
-            hold=out; out++; count=0;
-            while( ((in>=size-2)&&(in<size)) || 
-                   ((in<size-2) && ((inbuf[in]!=inbuf[in+1])
-                                    ||(inbuf[in]!=inbuf[in+2]))) ) {
-                outbuf[out++]=inbuf[in++];
-                if( ++count>=128 )
-                    break;
-            }
-            outbuf[hold]=count-1;
-        }
-    }
-    return(out);
-}
-
-
-
-/************ other utility functions ************/
-
-static void
-put_big_short(short s)
-{
-    if ( pm_writebigshort( stdout, s ) == -1 )
-        pm_error( "write error" );
-}
-
-
-static void
-put_big_long(l)
-    long l;
-{
-    if ( pm_writebiglong( stdout, l ) == -1 )
-        pm_error( "write error" );
-}
-
-
-static void
-write_bytes(buffer, bytes)
-    unsigned char *buffer;
-    int bytes;
-{
-    if( fwrite(buffer, 1, bytes, stdout) != bytes )
-        pm_error("write error");
-}
-
-
-static int *
-make_val_table(oldmaxval, newmaxval)
-    int oldmaxval, newmaxval;
-{
-    unsigned int i;
-    int * table;
-
-    MALLOCARRAY_NOFAIL(table, oldmaxval + 1);
-    for (i = 0; i <= oldmaxval; ++i)
-        table[i] = ROUNDDIV(i * newmaxval, oldmaxval);
-
-    return table;
-}
-
-
-
-static int  gFormat;
-static int  gCols;
-static int  gMaxval;
-
-static void
-init_read(fp, colsP, rowsP, maxvalP, formatP, readall)
-    FILE *fp;
-    int *colsP, *rowsP;
-    pixval *maxvalP;
-    int *formatP;
-    int readall;
-{
-    ppm_readppminit(fp, colsP, rowsP, maxvalP, formatP);
-
-    if( *rowsP >INT16MAX || *colsP >INT16MAX )
-      pm_error ("Input image is too large.");
-
-    if( readall ) {
-        int row;
-
-        pixels = ppm_allocarray(*colsP, *rowsP);
-        for( row = 0; row < *rowsP; row++ )
-            ppm_readppmrow(fp, pixels[row], *colsP, *maxvalP, *formatP);
-        /* pixels = ppm_readppm(fp, colsP, rowsP, maxvalP); */
-    }
-    else {
-        pixrow = ppm_allocrow(*colsP);
-    }
-    gCols = *colsP;
-    gMaxval = *maxvalP;
-    gFormat = *formatP;
-}
-
-
-static pixel *
-next_pixrow(fp, row)
-    FILE *fp;
-    int row;
-{
-    if( pixels )
-        pixrow = pixels[row];
-    else {
-        ppm_readppmrow(fp, pixrow, gCols, gMaxval, gFormat);
-    }
-    if( maskrow ) {
-        int col;
-
-        if( maskfile )
-            pbm_readpbmrow(maskfile, maskrow, maskcols, maskformat);
-        else {
-            for( col = 0; col < gCols; col++ )
-                maskrow[col] = PBM_BLACK;
-        }
-        if( transpColor ) {
-            for( col = 0; col < gCols; col++ )
-                if( PPM_EQUAL(pixrow[col], *transpColor) )
-                    maskrow[col] = PBM_WHITE;
-        }
-    }
-    return pixrow;
-}
-
-
 
 int
 main(int argc, char ** argv) {
@@ -1902,7 +1937,7 @@ main(int argc, char ** argv) {
             pm_keymatch(argv[argn], "-mp", 3) ) {
             if( ++argn >= argc )
                 pm_error("-maxplanes requires a value");
-            maxplanes = get_int_val(argv[argn], argv[argn-1], 1, MAXPLANES);
+            maxplanes = getIntVal(argv[argn], argv[argn-1], 1, MAXPLANES);
             fixplanes = 0;
         }
         else
@@ -1910,7 +1945,7 @@ main(int argc, char ** argv) {
             pm_keymatch(argv[argn], "-fp", 3) ) {
             if( ++argn >= argc )
                 pm_error("-fixplanes requires a value");
-            fixplanes = get_int_val(argv[argn], argv[argn-1], 1, MAXPLANES);
+            fixplanes = getIntVal(argv[argn], argv[argn-1], 1, MAXPLANES);
             maxplanes = fixplanes;
         }
         else
@@ -1923,7 +1958,7 @@ main(int argc, char ** argv) {
         if( pm_keymatch(argv[argn], "-mmethod", 3) ) {
             if( ++argn >= argc )
                 pm_error("-mmethod requires a value");
-            maskmethod = get_mask_type(argv[argn]);
+            maskmethod = getMaskType(argv[argn]);
             switch( maskmethod ) {
                 case mskNone:
                 case mskHasMask:
@@ -2003,14 +2038,14 @@ main(int argc, char ** argv) {
         if( pm_keymatch(argv[argn], "-hamplanes", 5) ) {
             if( ++argn >= argc )
                 pm_error("-hamplanes requires a value");
-            hamplanes = get_int_val(argv[argn], argv[argn-1], 3, HAMMAXPLANES);
+            hamplanes = getIntVal(argv[argn], argv[argn-1], 3, HAMMAXPLANES);
         }
         else
         if( pm_keymatch(argv[argn], "-hambits", 5) ) {
             if( ++argn >= argc )
                 pm_usage("-hambits requires a value");
             hamplanes = 
-                get_int_val(argv[argn], argv[argn-1], 3, HAMMAXPLANES-2) +2;
+                getIntVal(argv[argn], argv[argn-1], 3, HAMMAXPLANES-2) +2;
         }
         else
         if( pm_keymatch(argv[argn], "-ham6", 5) ) {
@@ -2026,7 +2061,7 @@ main(int argc, char ** argv) {
         if( pm_keymatch(argv[argn], "-hammap", 5) ) {
             if( ++argn >= argc )
                 pm_error("-hammap requires a value");
-            hammapmode = get_hammap_mode(argv[argn]);
+            hammapmode = getHammapMode(argv[argn]);
         }
         else
         if( pm_keymatch(argv[argn], "-hamif", 5) )
@@ -2068,7 +2103,7 @@ main(int argc, char ** argv) {
         if( pm_keymatch(argv[argn], "-deepplanes", 6) ) {
             if( ++argn >= argc )
                 pm_error("-deepplanes requires a value");
-            deepbits = get_int_val(argv[argn], argv[argn-1], 3, 3*MAXPLANES);
+            deepbits = getIntVal(argv[argn], argv[argn-1], 3, 3*MAXPLANES);
             if( deepbits % 3 != 0 )
                 pm_error("option \"%s\" argument value must be divisible by 3",
                          argv[argn-1]);
@@ -2078,7 +2113,7 @@ main(int argc, char ** argv) {
         if( pm_keymatch(argv[argn], "-deepbits", 6) ) {
             if( ++argn >= argc )
                 pm_error("-deepbits requires a value");
-            deepbits = get_int_val(argv[argn], argv[argn-1], 1, MAXPLANES);
+            deepbits = getIntVal(argv[argn], argv[argn-1], 1, MAXPLANES);
         }
         else
         if( pm_keymatch(argv[argn], "-deepif", 6) )
@@ -2117,9 +2152,9 @@ main(int argc, char ** argv) {
             pm_keymatch(argv[argn], "-dcplanes", 4) ) {
             if( argc - argn < 4 )
                 pm_error("-dcbits requires 4 arguments");
-            dcol.r = get_int_val(argv[argn+1], argv[argn], 1, MAXPLANES);
-            dcol.g = get_int_val(argv[argn+2], argv[argn], 1, MAXPLANES);
-            dcol.b = get_int_val(argv[argn+3], argv[argn], 1, MAXPLANES);
+            dcol.r = getIntVal(argv[argn+1], argv[argn], 1, MAXPLANES);
+            dcol.g = getIntVal(argv[argn+2], argv[argn], 1, MAXPLANES);
+            dcol.b = getIntVal(argv[argn+3], argv[argn], 1, MAXPLANES);
             argn += 3;
         }
         else
@@ -2146,7 +2181,7 @@ main(int argc, char ** argv) {
         if( pm_keymatch(argv[argn], "-cmethod", 4) ) {
             if( ++argn >= argc )
                 pm_error("-cmethod requires a value");
-            compmethod = get_compr_method(argv[argn]);
+            compmethod = getComprMethod(argv[argn]);
         }
         else
         if( pm_keymatch(argv[argn], "-floyd", 3) || 
@@ -2205,22 +2240,22 @@ main(int argc, char ** argv) {
     switch(forcemode) {
         case MODE_HAM:
             if (hammapmode == HAMMODE_RGB4 || hammapmode == HAMMODE_RGB5)
-                init_read(ifP, &cols, &rows, &maxval, &format, 1);
+                initRead(ifP, &cols, &rows, &maxval, &format, 1);
             else
-                init_read(ifP, &cols, &rows, &maxval, &format, 0);
+                initRead(ifP, &cols, &rows, &maxval, &format, 0);
             break;
         case MODE_DCOL:
         case MODE_DEEP:
             mapfile = NULL;
-            init_read(ifP, &cols, &rows, &maxval, &format, 0);
+            initRead(ifP, &cols, &rows, &maxval, &format, 0);
             break;
         case MODE_RGB8:
             mapfile = NULL;
-            init_read(ifP, &cols, &rows, &maxval, &format, 0);
+            initRead(ifP, &cols, &rows, &maxval, &format, 0);
             break;
         case MODE_RGBN:
             mapfile = NULL;
-            init_read(ifP, &cols, &rows, &maxval, &format, 0);
+            initRead(ifP, &cols, &rows, &maxval, &format, 0);
             break;
         case MODE_CMAP:
             /* Figure out the colormap. */
@@ -2234,9 +2269,9 @@ main(int argc, char ** argv) {
             break;
         default:
             if (mapfile)
-                init_read(ifP, &cols, &rows, &maxval, &format, 0);
+                initRead(ifP, &cols, &rows, &maxval, &format, 0);
             else {
-                init_read(ifP, &cols, &rows, &maxval, &format, 1);  
+                initRead(ifP, &cols, &rows, &maxval, &format, 1);  
                     /* read file into memory */
                 pm_message("computing colormap...");
                 colormap = 
@@ -2250,7 +2285,7 @@ main(int argc, char ** argv) {
                         nPlanes = fixplanes;
                 } else {  /* too many colors */
                     mode = ifmode;
-                    report_too_many_colors(ifmode, maxplanes, hamplanes,
+                    reportTooManyColors(ifmode, maxplanes, hamplanes,
                                            dcol, deepbits );
                 }
             }
@@ -2300,31 +2335,34 @@ main(int argc, char ** argv) {
     switch (mode) {
         case MODE_HAM:
             viewportmodes |= vmHAM;
-            ppm_to_ham(ifP, cols, rows, maxval, 
-                       colormap, colors, cmapmaxval, hamplanes);
+            ppmToHam(ifP, cols, rows, maxval, 
+                     colormap, colors, cmapmaxval, hamplanes);
             break;
         case MODE_DEEP:
-            ppm_to_deep(ifP, cols, rows, maxval, deepbits);
+            ppmToDeep(ifP, cols, rows, maxval, deepbits);
             break;
         case MODE_DCOL:
-            ppm_to_dcol(ifP, cols, rows, maxval, &dcol);
+            ppmToDcol(ifP, cols, rows, maxval, &dcol);
             break;
         case MODE_RGB8:
-            ppm_to_rgb8(ifP, cols, rows, maxval);
+            ppmToRgb8(ifP, cols, rows, maxval);
             break;
         case MODE_RGBN:
-            ppm_to_rgbn(ifP, cols, rows, maxval);
+            ppmToRgbn(ifP, cols, rows, maxval);
             break;
         case MODE_CMAP:
-            ppm_to_cmap(colormap, colors, cmapmaxval);
+            ppmToCmap(colormap, colors, cmapmaxval);
             break;
         default:
             if (mapfile == NULL)
                 floyd = 0;          /* would only slow down conversion */
-            ppm_to_std(ifP, cols, rows, maxval, colormap, colors, 
-                       cmapmaxval, MAXCOLORS, nPlanes);
+            ppmToStd(ifP, cols, rows, maxval, colormap, colors, 
+                     cmapmaxval, MAXCOLORS, nPlanes);
             break;
     }
     pm_close(ifP);
     return 0;
 }
+
+
+
diff --git a/converter/ppm/ppmtompeg/bitio.c b/converter/ppm/ppmtompeg/bitio.c
index e02fe985..3812bc39 100644
--- a/converter/ppm/ppmtompeg/bitio.c
+++ b/converter/ppm/ppmtompeg/bitio.c
@@ -244,7 +244,7 @@ Bitio_Write(BitBucket * const bbPtr,
     assert(nbits <= 32 && nbits >= 0);
 
     /*
-     * Clear top bits if not part of data, necessary due to down and
+     * Clear top bits if not part of data, necessary because of down and
      * dirty calls of Bitio_Write with unnecessary top bits set.
      */
 
diff --git a/converter/ppm/ppmtompeg/jrevdct.c b/converter/ppm/ppmtompeg/jrevdct.c
index 2e99a67a..c3379d7a 100644
--- a/converter/ppm/ppmtompeg/jrevdct.c
+++ b/converter/ppm/ppmtompeg/jrevdct.c
@@ -199,7 +199,7 @@ mpeg_jrevdct_quick(data)
   dataptr = data;
 
   for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) {
-    /* Due to quantization, we will usually find that many of the input
+    /* Because of quantization, we will usually find that many of the input
      * coefficients are zero, especially the AC terms.  We can exploit this
      * by short-circuiting the IDCT calculation for any row in which all
      * the AC terms are zero.  In that case each output is equal to the
diff --git a/doc/HISTORY b/doc/HISTORY
index 850e8dcd..cec81279 100644
--- a/doc/HISTORY
+++ b/doc/HISTORY
@@ -4,16 +4,16 @@ Netpbm.
 CHANGE HISTORY 
 --------------
 
-13.07.25 BJH  Release 10.63.02
-
-              libnetpbm, pnmpsnr, ppmcie on Mac OS X: fix bogus printing of
-              floating point numbers.
-
-13.07.04 BJH  Release 10.63.01
+13.09.28 BJH  Release 10.64.00
 
               pngtopam: fix bug: ignores -gamma.  Introduced in 10.48
               (September 2009).
 
+              libnetpbm, pnmpsnr, ppmcie on systems that don't use GNU C
+              library: fix bogus printing of floating point numbers.
+
+              test: fix ppmhist lack of sorting.
+
 13.06.29 BJH  Release 10.63.00
 
               Add pamtowinicon, winicontopam.  Thanks Ludolf Holzheid
diff --git a/doc/TESTS b/doc/TESTS
index 3196a8fb..7b62a841 100644
--- a/doc/TESTS
+++ b/doc/TESTS
@@ -55,7 +55,7 @@ appear at the end:
   ==================
   SUCCESS 83
   FAILURE 1
-  TOTAL SUPPORTED 84
+  TOTAL TESTABLE 84
   ==================
   All tests done.
   Sat, 08 Jun 2013 09:30:33 +0000
@@ -205,8 +205,8 @@ http://netpbm.sourceforge.net/prereq.html .
 ===================
 
 Broken programs will invariably lead to failures.  Certain programs
-(for instance, image generators pbmmake pgmmake) are used in numerous
-test scripts.  Problem in them will lead to multiple failures.
+(for instance, image generators 'pbmmake' and 'pgmmake') are used in numerous
+test scripts.  Problems in them will lead to multiple failures.
 
 To aid you in this situation each test routine lists the necessary programs
 near the top.
diff --git a/editor/pamscale.c b/editor/pamscale.c
index 485ae27f..48b0f8dd 100644
--- a/editor/pamscale.c
+++ b/editor/pamscale.c
@@ -1143,7 +1143,7 @@ createWeightListSet(unsigned int          const sourceSize,
       
    2) Filter out any frequencies that are too high to be captured
       by the new sampling -- i.e. frequencies above 1/2 the new
-      sample rate.  This is the information we must lose due to low
+      sample rate.  This is the information we must lose because of low
       sample rate.
       
    3) Sample the result at the new sample rate.
@@ -1656,7 +1656,7 @@ horizontalScale(tuplen *     const inputtuplenrow,
   it by a factor of 'xscale', to create the output row 'newtuplenrow',
   described by *outpamP.
 
-  Due to arithmetic imprecision, we may have to stretch slightly the
+  Because of arithmetic imprecision, we may have to stretch slightly the
   contents of the last pixel of the output row to make a full pixel.
   Return as *stretchP the fraction of a pixel by which we had to
   stretch in this way.
@@ -1697,7 +1697,7 @@ horizontalScale(tuplen *     const inputtuplenrow,
         }
         /* There's not enough left in the current input pixel to fill up 
            a whole output column, so just accumulate the remainder of the
-           pixel into the current output column.  Due to rounding, we may
+           pixel into the current output column.  Because of rounding, we may
            have a tiny bit of pixel left and have run out of output pixels.
            In that case, we throw away what's left.
         */
@@ -1850,7 +1850,7 @@ issueStretchWarning(bool   const verbose,
        row.  
     */
     if (verbose)
-        pm_message("%f of bottom row stretched due to "
+        pm_message("%f of bottom row stretched because of "
                    "arithmetic imprecision", 
                    fracrowtofill);
 }
@@ -1884,7 +1884,7 @@ scaleHorizontallyAndOutputRow(struct pam *             const inpamP,
                         xscale, &stretch);
             
         if (verbose && row == 0)
-            pm_message("%f of right column stretched due to "
+            pm_message("%f of right column stretched because of "
                        "arithmetic imprecision", 
                        stretch);
             
diff --git a/editor/pamsistoaglyph.c b/editor/pamsistoaglyph.c
index 9866b7bd..6b093520 100644
--- a/editor/pamsistoaglyph.c
+++ b/editor/pamsistoaglyph.c
@@ -247,12 +247,19 @@ findRegionEyeSeparation( gray ** const grayArray,
 
 
 
+#ifndef LITERAL_FN_DEF_MATCH
+static qsort_comparison_fn compareInts;
+#endif
+
 static int
-compare_ints( const void * const firstP,
-              const void * const secondP ) {
+compareInts(const void * const a,
+            const void * const b) {
+
+    const int * const firstP = a;
+    const int * const secondP = b;
 
-    int const first  = *(int *)firstP;
-    int const second = *(int *)secondP;
+    int const first  = *firstP;
+    int const second = *secondP;
 
     int retval;
 
@@ -311,7 +318,7 @@ findEyeSeparation( struct pam *  const pamP,
                 rowSeparation[numValidRows++] = sep;
         }
         if (numValidRows > 0) {
-            qsort( rowSeparation, numValidRows, sizeof(int), compare_ints );
+            qsort(rowSeparation, numValidRows, sizeof(int), compareInts);
             bestSeparation = rowSeparation[numValidRows/2];
         }
         free( rowSeparation );
diff --git a/editor/pnmnorm.c b/editor/pnmnorm.c
index 56685ee0..70d5641a 100644
--- a/editor/pnmnorm.c
+++ b/editor/pnmnorm.c
@@ -452,7 +452,7 @@ resolvePercentParams(FILE *             const ifP,
    to black and the one that is to be stretched to white) as requested
    by the -bvalue, -bpercent, -wvalue, and -wpercent options.
 
-   These values may be invalid due to overlapping, and they may exceed
+   These values may be invalid because of overlapping, and they may exceed
    the maximum allowed stretch; Caller must deal with that.
 -----------------------------------------------------------------------------*/
     unsigned int * hist;  /* malloc'ed */
@@ -735,7 +735,7 @@ computeTransferFunction(bool      const quadratic,
    3 points.
 
    This stretching could conceivably result in more brightnesses mapping to
-   zero and full brightness that 'bvalue' and 'wvalue' demand, due to
+   zero and full brightness that 'bvalue' and 'wvalue' demand, because of
    rounding.
 
    Define function only for values 0..maxval.
diff --git a/editor/pnmscalefixed.c b/editor/pnmscalefixed.c
index 81efc9f4..884ca315 100644
--- a/editor/pnmscalefixed.c
+++ b/editor/pnmscalefixed.c
@@ -256,7 +256,7 @@ compute_output_dimensions(const struct cmdline_info cmdline,
             *newrowsP = rows;
     }    
 
-    /* If the calculations above yielded (due to rounding) a zero 
+    /* If the calculations above yielded (because of rounding) a zero 
        dimension, we fudge it up to 1.  We do this rather than considering
        it a specification error (and dying) because it's friendlier to 
        automated processes that work on arbitrary input.  It saves them
@@ -283,7 +283,7 @@ horizontal_scale(const xel inputxelrow[], xel newxelrow[],
    output rows.
 
    *stretchP is the number of columns (could be fractional) on the right 
-   that we had to fill by stretching due to rounding problems.
+   that we had to fill by stretching because of rounding problems.
 -----------------------------------------------------------------------------*/
     long r, g, b;
     long fraccoltofill, fraccolleft;
@@ -574,7 +574,7 @@ main(int argc, char **argv ) {
             
             if (cmdline.verbose && row == 0 && stretch != 0)
                 pm_message("%d/%d = %f right columns filled by stretching "
-                           "due to arithmetic imprecision", 
+                           "because of arithmetic imprecision", 
                            stretch, SCALE, (float) stretch/SCALE);
             
             pnm_writepnmrow(stdout, newxelrow, newcols, 
diff --git a/editor/ppmdist.c b/editor/ppmdist.c
index bca96adc..e8f17bff 100644
--- a/editor/ppmdist.c
+++ b/editor/ppmdist.c
@@ -22,6 +22,7 @@ struct colorToGrayEntry {
 #define MAXCOLORS 255
 
 
+
 static gray
 newGrayValue(pixel *pix, struct colorToGrayEntry *colorToGrayMap, int colors) {
 
@@ -40,20 +41,34 @@ newGrayValue(pixel *pix, struct colorToGrayEntry *colorToGrayMap, int colors) {
 
 
 
+#ifndef LITERAL_FN_DEF_MATCH
+static qsort_comparison_fn cmpColorToGrayEntryByIntensity;
+#endif
+
 static int
-cmpColorToGrayEntryByIntensity(const void *entry1, const void *entry2) {
+cmpColorToGrayEntryByIntensity(const void * const a,
+                               const void * const b) {
+
+    const struct colorToGrayEntry * const entry1P = a;
+    const struct colorToGrayEntry * const entry2P = b;
 
-    return ((struct colorToGrayEntry *) entry1)->gray -
-        ((struct colorToGrayEntry *) entry2)->gray;
+    return entry1P->gray - entry2P->gray;
 }
 
 
 
+#ifndef LITERAL_FN_DEF_MATCH
+static qsort_comparison_fn cmpColorToGrayEntryByFrequency;
+#endif
+
 static int
-cmpColorToGrayEntryByFrequency(const void * entry1, const void * entry2) {
+cmpColorToGrayEntryByFrequency(const void * const a,
+                               const void * const b) {
+
+    const struct colorToGrayEntry * const entry1P = a;
+    const struct colorToGrayEntry * const entry2P = b;
 
-    return ((struct colorToGrayEntry *) entry1)->frequency -
-        ((struct colorToGrayEntry *) entry2)->frequency;
+    return entry1P->frequency - entry2P->frequency;
 }
 
 
diff --git a/lib/libpamd.c b/lib/libpamd.c
index 0da818c1..77c7fc54 100644
--- a/lib/libpamd.c
+++ b/lib/libpamd.c
@@ -1014,12 +1014,12 @@ pamd_fill_drawproc(tuple **     const tuples,
 
 
 #ifndef LITERAL_FN_DEF_MATCH
-static qsort_comparison_fn yx_compare;
+static qsort_comparison_fn yxCompare;
 #endif
 
 static int
-yx_compare(const void * const c1Arg,
-           const void * const c2Arg) {
+yxCompare(const void * const c1Arg,
+          const void * const c2Arg) {
 
     const coord * const c1P = c1Arg;
     const coord * const c2P = c2Arg;
@@ -1082,7 +1082,7 @@ pamd_fill(tuple **         const tuples,
     pamd_setlineclip(oldclip);
 
     /* Sort the coords by Y, secondarily by X. */
-    qsort((char*) fh->coords, fh->n, sizeof(coord), yx_compare);
+    qsort((char*) fh->coords, fh->n, sizeof(coord), yxCompare);
 
     /* Find equal coords with different edge numbers, and swap if necessary. */
     edge = -1;
diff --git a/lib/libppmcmap.c b/lib/libppmcmap.c
index 27233a46..67a85ebf 100644
--- a/lib/libppmcmap.c
+++ b/lib/libppmcmap.c
@@ -689,9 +689,33 @@ fail:
 }
 
 
+
+static int (*customCmp)(pixel *, pixel *);
+
+#ifndef LITERAL_FN_DEF_MATCH
+static qsort_comparison_fn customStub;
+#endif
+
 static int
-pixel_cmp(const void * const a, const void * const b) {
-    const pixel *p1 = (const pixel *)a, *p2 = (const pixel *)b;
+customStub(const void * const a,
+           const void * const b) {
+
+    return (*customCmp)((pixel *)a, (pixel *)b);
+}
+
+
+
+#ifndef LITERAL_FN_DEF_MATCH
+static qsort_comparison_fn pixelCmp;
+#endif
+
+static int
+pixelCmp(const void * const a,
+         const void * const b) {
+
+    const pixel * const p1 = (const pixel *)a;
+    const pixel * const p2 = (const pixel *)b;
+
     int diff;
 
     diff = PPM_GETR(*p1) - PPM_GETR(*p2);
@@ -703,23 +727,18 @@ pixel_cmp(const void * const a, const void * const b) {
     return diff;
 }
 
-static int (*custom_cmp)(pixel *, pixel *);
-
-static int
-custom_stub(const void * const a, const void * const b) {
-    return (*custom_cmp)((pixel *)a, (pixel *)b);
-}
 
 
 void
-ppm_sortcolorrow(pixel * const colorrow, const int ncolors, 
+ppm_sortcolorrow(pixel * const colorrow,
+                 int     const ncolors, 
                  int (*cmpfunc)(pixel *, pixel *)) {
 
-    if( cmpfunc ) {
-        custom_cmp = cmpfunc;
-        qsort((void *)colorrow, ncolors, sizeof(pixel), custom_stub);
+    if (cmpfunc) {
+        customCmp = cmpfunc;
+        qsort((void *)colorrow, ncolors, sizeof(pixel), customStub);
     } else
-        qsort((void *)colorrow, ncolors, sizeof(pixel), pixel_cmp);
+        qsort((void *)colorrow, ncolors, sizeof(pixel), pixelCmp);
 }
 
 
diff --git a/lib/libppmd.c b/lib/libppmd.c
index 2a998947..d6f08b37 100644
--- a/lib/libppmd.c
+++ b/lib/libppmd.c
@@ -1191,12 +1191,12 @@ ppmd_fill_drawproc(pixel**      const pixels,
 
 
 #ifndef LITERAL_FN_DEF_MATCH
-static qsort_comparison_fn yx_compare;
+static qsort_comparison_fn yxCompare;
 #endif
 
 static int
-yx_compare(const void * const c1Arg,
-           const void * const c2Arg) {
+yxCompare(const void * const c1Arg,
+          const void * const c2Arg) {
 
     const coord * const c1P = c1Arg;
     const coord * const c2P = c2Arg;
@@ -1258,7 +1258,7 @@ ppmd_fill(pixel **         const pixels,
     ppmd_setlineclip(oldclip);
 
     /* Sort the coords by Y, secondarily by X. */
-    qsort((char*) fh->coords, fh->n, sizeof(coord), yx_compare);
+    qsort((char*) fh->coords, fh->n, sizeof(coord), yxCompare);
 
     /* Find equal coords with different edge numbers, and swap if necessary. */
     edge = -1;
diff --git a/lib/util/mallocvar.c b/lib/util/mallocvar.c
index 05e2d4c4..339d5d61 100644
--- a/lib/util/mallocvar.c
+++ b/lib/util/mallocvar.c
@@ -86,9 +86,9 @@ pm_mallocarray2(void **      const resultP,
    of those rows.  So a[row][col] gives you the element of the two
    dimensional array at Row 'row', Column 'col'.
 
-   Each array element is ideally aligned to an 'elementSize' boundary.
-   But we guarantee this only for 1, 2, 4, 8, and 16, due to limitations of
-   libc malloc() (which we use to allocate all the memory).
+   Each array element is ideally aligned to an 'elementSize' boundary.  But we
+   guarantee this only for 1, 2, 4, 8, and 16, because of limitations of libc
+   malloc() (which we use to allocate all the memory).
 
    We tack on two extra elements to the end of the row index, transparent to
    the user, for use in memory management (in particular, in destroying the
diff --git a/lib/util/nstring.c b/lib/util/nstring.c
index 5dd8f680..e95d9824 100644
--- a/lib/util/nstring.c
+++ b/lib/util/nstring.c
@@ -39,7 +39,7 @@
  * IMPLEMENTED CONVERSION SPECIFIERS AND DATA TYPES
  *
  * This snprintf implements only the following conversion specifiers:
- * s, c, d, u, o, x, X, p  (and synonyms: i, D, U, O - see below)
+ * s, c, d, u, o, x, X, p, f  (and synonyms: i, D, U, O - see below)
  * with flags: '-', '+', ' ', '0' and '#'.
  * An asterisk is acceptable for field width as well as precision.
  *
@@ -66,7 +66,7 @@
  *
  * The following is specifically NOT implemented:
  *   - flag ' (thousands' grouping character) is recognized but ignored
- *   - numeric conversion specifiers: f, e, E, g, G and synonym F,
+ *   - numeric conversion specifiers: e, E, g, G and synonym F,
  *     as well as the new a and A conversion specifiers
  *   - length modifier 'L' (long double) and 'q' (quad - use 'll' instead)
  *   - wide character/string conversions: lc, ls, and nonstandard
@@ -114,8 +114,8 @@
 
 
 #define _GNU_SOURCE
-   /* Due to conditional compilation, this is GNU source only if the C library
-      is GNU.
+   /* Because of conditional compilation, this is GNU source only if the C
+      library is GNU.
    */
 #define PORTABLE_SNPRINTF_VERSION_MAJOR 2
 #define PORTABLE_SNPRINTF_VERSION_MINOR 2
@@ -231,10 +231,14 @@ pm_vsnprintf(char *       const str,
             p += n; str_l += n;
         } else {
             const char *starting_p;
-            size_t min_field_width = 0, precision = 0;
-            int zero_padding = 0, precision_specified = 0, justify_left = 0;
-            int alternate_form = 0, force_sign = 0;
-            int space_for_positive = 1;
+            size_t min_field_width;
+            size_t precision = 0;
+            bool precision_specified;
+            bool justify_left;
+            bool zero_padding;
+            bool alternate_form;
+            bool force_sign;
+            bool space_for_positive;
                 /* If both the ' ' and '+' flags appear,
                    the ' ' flag should be ignored.
                 */
@@ -271,17 +275,22 @@ pm_vsnprintf(char *       const str,
             ++p;  /* skip '%' */
 
             /* parse flags */
+            justify_left = false;  /* initial value */
+            zero_padding = false;  /* initial value */
+            alternate_form = false;  /* initial value */
+            force_sign = false;  /* initial value */
+            space_for_positive = false;  /* initial value */
             while (*p == '0' || *p == '-' || *p == '+' ||
                    *p == ' ' || *p == '#' || *p == '\'') {
                 switch (*p) {
-                case '0': zero_padding = 1; break;
-                case '-': justify_left = 1; break;
-                case '+': force_sign = 1; space_for_positive = 0; break;
-                case ' ': force_sign = 1; break;
+                case '0': zero_padding = true; break;
+                case '-': justify_left = true; break;
+                case '+': force_sign = true; space_for_positive = false; break;
+                case ' ': force_sign = true; break;
                     /* If both the ' ' and '+' flags appear, the ' '
                        flag should be ignored
                     */
-                case '#': alternate_form = 1; break;
+                case '#': alternate_form = true; break;
                 case '\'': break;
                 }
                 ++p;
@@ -293,9 +302,10 @@ pm_vsnprintf(char *       const str,
             /* parse field width */
             if (*p == '*') {
                 int j;
-                p++; j = va_arg(ap, int);
-                if (j >= 0) min_field_width = j;
-                else { min_field_width = -j; justify_left = 1; }
+                ++p;
+                j = va_arg(ap, int);
+                if (j >= 0) { min_field_width = j; justify_left = false; }
+                else { min_field_width = -j; justify_left = true; }
             } else if (isdigit((int)(*p))) {
                 /* size_t could be wider than unsigned int; make sure
                    we treat argument like common implementations do
@@ -304,16 +314,19 @@ pm_vsnprintf(char *       const str,
                 while (isdigit((int)(*p)))
                     uj = 10*uj + (unsigned int)(*p++ - '0');
                 min_field_width = uj;
-            }
+            } else
+                min_field_width = 0;
+
             /* parse precision */
             if (*p == '.') {
-                p++; precision_specified = 1;
+                ++p;
+                precision_specified = true;
                 if (*p == '*') {
                     int j = va_arg(ap, int);
                     p++;
                     if (j >= 0) precision = j;
                     else {
-                        precision_specified = 0; precision = 0;
+                        precision_specified = false; precision = 0;
                         /* NOTE: Solaris 2.6 man page claims that in
                            this case the precision should be set to 0.
                            Digital Unix 4.0, HPUX 10 and BSD man page
@@ -332,7 +345,9 @@ pm_vsnprintf(char *       const str,
                         uj = 10*uj + (unsigned int)(*p++ - '0');
                     precision = uj;
                 }
-            }
+            } else
+                precision_specified = false;
+
             /* parse 'h', 'l' and 'll' length modifiers */
             if (*p == 'h' || *p == 'l') {
                 length_modifier = *p; p++;
@@ -367,7 +382,7 @@ pm_vsnprintf(char *       const str,
                     Unix and Linux does not.
                 */
 
-                zero_padding = 0;
+                zero_padding = false;
                     /* turn zero padding off for string conversions */
                 str_arg_l = 1;
                 switch (fmt_spec) {
@@ -493,7 +508,7 @@ pm_vsnprintf(char *       const str,
                    Perl.
                 */
                 if (precision_specified)
-                    zero_padding = 0;
+                    zero_padding = false;
                 if (fmt_spec == 'd') {
                     if (force_sign && arg_sign >= 0)
                         tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
@@ -586,7 +601,7 @@ pm_vsnprintf(char *       const str,
                                explicit precision of zero
                             */
                             precision = num_of_digits+1;
-                            precision_specified = 1;
+                            precision_specified = true;
                         }
                     }
                     /* zero padding to specified precision? */
@@ -600,18 +615,31 @@ pm_vsnprintf(char *       const str,
                     if (n > 0) number_of_zeros_to_pad += n;
                 }
             } break;
+            case 'f': {
+                char f[10];
+                if (precision_specified)
+                    snprintf(f, ARRAY_SIZE(f), "%%%u.%uf",
+                             (unsigned)min_field_width, (unsigned)precision);
+                else
+                    snprintf(f, ARRAY_SIZE(f), "%%%uf",
+                             (unsigned)min_field_width);
+
+                str_arg_l = sprintf(tmp, f, va_arg(ap, double));
+                str_arg = &tmp[0];
+
+                min_field_width = 0;
+                zero_padding_insertion_ind = 0;
+            } break;
             default:
-                /* unrecognized conversion specifier, keep format
-                   string as-is
+                /* Unrecognized conversion specifier.  Discard the
+                   unrecognized conversion, just keep the unrecognized
+                   conversion character.
                 */
-                zero_padding = 0;
+                zero_padding = false;
                     /* turn zero padding off for non-numeric convers. */
                 /* reset flags */
-                justify_left = 1;
+                justify_left = true;
                 min_field_width = 0;
-                /* discard the unrecognized conversion, just keep the
-                   unrecognized conversion character
-                */
                 str_arg = p;
                 str_arg_l = 0;
                 if (*p)
@@ -676,10 +704,10 @@ pm_vsnprintf(char *       const str,
                for unknown conversions)
             */
             {
-                int n = str_arg_l - zero_padding_insertion_ind;
+                int const n = str_arg_l - zero_padding_insertion_ind;
                 if (n > 0) {
                     if (str_l < str_m) {
-                        size_t avail = str_m-str_l;
+                        size_t const avail = str_m-str_l;
                         fast_memcpy(str + str_l,
                                     str_arg + zero_padding_insertion_ind,
                                     (n > avail ? avail : n));
diff --git a/lib/util/vasprintf.c b/lib/util/vasprintf.c
index a41cd7b5..209827eb 100644
--- a/lib/util/vasprintf.c
+++ b/lib/util/vasprintf.c
@@ -1,6 +1,6 @@
 #define _GNU_SOURCE
-   /* Due to conditional compilation, this is GNU source only if the C library
-      is GNU.
+   /* Because of conditional compilation, this is GNU source only if the C
+      library is GNU.
    */
 #include <stdlib.h>
 #include <string.h>
diff --git a/test/Execute-Tests b/test/Execute-Tests
index 39fab58c..047cf4a3 100755
--- a/test/Execute-Tests
+++ b/test/Execute-Tests
@@ -89,7 +89,7 @@ fi
 # For now only "SUCCESS" and "FAILURE" are used.
 declare -a array=(0 0 0 0 0 0)
 declare -a status=("SUCCESS" "FAILURE" "UNEXPECTED SUCCESS"
-                   "EXPECTED FAILURE" "NOT SUPPORTED" "TOTAL SUPPORTED")
+                   "EXPECTED FAILURE" "NOT TESTABLE" "TOTAL TESTABLE")
 
 # Copy test files to the current work directory
 
@@ -132,9 +132,9 @@ case $result in
         then let result=0;  rm  ${t%.test}.out ;
         else let result=1;
      fi
-     let supported=1 ;;
-80) let result=4 ; let supported=0;;
-*)  let result=1 ; let supported=1;;
+     let testable=1 ;;
+80) let result=4 ; let testable=0;;
+*)  let result=1 ; let testable=1;;
 esac
 
 # Report whether a single test succeeded or failed.
@@ -142,7 +142,7 @@ esac
 
 echo $t: ${status[${result}]}; echo
 let array[${result}]=${array[${result}]}+1
-let array[5]=${array[5]}+$supported
+let array[5]=${array[5]}+$testable
 
 done
 
@@ -180,7 +180,7 @@ echo "All tests done."
 date -R -u
 
 
-# Exit with status 0 if all supported tests succeeded, 1 otherwise.
+# Exit with status 0 if all possible tests succeeded, 1 otherwise.
 
 if [[ ${array[0]} -eq ${array[5]} ]]
 then exit 0
diff --git a/test/all-in-place.ok b/test/all-in-place.ok
index 1510f2e7..ca8ad8c3 100644
--- a/test/all-in-place.ok
+++ b/test/all-in-place.ok
@@ -324,13 +324,13 @@ tgatoppm: ok
 thinkjettopbm: ok
 tifftopnm: ok
 wbmptopbm: ok
+winicontopam: ok
 winicontoppm: ok
 xbmtopbm: ok
 ximtoppm: ok
 xpmtoppm: ok
 xvminitoppm: ok
 xwdtopnm: ok
-winicontopam: ok
 ybmtopbm: ok
 yuvsplittoppm: ok
 yuvtoppm: ok
diff --git a/test/gif-quant-roundtrip.test b/test/gif-quant-roundtrip.test
index 5e093b29..5e093b29 100644..100755
--- a/test/gif-quant-roundtrip.test
+++ b/test/gif-quant-roundtrip.test
diff --git a/test/pamchannel.test b/test/pamchannel.test
index f83dd3b6..f83dd3b6 100644..100755
--- a/test/pamchannel.test
+++ b/test/pamchannel.test
diff --git a/test/pgmcrater.test b/test/pgmcrater.test
index e8df9a23..e6942cee 100644..100755
--- a/test/pgmcrater.test
+++ b/test/pgmcrater.test
@@ -1,6 +1,5 @@
 #! /bin/bash
 # This script tests: pgmcrater
-# Also requires: pgmnoise
 
 # This test is sensitive to differences in floating point math.
 # With GCC slight results start to appear with -number 75 in
@@ -14,7 +13,7 @@
 # The slight differences in the image file are not discernable by
 # the naked eye.
 
-${PBM_BINPREFIX}pgmnoise --testrandom --quiet
+testrandom -q
 case $? in
    81)
       # Should print: 3828822912 65551
@@ -25,5 +24,5 @@ case $? in
        echo "Skipping: random number generator is not glibc." 1>&2
        exit 80;;
 
-   *)  exit 1;;  # pgmnoise --testrandom failed
+   *)  exit 1;;  # testrandom failed
 esac
diff --git a/test/pgmnoise.test b/test/pgmnoise.test
index 8ee2fccc..60d06510 100644..100755
--- a/test/pgmnoise.test
+++ b/test/pgmnoise.test
@@ -5,7 +5,7 @@
 # We first check whether random number generator is glibc rand().
 # If not, this test is skipped.
 
-${PBM_TESTPREFIX}pgmnoise --testrandom
+testrandom
 
 case $? in
    81)
@@ -18,5 +18,5 @@ case $? in
         echo "Skipping: random number generator is not glibc." 1>&2
         exit 80;;
 
-   *)   exit 1;;  # pgmnoise --testrandom failed
+   *)   exit 1;;  # testrandom failed
 esac
diff --git a/test/ppmforge.test b/test/ppmforge.test
index 014dc543..5ec37e9c 100644..100755
--- a/test/ppmforge.test
+++ b/test/ppmforge.test
@@ -1,11 +1,10 @@
 #! /bin/bash
 # This script tests: ppmforge
-# Also requires: pgmnoise
 
 # Use small x y values to avoid floating point issues.
 
 
-${PBM_BINPREFIX}pgmnoise --testrandom --quiet
+testrandom -q
 case $? in
    81)
       # Test 1: Should print: 3634219838 196623
@@ -16,5 +15,5 @@ case $? in
        echo "Skipping: random number generator is not glibc." 1>&2
        exit 80;;
 
-   *)  exit 1;;  # pgmnoise --testrandom failed
+   *)  exit 1;;  # testrandom failed
 esac
diff --git a/test/ppmhist.test b/test/ppmhist.test
index 55cbeac9..95fcd2f7 100755
--- a/test/ppmhist.test
+++ b/test/ppmhist.test
@@ -2,6 +2,6 @@
 # This script tests: ppmhist
 # Also requires: pgmramp
 
-${PBM_BINPREFIX}pgmramp -maxval=8 -lr 8 2 | ${PBM_TESTPREFIX}ppmhist
+${PBM_BINPREFIX}pgmramp -maxval=8 -lr 8 2 | ${PBM_TESTPREFIX}ppmhist -sort=rgb
 ${PBM_TESTPREFIX}ppmhist -map -sort=rgb testimg.ppm | cksum
 
diff --git a/test/ppmpat.test b/test/ppmpat.test
index 669cf17c..af0ce956 100755
--- a/test/ppmpat.test
+++ b/test/ppmpat.test
@@ -1,11 +1,10 @@
 #! /bin/bash
 # This script tests: ppmpat
-# Also requires: pgmnoise
 
 # TODO: Write tests for squig and poles.  It appears that they are
 # sensitive to differences in floating point math.
 
-${PBM_BINPREFIX}pgmnoise --testrandom --quiet
+testrandom -q
 case $? in
    81)
        # Test 1. Should print: 4008533639 781
@@ -31,5 +30,5 @@ case $? in
        echo "Skipping: random number generator is not glibc." 1>&2
        exit 80;;
 
-   *)  exit 1;;  # pgmnoise --testrandom failed
+   *)  exit 1;;  # testrandom failed
 esac
diff --git a/test/ppmrough.test b/test/ppmrough.test
index 1de8dd1b..92cc02d7 100644..100755
--- a/test/ppmrough.test
+++ b/test/ppmrough.test
@@ -1,9 +1,8 @@
 #! /bin/bash
 # This script tests: ppmrough
-# Also requires: pgmnoise
 
 
-${PBM_BINPREFIX}pgmnoise --testrandom --quiet
+testrandom -q
 case $? in
    81)
       # Should print: 378403602 30015
@@ -14,5 +13,5 @@ case $? in
        echo "Skipping: random number generator is not glibc." 1>&2
        exit 80;;
 
-   *)  exit 1;;  # pgmnoise --testrandom failed
+   *)  exit 1;;  # testrandom failed
 esac
diff --git a/test/winicon-roundtrip.test b/test/winicon-roundtrip.test
index f5f2926e..f5f2926e 100644..100755
--- a/test/winicon-roundtrip.test
+++ b/test/winicon-roundtrip.test
diff --git a/version.mk b/version.mk
index d6a12d17..534e652a 100644
--- a/version.mk
+++ b/version.mk
@@ -1,4 +1,4 @@
 NETPBM_MAJOR_RELEASE = 10
-NETPBM_MINOR_RELEASE = 63
-NETPBM_POINT_RELEASE = 1
+NETPBM_MINOR_RELEASE = 64
+NETPBM_POINT_RELEASE = 0