about summary refs log tree commit diff
path: root/converter/ppm
diff options
context:
space:
mode:
Diffstat (limited to 'converter/ppm')
-rw-r--r--converter/ppm/411toppm.c219
-rw-r--r--converter/ppm/Makefile7
-rw-r--r--converter/ppm/eyuvtoppm.c291
-rwxr-xr-xconverter/ppm/hpcdtoppm/pcdovtoppm2
-rw-r--r--converter/ppm/ilbm.h6
-rw-r--r--converter/ppm/ilbmtoppm.c558
-rw-r--r--converter/ppm/pc1toppm.c2
-rw-r--r--converter/ppm/pcxtoppm.c16
-rw-r--r--converter/ppm/picttoppm.c671
-rw-r--r--converter/ppm/ppmtoacad.c5
-rw-r--r--converter/ppm/ppmtoapplevol.c95
-rw-r--r--converter/ppm/ppmtoarbtxt.c1530
-rw-r--r--converter/ppm/ppmtoascii.c236
-rw-r--r--converter/ppm/ppmtobmp.c89
-rw-r--r--converter/ppm/ppmtogif.c50
-rw-r--r--converter/ppm/ppmtoicr.c532
-rw-r--r--converter/ppm/ppmtoilbm.c1810
-rw-r--r--converter/ppm/ppmtompeg/BUGS2
-rw-r--r--converter/ppm/ppmtompeg/CHANGES2
-rw-r--r--converter/ppm/ppmtompeg/Makefile69
-rw-r--r--converter/ppm/ppmtompeg/bframe.c2
-rw-r--r--converter/ppm/ppmtompeg/bitio.c4
-rw-r--r--converter/ppm/ppmtompeg/bsearch.c3
-rw-r--r--converter/ppm/ppmtompeg/combine.c10
-rw-r--r--converter/ppm/ppmtompeg/docs/template.param2
-rw-r--r--converter/ppm/ppmtompeg/examples/template.param2
-rw-r--r--converter/ppm/ppmtompeg/frame.c2
-rw-r--r--converter/ppm/ppmtompeg/gethostname.c1
-rw-r--r--converter/ppm/ppmtompeg/gethostname_win32.c2
-rw-r--r--converter/ppm/ppmtompeg/headers/all.h3
-rw-r--r--converter/ppm/ppmtompeg/headers/ansi.h76
-rw-r--r--converter/ppm/ppmtompeg/headers/bitio.h1
-rw-r--r--converter/ppm/ppmtompeg/headers/dct.h8
-rw-r--r--converter/ppm/ppmtompeg/headers/frame.h21
-rw-r--r--converter/ppm/ppmtompeg/headers/frames.h2
-rw-r--r--converter/ppm/ppmtompeg/headers/frametype.h2
-rw-r--r--converter/ppm/ppmtompeg/headers/general.h10
-rw-r--r--converter/ppm/ppmtompeg/headers/huff.h5
-rw-r--r--converter/ppm/ppmtompeg/headers/jpeg.h4
-rw-r--r--converter/ppm/ppmtompeg/headers/mheaders.h23
-rw-r--r--converter/ppm/ppmtompeg/headers/motion_search.h3
-rw-r--r--converter/ppm/ppmtompeg/headers/mpeg.h5
-rw-r--r--converter/ppm/ppmtompeg/headers/mproto.h47
-rw-r--r--converter/ppm/ppmtompeg/headers/mtypes.h15
-rw-r--r--converter/ppm/ppmtompeg/headers/opts.h15
-rw-r--r--converter/ppm/ppmtompeg/headers/parallel.h1
-rw-r--r--converter/ppm/ppmtompeg/headers/param.h18
-rw-r--r--converter/ppm/ppmtompeg/headers/prototypes.h35
-rw-r--r--converter/ppm/ppmtompeg/headers/rate.h20
-rw-r--r--converter/ppm/ppmtompeg/headers/specifics.h9
-rw-r--r--converter/ppm/ppmtompeg/huff.c3
-rw-r--r--converter/ppm/ppmtompeg/input.c14
-rw-r--r--converter/ppm/ppmtompeg/jpeg.c24
-rw-r--r--converter/ppm/ppmtompeg/jrevdct.c9
-rw-r--r--converter/ppm/ppmtompeg/mfwddct.c180
-rw-r--r--converter/ppm/ppmtompeg/mpeg.c25
-rw-r--r--converter/ppm/ppmtompeg/opts.c6
-rw-r--r--converter/ppm/ppmtompeg/parallel.c86
-rw-r--r--converter/ppm/ppmtompeg/param.c67
-rw-r--r--converter/ppm/ppmtompeg/ppmtompeg.c28
-rw-r--r--converter/ppm/ppmtompeg/psearch.c2
-rw-r--r--converter/ppm/ppmtompeg/psocket.c44
-rw-r--r--converter/ppm/ppmtompeg/rate.c20
-rw-r--r--converter/ppm/ppmtompeg/readframe.c83
-rw-r--r--converter/ppm/ppmtompeg/rgbtoycc.c6
-rw-r--r--converter/ppm/ppmtompeg/specifics.c24
-rw-r--r--converter/ppm/ppmtopcx.c20
-rw-r--r--converter/ppm/ppmtopict.c860
-rw-r--r--converter/ppm/ppmtopjxl.c190
-rw-r--r--converter/ppm/ppmtorgb3.c8
-rw-r--r--converter/ppm/ppmtospu.c593
-rw-r--r--converter/ppm/ppmtoterm.c238
-rw-r--r--converter/ppm/ppmtowinicon.c20
-rw-r--r--converter/ppm/ppmtoxpm.c20
-rw-r--r--converter/ppm/ppmtoyuv.c141
-rw-r--r--converter/ppm/ppmtoyuvsplit.c12
-rw-r--r--converter/ppm/sldtoppm.c151
-rw-r--r--converter/ppm/sputoppm.c135
-rw-r--r--converter/ppm/tgatoppm.c2
-rw-r--r--converter/ppm/winicontoppm.c822
-rw-r--r--converter/ppm/xim.h2
-rw-r--r--converter/ppm/ximtoppm.c4
-rw-r--r--converter/ppm/xpmtoppm.c1149
-rw-r--r--converter/ppm/yuvsplittoppm.c16
-rw-r--r--converter/ppm/yuvtoppm.c255
85 files changed, 6894 insertions, 4908 deletions
diff --git a/converter/ppm/411toppm.c b/converter/ppm/411toppm.c
index 6ece4c4b..eb2372a5 100644
--- a/converter/ppm/411toppm.c
+++ b/converter/ppm/411toppm.c
@@ -30,7 +30,7 @@
 
    Bryan Henderson reworked the program to use the Netpbm libraries to
    create the PPM output and follow some other Netpbm conventions.
-   2001-03-03.  Bryan's contribution is public domain.  
+   2001-03-03.  Bryan's contribution is public domain.
 */
 /*
  * Copyright (c) 1995 The Regents of the University of California.
@@ -56,22 +56,21 @@
  * HEADER FILES *
  *==============*/
 #include <stdio.h>
-#include <stdlib.h>
 
 #include "pm_c_util.h"
-#include "ppm.h"
-#include "shhopt.h"
 #include "mallocvar.h"
+#include "shhopt.h"
+#include "ppm.h"
 
 typedef unsigned char uint8;
 
 #define CHOP(x)     ((x < 0) ? 0 : ((x > 255) ? 255 : x))
 
-struct cmdline_info {
+struct CmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
-    const char *input_filespec;  /* Filespec of input file */
+    const char * inputFileName;
     int width;
     int height;
 };
@@ -79,38 +78,42 @@ struct cmdline_info {
 
 
 static void
-parse_command_line(int argc, char ** argv,
-                   struct cmdline_info *cmdline_p) {
+parseCommandLine(int argc, const char ** argv,
+                 struct CmdlineInfo *cmdlineP) {
 /*----------------------------------------------------------------------------
    Note that the file spec array we return is stored in the storage that
    was passed to us as the argv array.
 -----------------------------------------------------------------------------*/
 
-    optStruct *option_def = malloc(100*sizeof(optStruct));
+    optEntry * option_def;
         /* Instructions to OptParseOptions2 on how to parse our options.
          */
-    optStruct2 opt;
+    optStruct3 opt;
 
     unsigned int option_def_index;
 
-    option_def_index = 0;   /* incremented by OPTENTRY */
-    OPTENTRY(0,   "width",      OPT_INT,    &cmdline_p->width,          0);
-    OPTENTRY(0,   "height",     OPT_INT,    &cmdline_p->height,         0);
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    option_def_index = 0;   /* incremented by OPTENT3 */
+    OPTENT3(0,   "width",      OPT_INT,    &cmdlineP->width,  NULL,   0);
+    OPTENT3(0,   "height",     OPT_INT,    &cmdlineP->height, NULL,   0);
 
     /* Set the defaults */
-    cmdline_p->width = 64;
-    cmdline_p->height = 48;
+    cmdlineP->width = 64;
+    cmdlineP->height = 48;
 
     opt.opt_table = option_def;
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
     
-    optParseOptions2(&argc, argv, opt, 0);
-        /* Uses and sets argc, argv, and some of *cmdline_p and others. */
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
-    if (cmdline_p->width <= 0)
+    if (cmdlineP->width <= 0)
         pm_error("-width must be positive.");
-    if (cmdline_p->height <= 0)
+    if (cmdlineP->width %4 != 0)
+        pm_error("-width must be a multiple of 4.");
+    if (cmdlineP->height <= 0)
         pm_error("-height must be positive.");
 
     if (argc > 2)
@@ -118,145 +121,111 @@ parse_command_line(int argc, char ** argv,
                  "You supplied %d", argc-1);
     else {
         if (argc > 1)
-            cmdline_p->input_filespec = argv[1];
+            cmdlineP->inputFileName = argv[1];
         else
-            cmdline_p->input_filespec = "-";
+            cmdlineP->inputFileName = "-";
     }
+    free(option_def);
 }
 
 
 
-static void 
-ReadYUV(FILE *fpointer, const int width, const int height, 
-        uint8 ** const orig_y, uint8 ** const orig_cb, 
-        uint8 ** const orig_cr) {
+static void
+ReadYUV(FILE  * const ifP,
+        uint8 * const inbuff) {
+
+    size_t bytesRead;
 
-    int y, x, i;
+    bytesRead = fread(inbuff, 1, 6, ifP);
 
-    for (y = 0; y < height; y++) {
-        for (x = 0, i = 0; x < width; x+=4, i++) {
-            fread(orig_y[y]+x , 1, 4, fpointer);
-            fread(orig_cb[y]+i, 1, 1, fpointer);
-            fread(orig_cr[y]+i, 1, 1, fpointer);
-        }
-    }
+    if (bytesRead != 6 ) {
+        if (feof(ifP))
+            pm_error("Premature end of input.");
+        else
+            pm_error("Error reading input.");
+     }
 }
 
 
 
 static void
-AllocYCC(const int width, const int height,
-         uint8 *** const orig_yP, uint8 *** const orig_crP, 
-         uint8 *** const orig_cbP) {
-    int y;
-
-    MALLOCARRAY_NOFAIL(*orig_yP, height);
-    for (y = 0; y < height; y++) 
-        MALLOCARRAY_NOFAIL((*orig_yP)[y], width);
-
-    MALLOCARRAY_NOFAIL(*orig_crP, height);
-    for (y = 0; y < height; y++) 
-        MALLOCARRAY_NOFAIL((*orig_crP)[y], width/4);
-
-    MALLOCARRAY_NOFAIL(*orig_cbP, height);
-    for (y = 0; y < height; y++) 
-        MALLOCARRAY_NOFAIL((*orig_cbP)[y], width/4);
-}
+YUVtoPPM(FILE  * const ifP,
+         int     const width,
+         int     const height,
+         pixel * const pixrow ) {
 
+    unsigned int col;
 
+    for (col = 0; col < width; ++col) {
 
-static void 
-YUVtoPPM(const int width, const int height, 
-         uint8 ** const orig_y, 
-         uint8 ** const orig_cb,
-         uint8 ** const orig_cr,
-         pixel ** const ppm_image
-         ) {
-    int     **Y, **U, **V;
-    int    y;
+        uint8 inbuff[6];
 
-    /* first, allocate tons of memory */
+        uint8 * const origY  = &inbuff[0];
+        uint8 * const origCb = &inbuff[4];
+        uint8 * const origCr = &inbuff[5];
+        int   y, u, v;
+        int32_t tempR, tempG, tempB;
+        pixval r, g, b;
 
-    MALLOCARRAY_NOFAIL(Y, height);
-    for (y = 0; y < height; y++) 
-        MALLOCARRAY_NOFAIL(Y[y], width);
-    
-    MALLOCARRAY_NOFAIL(U, height);
-    for (y = 0; y < height; y++) 
-        MALLOCARRAY_NOFAIL(U[y], width / 4);
-
-    MALLOCARRAY_NOFAIL(V, height);
-    for (y = 0; y < height; y++) 
-        MALLOCARRAY_NOFAIL(V[y], width/4);
-
-	for ( y = 0; y < height; y ++ ) {
-        int x;
-	    for ( x = 0; x < width/4; x ++ ) {
-            U[y][x] = orig_cb[y][x] - 128;
-            V[y][x] = orig_cr[y][x] - 128;
-	    }
-    }
-	for ( y = 0; y < height; y ++ ) {
-        int x;
-	    for ( x = 0; x < width; x ++ )
-	    {
-            Y[y][x] = orig_y[y][x] - 16;
-	    }
-    }
-    for ( y = 0; y < height; y++ ) {
-        int x;
-        for ( x = 0; x < width; x++ ) {
-            pixval r, g, b;
-            long   tempR, tempG, tempB;
-            /* look at yuvtoppm source for explanation */
-            
-            tempR = 104635*V[y][x/4];
-            tempG = -25690*U[y][x/4] + -53294 * V[y][x/4];
-            tempB = 132278*U[y][x/4];
-            
-            tempR += (Y[y][x]*76310);
-            tempG += (Y[y][x]*76310);
-            tempB += (Y[y][x]*76310);
-            
-            r = CHOP((int)(tempR >> 16));
-            g = CHOP((int)(tempG >> 16));
-            b = CHOP((int)(tempB >> 16));
-
-            PPM_ASSIGN(ppm_image[y][x], r, g, b);
+        if (col % 4 == 0) {
+            ReadYUV(ifP, inbuff);
+            u = origCb[0] - 128;
+            v = origCr[0] - 128;
         }
+
+        y = origY[col % 4] - 16;
+
+        tempR = 104635 * v              + y * 76310;
+        tempG = -25690 * u + -53294 * v + y * 76310;
+        tempB = 132278 * u              + y * 76310;
+
+        r = CHOP((int)(tempR >> 16));
+        g = CHOP((int)(tempG >> 16));
+        b = CHOP((int)(tempB >> 16));
+        
+        PPM_ASSIGN(pixrow[col], r, g, b);
     }
-    /* We really should free the Y, U, and V arrays now */
 }
 
 
 
 int
-main(int argc, char **argv) {
-    FILE *infile;
-    struct cmdline_info cmdline;
-    uint8 **orig_y, **orig_cb, **orig_cr;
-    pixel **ppm_image;
+main(int argc, const char **argv) {
 
-    ppm_init(&argc, argv);
+    pixval const maxval = 255;
+    struct CmdlineInfo cmdline;
+    FILE  * ifP;
+    pixel * pixrow;
+    unsigned int row;
 
-    parse_command_line(argc, argv, &cmdline);
+    pm_proginit(&argc, argv);
 
-    AllocYCC(cmdline.width, cmdline.height, &orig_y, &orig_cr, &orig_cb);
-    ppm_image = ppm_allocarray(cmdline.width, cmdline.height);
+    parseCommandLine(argc, argv, &cmdline);
 
-    pm_message("Reading (%dx%d):  %s\n", cmdline.width, cmdline.height, 
-               cmdline.input_filespec);
-    infile = pm_openr(cmdline.input_filespec);
-    ReadYUV(infile, cmdline.width, cmdline.height, orig_y, orig_cb, orig_cr);
-    pm_close(infile);
+    pixrow = ppm_allocrow(cmdline.width);
 
-    YUVtoPPM(cmdline.width, cmdline.height, orig_y, orig_cb, orig_cr, 
-             ppm_image);
+    pm_message("Reading (%ux%u): '%s'", cmdline.width, cmdline.height,
+               cmdline.inputFileName);
 
-    ppm_writeppm(stdout, ppm_image, cmdline.width, cmdline.height, 255, 0);
+    ifP = pm_openr(cmdline.inputFileName);
 
-    ppm_freearray(ppm_image, cmdline.height);
+    ppm_writeppminit(stdout, cmdline.width, cmdline.height, maxval, 0);
+
+    for (row = 0; row < cmdline.height; ++row) {
+        YUVtoPPM(ifP, cmdline.width, cmdline.height, pixrow);
+        ppm_writeppmrow(stdout, pixrow, cmdline.width, maxval, 0);
+    }
+
+    if (fgetc(ifP) != EOF)
+        pm_message("Extraneous data at end of image.");
+
+    pm_close(ifP);
+    ppm_freerow(pixrow);
 
     return 0;
 }
 
+/*
+   By default a .411 file is width=64, height=48, 4608 bytes.
+   There is no header.
+*/
diff --git a/converter/ppm/Makefile b/converter/ppm/Makefile
index adc3a400..003ef8d3 100644
--- a/converter/ppm/Makefile
+++ b/converter/ppm/Makefile
@@ -12,15 +12,16 @@ SUBDIRS = hpcdtoppm ppmtompeg
 PORTBINARIES =	411toppm eyuvtoppm gouldtoppm ilbmtoppm imgtoppm \
 		leaftoppm mtvtoppm neotoppm \
 		pcxtoppm pc1toppm pi1toppm picttoppm pjtoppm \
-		ppmtoacad ppmtoarbtxt \
+		ppmtoacad ppmtoapplevol ppmtoarbtxt ppmtoascii \
 		ppmtobmp ppmtoeyuv ppmtogif ppmtoicr ppmtoilbm \
 		ppmtoleaf ppmtolj ppmtomitsu ppmtoneo \
 		ppmtopcx ppmtopi1 ppmtopict ppmtopj \
-		ppmtopjxl ppmtoppm ppmtopuzz ppmtorgb3 ppmtosixel ppmtoterm \
+		ppmtopjxl ppmtoppm ppmtopuzz ppmtorgb3 \
+		ppmtosixel ppmtospu ppmtoterm \
 		ppmtowinicon ppmtoxpm ppmtoyuv ppmtoyuvsplit \
 		qrttoppm rawtoppm rgb3toppm spctoppm \
 		sputoppm tgatoppm winicontoppm ximtoppm xpmtoppm xvminitoppm \
-		yuvtoppm yuvsplittoppm
+		yuvsplittoppm yuvtoppm 
 
 MATHBINARIES = sldtoppm 
 
diff --git a/converter/ppm/eyuvtoppm.c b/converter/ppm/eyuvtoppm.c
index 33d57409..910a125b 100644
--- a/converter/ppm/eyuvtoppm.c
+++ b/converter/ppm/eyuvtoppm.c
@@ -36,9 +36,9 @@
 #include <unistd.h>
 
 #include "pm_c_util.h"
-#include "ppm.h"
 #include "shhopt.h"
 #include "mallocvar.h"
+#include "ppm.h"
 
 typedef unsigned char uint8;
 
@@ -46,11 +46,11 @@ typedef unsigned char uint8;
 
 
 
-struct cmdline_info {
+struct CmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
-    const char *input_filespec;  /* Filespecs of input file */
+    const char * inputFileName;  /* Name of input file */
     unsigned int width;
     unsigned int height;
 };
@@ -59,11 +59,13 @@ struct cmdline_info {
 
 static void
 parseCommandLine(int argc, char ** argv,
-                 struct cmdline_info *cmdlineP) {
+                 struct CmdlineInfo * const cmdlineP) {
 
     optStruct3 opt;   /* Set by OPTENT3 */
     unsigned int option_def_index;
-    optEntry *option_def = malloc(100*sizeof(optEntry));
+    optEntry * option_def;
+
+    MALLOCARRAY_NOFAIL(option_def, 100);
 
     option_def_index = 0;   /* incremented by OPTENT3 */
     OPTENT3('w', "width",     OPT_UINT,  &cmdlineP->width,   NULL,         0);
@@ -77,7 +79,7 @@ parseCommandLine(int argc, char ** argv,
     opt.short_allowed = TRUE;
     opt.allowNegNum = FALSE;
 
-    optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
+    pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
 
     if (cmdlineP->width == 0)
         pm_error("The width cannot be zero.");
@@ -92,32 +94,34 @@ parseCommandLine(int argc, char ** argv,
 
 
     if (argc-1 == 0) 
-        cmdlineP->input_filespec = "-";
+        cmdlineP->inputFileName = "-";
     else if (argc-1 != 1)
         pm_error("Program takes zero or one argument (filename).  You "
-                 "specified %d", argc-1);
+                 "specified %u", argc-1);
     else
-        cmdlineP->input_filespec = argv[1];
+        cmdlineP->inputFileName = argv[1];
 
+    free(option_def);
 }
 
 
 
 static uint8 ** 
-AllocUint8Array(unsigned int const cols, unsigned int const rows) {
+allocUint8Array(unsigned int const cols,
+                unsigned int const rows) {
 
-    uint8 **retval;
-    unsigned int y;
+    uint8 ** retval;
+    unsigned int row;
 
     MALLOCARRAY(retval, rows);
     if (retval == NULL)
-        pm_error("Unable to allocate storage for %d x %d byte array.",
+        pm_error("Unable to allocate storage for %u x %u byte array.",
                  cols, rows);
 
-    for (y = 0; y < rows; y++) {
-        MALLOCARRAY(retval[y], cols);
-        if (retval[y] == NULL)
-            pm_error("Unable to allocate storage for %d x %d byte array.",
+    for (row = 0; row < rows; ++row) {
+        MALLOCARRAY(retval[row], cols);
+        if (retval[row] == NULL)
+            pm_error("Unable to allocate storage for %u x %u byte array.",
                      cols, rows);
     }
     return retval;
@@ -125,216 +129,191 @@ AllocUint8Array(unsigned int const cols, unsigned int const rows) {
 
 
 
-static int ** 
-AllocIntArray(unsigned int const cols, unsigned int const rows) {
+static void 
+freeUint8Array(uint8 **     const array,
+               unsigned int const rows) {
 
-    int **retval;
-    unsigned int y;
+    unsigned int row;
 
-    MALLOCARRAY(retval, rows);
-    if (retval == NULL)
-        pm_error("Unable to allocate storage for %d x %d byte array.",
-                 cols, rows);
+    for (row = 0; row < rows; ++row)
+        free(array[row]);
 
-    for (y = 0; y < rows; y++) {
-        MALLOCARRAY(retval[y], cols);
-        if (retval[y] == NULL)
-            pm_error("Unable to allocate storage for %d x %d byte array.",
-                     cols, rows);
-    }
-    return retval;
+    free(array);
 }
 
 
 
 static void
-allocateStorage(int const cols, int const rows,
-                int *** const YP, int *** const UP, int *** const VP,
-                pixel *** const pixelsP, 
-                uint8 *** const orig_yP, uint8 *** const orig_cbP,
-                uint8 *** const orig_crP) {
-
-    *YP = AllocIntArray(cols, rows);
-    *UP = AllocIntArray(cols, rows);
-    *VP = AllocIntArray(cols, rows);
-
-    *pixelsP = ppm_allocarray(cols, rows);
-
-    *orig_yP  = AllocUint8Array(cols, rows);
-    *orig_cbP = AllocUint8Array(cols, rows);
-    *orig_crP = AllocUint8Array(cols, rows);
-}
-
-
-
-static void 
-FreeArray(void ** const array, unsigned int const rows) {
-
-    unsigned int y;
-
-    for (y = 0; y < rows; y++)
-        free(array[y]);
-    free(array);
+allocateStorage(unsigned int const cols,
+                unsigned int const rows,
+                uint8 ***    const orig_yP,
+                uint8 ***    const orig_cbP,
+                uint8 ***    const orig_crP) {
+
+    *orig_yP  = allocUint8Array(cols, rows);
+    *orig_cbP = allocUint8Array(cols, rows);
+    *orig_crP = allocUint8Array(cols, rows);
 }
 
 
 
 static void
-freeStorage(int const rows,
-            int ** const Y, int ** const U, int ** const V,
-            pixel ** const pixels, 
-            uint8 ** const orig_y, uint8 ** const orig_cb,
-            uint8 ** const orig_cr) {
+freeStorage(unsigned int const rows,
+            uint8 **     const orig_y,
+            uint8 **     const orig_cb,
+            uint8 **     const orig_cr) {
     
-    FreeArray((void**) orig_y, rows); 
-    FreeArray((void**) orig_cb, rows); 
-    FreeArray((void**) orig_cr, rows);
-
-    ppm_freearray(pixels, rows);
+    freeUint8Array(orig_y,  rows); 
+    freeUint8Array(orig_cb, rows); 
+    freeUint8Array(orig_cr, rows);
 
-    FreeArray((void**) Y, rows);
-    FreeArray((void**) U, rows);
-    FreeArray((void**) V, rows);
 }
 
 
 
 static void 
-YUVtoPPM(unsigned int const cols, unsigned int const rows,
-         uint8 ** const orig_y, uint8 ** const orig_cb, uint8 ** const orig_cr,
-         pixel ** const pixels, 
-         int ** const Y, int ** const U, int ** const V) {
+YUVtoPPM(FILE *       const ofP,
+         unsigned int const cols,
+         unsigned int const rows,
+         uint8 **     const orig_y,
+         uint8 **     const orig_cb,
+         uint8 **     const orig_cr) { 
 /*----------------------------------------------------------------------------
    Convert the YUV image in arrays orig_y[][], orig_cb[][], and orig_cr[][]
-   to a PPM image in the array (already allocated) pixels[][].
-
-   Use the preallocated areas Y[][], U[][], and V[][] for working space.
+   to a PPM image and write it to file *ofP.
 -----------------------------------------------------------------------------*/
+    pixel * const pixrow = ppm_allocrow(cols);
     
-    int y;
+    unsigned int row;
 
-    for ( y = 0; y < rows/2; y ++ ) {
-        int x;
-        for ( x = 0; x < cols/2; x ++ ) {
-            U[y][x] = orig_cb[y][x] - 128;
-            V[y][x] = orig_cr[y][x] - 128;
-        }
-    }
+    ppm_writeppminit(ofP, cols, rows, 255, FALSE);
 
-    for ( y = 0; y < rows; y ++ ) {
-        int x;
-        for ( x = 0; x < cols; x ++ ) 
-            Y[y][x] = orig_y[y][x] - 16;
-    }
+    for (row = 0; row < rows; ++row) {
+        unsigned int col;
 
-    for ( y = 0; y < rows; y++ ) {
-        int x;
-        for ( x = 0; x < cols; x++ ) {
+        for (col = 0; col < cols; ++col) {
+            int const y =  orig_y[row][col] - 16;
+            int const u =  orig_cb[row/2][col/2] - 128;
+            int const v =  orig_cr[row/2][col/2] - 128;
             long   tempR, tempG, tempB;
-            int     r, g, b;
+            int    r, g, b;
             /* look at yuvtoppm source for explanation */
 
-            tempR = 104635*V[y/2][x/2];
-            tempG = -25690*U[y/2][x/2] + -53294 * V[y/2][x/2];
-            tempB = 132278*U[y/2][x/2];
-
-            tempR += (Y[y][x]*76310);
-            tempG += (Y[y][x]*76310);
-            tempB += (Y[y][x]*76310);
+            tempR = 104635*v + 76310*y;
+            tempG = -25690*u + -53294*v + 76310*y;
+            tempB = 132278*u + 76310*y;
             
             r = CHOP((int)(tempR >> 16));
             g = CHOP((int)(tempG >> 16));
             b = CHOP((int)(tempB >> 16));
             
-            PPM_ASSIGN(pixels[y][x], r, g, b);
+            PPM_ASSIGN(pixrow[col], r, g, b);
         }
+        ppm_writeppmrow(stdout, pixrow, cols, 255, FALSE);
     }
+    ppm_freerow(pixrow);
 }
 
 
 
 static void 
-ReadYUV(FILE * const yuvfile,
-        unsigned int const cols, unsigned int const rows,
-        uint8 ** const orig_y, 
-        uint8 ** const orig_cb, 
-        uint8 ** const orig_cr,
-        bool * const eofP) {
-
-    unsigned int y;
-    int c;
-
-    c = fgetc(yuvfile);
-    if (c < 0)
-        *eofP = TRUE;
-    else {
-        *eofP = FALSE;
-        ungetc(c, yuvfile);
+ReadYUV(FILE *       const ifP,
+        unsigned int const cols,
+        unsigned int const rows,
+        uint8 **     const orig_y, 
+        uint8 **     const orig_cb, 
+        uint8 **     const orig_cr,
+        bool *       const eofP) {
+
+    unsigned int row;
+    unsigned int totalRead;
+    bool eof;
+
+    eof = false;  /* initial value */
+    totalRead = 0;  /* initial value */
+
+    for (row = 0; row < rows && !eof; ++row) {        /* Y */
+        size_t bytesRead;
+
+        bytesRead = fread(orig_y[row], 1, cols, ifP);
+        totalRead += bytesRead;
+        if (bytesRead != cols)
+            eof = true;
     }
-    if (!*eofP) {
-        for (y = 0; y < rows; y++)            /* Y */
-            fread(orig_y[y], 1, cols, yuvfile);
         
-        for (y = 0; y < rows / 2; y++)            /* U */
-            fread(orig_cb[y], 1, cols / 2, yuvfile);
+    for (row = 0; row < rows / 2 && !eof; ++row) {  /* U */
+        size_t bytesRead;
+
+        bytesRead = fread(orig_cb[row], 1, cols / 2, ifP);
+        totalRead += bytesRead;
+        if (bytesRead != cols / 2)
+            eof = true;
+    }
         
-        for (y = 0; y < rows / 2; y++)            /* V */
-            fread(orig_cr[y], 1, cols / 2, yuvfile);
-        if (feof(yuvfile))
-            pm_error("Premature end of file reading EYUV input file");
+    for (row = 0; row < rows / 2 && !eof; ++row) { /* V */
+        size_t bytesRead;
+
+        bytesRead = fread(orig_cr[row], 1, cols / 2, ifP);
+        totalRead += bytesRead;
+        if (bytesRead != cols / 2)
+            eof = true;
     }
+
+    if (eof) {
+        if (totalRead == 0)
+            *eofP = TRUE;
+        else
+            pm_error("Premature end of file reading EYUV input file");
+    } else
+        *eofP = FALSE;
 }
 
 
 
 int
-main(int argc, char **argv) {
+main(int argc, const char **argv) {
 
-    FILE *ifp;
-    struct cmdline_info cmdline;
+    FILE * ifP;
+    struct CmdlineInfo cmdline;
     unsigned int frameSeq;
 
     /* The following are addresses of malloc'ed storage areas for use by
        subroutines.
     */
-    int ** Y;
-    int ** U;
-    int ** V;
-    uint8 **orig_y, **orig_cb, **orig_cr;
-    pixel ** pixels;
+    uint8 ** orig_y;
+    uint8 ** orig_cb;
+    uint8 ** orig_cr;
+    bool eof;
 
-    ppm_init(&argc, argv);
+    pm_proginit(&argc, argv);
 
-    parseCommandLine(argc, argv, &cmdline);
+    parseCommandLine(argc, (char **)argv, &cmdline);
 
-    /* Allocate all the storage once, to save time. */
+    /* Allocate all the storage at once, to save time. */
     allocateStorage(cmdline.width, cmdline.height,
-                    &Y, &U, &V, &pixels, &orig_y, &orig_cb, &orig_cr);
+                    &orig_y, &orig_cb, &orig_cr);
 
-    ifp = pm_openr(cmdline.input_filespec);
+    ifP = pm_openr(cmdline.inputFileName);
 
-    for (frameSeq = 0; !feof(ifp); frameSeq++) {
-        bool eof;
+    for (frameSeq = 0, eof = false; !eof; ++frameSeq) {
 
-        ReadYUV(ifp, cmdline.width, cmdline.height, 
+        ReadYUV(ifP, cmdline.width, cmdline.height, 
                 orig_y, orig_cb, orig_cr, &eof);
+
         if (!eof) {
             pm_message("Converting Frame %u", frameSeq);
 
-            YUVtoPPM(cmdline.width, cmdline.height, orig_y, orig_cb, orig_cr, 
-                     pixels, Y, U, V);
-            ppm_writeppm(stdout, pixels, cmdline.width, cmdline.height, 
-                         255, FALSE);
-        }
+            YUVtoPPM(stdout, cmdline.width, cmdline.height,
+                     orig_y, orig_cb, orig_cr);
+        } else if (frameSeq == 0)
+            pm_error("Empty EYUV input file");
     }
 
-    freeStorage(cmdline.height, Y, U, V, pixels, orig_y, orig_cb, orig_cr);
-
-    pm_close(ifp);
-    exit(0);
-}
-
+    freeStorage(cmdline.height, orig_y, orig_cb, orig_cr);
 
+    pm_close(ifP);
 
+    return 0;
+}
 
 
diff --git a/converter/ppm/hpcdtoppm/pcdovtoppm b/converter/ppm/hpcdtoppm/pcdovtoppm
index 1f8b3006..dbf6f53d 100755
--- a/converter/ppm/hpcdtoppm/pcdovtoppm
+++ b/converter/ppm/hpcdtoppm/pcdovtoppm
@@ -195,7 +195,7 @@ if [ ${#imagefiles[*]} -gt 0 ] ; then
     rowfiles="$rowfiles $rowfile"
 fi
 
-if [ ${#rowfiles[*]} == 1 ]; then
+if [ ${#rowfiles[*]} = 1 ]; then
     cat $rowfiles
 else
     if [ "$colors" = "n" ] ; then
diff --git a/converter/ppm/ilbm.h b/converter/ppm/ilbm.h
index 68657956..dbe47758 100644
--- a/converter/ppm/ilbm.h
+++ b/converter/ppm/ilbm.h
@@ -23,7 +23,7 @@ typedef struct {
 #define mskNone                 0
 #define mskHasMask              1
 #define mskHasTransparentColor  2
-#define mskLasso                3       /* not supported */
+#define mskLasso                3       /* can't handle this */
 #define mskMAXKNOWN             mskLasso
 static const char * mskNAME[] = { 
     "none", "mask plane", "transparent color", "lasso" 
@@ -127,8 +127,8 @@ typedef struct {
 #define CLUT_RED    1
 #define CLUT_GREEN  2
 #define CLUT_BLUE   3
-#define CLUT_HUE    4   /* not supported */
-#define CLUT_SAT    5   /* not supported */
+#define CLUT_HUE    4   /* can't handle this */
+#define CLUT_SAT    5   /* can't handle this */
 
 
 /* unofficial DCOL chunk for direct-color */
diff --git a/converter/ppm/ilbmtoppm.c b/converter/ppm/ilbmtoppm.c
index 209f53c0..280ca939 100644
--- a/converter/ppm/ilbmtoppm.c
+++ b/converter/ppm/ilbmtoppm.c
@@ -9,7 +9,7 @@
 ** documentation.  This software is provided "as is" without express or
 ** implied warranty.
 **
-** Modified by Mark Thompson on 10/4/90 to accomodate 24-bit IFF files
+** Modified by Mark Thompson on 10/4/90 to accommodate 24-bit IFF files
 ** as used by ASDG, NewTek, etc.
 **
 ** Modified by Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
@@ -89,11 +89,10 @@ static unsigned char *ilbmrow;
 static pixel *pixelrow;
 static FILE *maskfile = NULL;
 static bit *maskrow = NULL;
-static short wrotemask = 0;
+static bool wrotemask;
 static IFF_ID typeid;       /* ID_ILBM, ID_RGBN, ID_RGB8 */
 
-static pixel *transpColor = NULL;       /* transparent color */
-static char *transpName = NULL;
+static char *transpName = NULL;  /* -transparent option value */
 
 static bool debug = FALSE;
 
@@ -192,8 +191,8 @@ read_bytes(FILE *          const ifP,
 
 
 static unsigned char
-get_byte(ifp, iffid, counter)
-    FILE* ifp;
+get_byte(ifP, iffid, counter)
+    FILE* ifP;
     IFF_ID iffid;
     long *counter;
 {
@@ -204,9 +203,9 @@ get_byte(ifp, iffid, counter)
             pm_error("insufficient data in %s chunk", ID2string(iffid));
         --(*counter);
     }
-    i = getc(ifp);
+    i = getc(ifP);
     if( i == EOF )
-        readerr(ifp, iffid);
+        readerr(ifP, iffid);
 
     return (unsigned char) i;
 }
@@ -311,7 +310,7 @@ display_chunk(FILE *        const ifP,
 
 
 static void
-read_cmap(FILE *     const ifp,
+read_cmap(FILE *     const ifP,
           IFF_ID     const iffid,
           long       const chunksize,
           ColorMap * const cmap) {
@@ -321,7 +320,7 @@ read_cmap(FILE *     const ifp,
     colors = chunksize / 3;
     if( colors == 0 ) {
         pm_error("warning - empty %s colormap", ID2string(iffid));
-        skip_chunk(ifp, iffid, chunksize);
+        skip_chunk(ifP, iffid, chunksize);
     } else {
         unsigned int i;
         if( cmap->color )               /* prefer CMAP-chunk over CMYK-chunk */
@@ -331,30 +330,30 @@ read_cmap(FILE *     const ifp,
         
         for( i = 0; i < colors; ++i ) {
             int r, g, b;
-            r = get_byte(ifp, iffid, &chunksize);
-            g = get_byte(ifp, iffid, &chunksize);
-            b = get_byte(ifp, iffid, &chunksize);
+            r = get_byte(ifP, iffid, &chunksize);
+            g = get_byte(ifP, iffid, &chunksize);
+            b = get_byte(ifP, iffid, &chunksize);
             PPM_ASSIGN(cmap->color[i], r, g, b);
         }
-        chunk_end(ifp, iffid, chunksize);
+        chunk_end(ifP, iffid, chunksize);
     }
 }
 
 
 
 static void
-read_cmyk(FILE *     const ifp,
+read_cmyk(FILE *     const ifP,
           IFF_ID     const iffid,
           long       const chunksize,
           ColorMap * const cmap) {
 
     if( HAS_COLORMAP(cmap) ) {      /* prefer RGB color map */
-        skip_chunk(ifp, iffid, chunksize);
+        skip_chunk(ifP, iffid, chunksize);
     } else {
         long const colors = chunksize/4;
         if( colors == 0 ) {
             pm_error("warning - empty %s colormap", ID2string(iffid));
-            skip_chunk(ifp, iffid, chunksize);
+            skip_chunk(ifP, iffid, chunksize);
         } else {
             unsigned int i;
             cmap->color = ppm_allocrow(colors);
@@ -362,10 +361,10 @@ read_cmyk(FILE *     const ifp,
             
             for( i = 0; i < colors; ++i ) {
                 int c, m, y, k;
-                c = get_byte(ifp, iffid, &chunksize);
-                m = get_byte(ifp, iffid, &chunksize);
-                y = get_byte(ifp, iffid, &chunksize);
-                k = get_byte(ifp, iffid, &chunksize);
+                c = get_byte(ifP, iffid, &chunksize);
+                m = get_byte(ifP, iffid, &chunksize);
+                y = get_byte(ifP, iffid, &chunksize);
+                k = get_byte(ifP, iffid, &chunksize);
 
                 {
                     pixval const red = 
@@ -381,7 +380,7 @@ read_cmyk(FILE *     const ifp,
                     PPM_ASSIGN(cmap->color[i], red, green, blue);
                 }
             }
-            chunk_end(ifp, iffid, chunksize);
+            chunk_end(ifP, iffid, chunksize);
         }
     }
 }
@@ -389,7 +388,7 @@ read_cmyk(FILE *     const ifp,
 
 
 static void
-read_clut(FILE *        const ifp,
+read_clut(FILE *        const ifP,
           IFF_ID        const iffid,
           unsigned long const chunksize,
           ColorMap *    const cmap) {
@@ -397,7 +396,7 @@ read_clut(FILE *        const ifp,
     if (chunksize != CLUTSize) {
         pm_message("invalid size for %s chunk - skipping it", 
                    ID2string(iffid));
-        skip_chunk(ifp, iffid, chunksize);
+        skip_chunk(ifP, iffid, chunksize);
     } else {
         long type;
         unsigned char * lut;
@@ -406,12 +405,12 @@ read_clut(FILE *        const ifp,
 
         remainingChunksize = chunksize;  /* initial value */
 
-        type = get_big_long(ifp, iffid, &remainingChunksize);
-        get_big_long(ifp, iffid, &remainingChunksize); /* skip reserved fld */
+        type = get_big_long(ifP, iffid, &remainingChunksize);
+        get_big_long(ifP, iffid, &remainingChunksize); /* skip reserved fld */
 
         MALLOCARRAY_NOFAIL(lut, 256);
         for( i = 0; i < 256; ++i )
-            lut[i] = get_byte(ifp, iffid, &remainingChunksize);
+            lut[i] = get_byte(ifP, iffid, &remainingChunksize);
 
         switch( type ) {
         case CLUT_MONO:
@@ -436,6 +435,27 @@ read_clut(FILE *        const ifp,
 
 
 
+static void
+warnNonsquarePixels(uint8_t const xAspect,
+                    uint8_t const yAspect) {
+
+    if (xAspect != yAspect) {
+        const char * const baseMsg = "warning - non-square pixels";
+
+        if (pm_have_float_format())
+            pm_message("%s; to fix do a 'pamscale -%cscale %g'",
+                       baseMsg,
+                       xAspect > yAspect ? 'x' : 'y',
+                       xAspect > yAspect ? 
+                       (float)xAspect/yAspect : 
+                       (float)yAspect/xAspect);
+        else
+            pm_message("%s", baseMsg);
+    }
+}
+
+
+
 static BitMapHeader *
 read_bmhd(FILE *        const ifP,
           IFF_ID        const iffid,
@@ -443,7 +463,7 @@ read_bmhd(FILE *        const ifP,
 
     BitMapHeader * bmhdP;
 
-    if( chunksize != BitMapHeaderSize ) {
+    if (chunksize != BitMapHeaderSize) {
         pm_message("invalid size for %s chunk - skipping it", 
                    ID2string(iffid));
         skip_chunk(ifP, iffid, chunksize);
@@ -470,24 +490,24 @@ read_bmhd(FILE *        const ifP,
         bmhdP->pageWidth  = get_big_short(ifP, iffid, &remainingChunksize);
         bmhdP->pageHeight = get_big_short(ifP, iffid, &remainingChunksize);
 
-        if( verbose ) {
-            if( typeid == ID_ILBM )
+        if (verbose) {
+            if (typeid == ID_ILBM)
                 pm_message("dimensions: %dx%d, %d planes", 
                            bmhdP->w, bmhdP->h, bmhdP->nPlanes);
             else
                 pm_message("dimensions: %dx%d", bmhdP->w, bmhdP->h);
 
-            if( typeid == ID_ILBM || typeid == ID_PBM ) {
+            if (typeid == ID_ILBM || typeid == ID_PBM) {
                 pm_message("compression: %s",
                            bmhdP->compression <= cmpMAXKNOWN ?
                            cmpNAME[bmhdP->compression] : "unknown");
 
-                switch( bmhdP->masking ) {
+                switch(bmhdP->masking) {
                 case mskNone:
                     break;
                 case mskHasMask:
                 case mskHasTransparentColor:
-                    if( !maskfile )
+                    if (!maskfile)
                         pm_message("use '-maskfile <filename>' "
                                    "to generate a PBM mask file from %s", 
                                    mskNAME[bmhdP->masking]);
@@ -501,27 +521,20 @@ read_bmhd(FILE *        const ifP,
                 }
             }
             else    /* RGBN/RGB8 */
-                if( !maskfile )
+                if (!maskfile)
                     pm_message("use '-maskfile <filename>' "
                                "to generate a PBM mask file "
                                "from genlock bits");
         }
 
         /* fix aspect ratio */
-        if( bmhdP->xAspect == 0 || bmhdP->yAspect == 0 ) {
+        if (bmhdP->xAspect == 0 || bmhdP->yAspect == 0) {
             pm_message("warning - illegal aspect ratio %d:%d, using 1:1", 
                        bmhdP->xAspect, bmhdP->yAspect);
             bmhdP->xAspect = bmhdP->yAspect = 1;
         }
 
-        if( bmhdP->xAspect != bmhdP->yAspect ) {
-            pm_message("warning - non-square pixels; "
-                       "to fix do a 'pnmscale -%cscale %g'",
-                       bmhdP->xAspect > bmhdP->yAspect ? 'x' : 'y',
-                       bmhdP->xAspect > bmhdP->yAspect ? 
-                       (float)(bmhdP->xAspect)/bmhdP->yAspect : 
-                       (float)(bmhdP->yAspect)/bmhdP->xAspect);
-        }
+        warnNonsquarePixels(bmhdP->xAspect, bmhdP->yAspect);
     }
     return bmhdP;
 }
@@ -630,42 +643,42 @@ decode_mask(FILE *          const ifP,
     unsigned char *ilp;
 
     cols = bmhdP->w;
-    switch( bmhdP->masking ) {
+    switch (bmhdP->masking) {
     case mskNone:
         break;
     case mskHasMask:        /* mask plane */
         read_ilbm_plane(ifP, remainingChunksizeP, RowBytes(cols), 
                         bmhdP->compression);
-        if( maskfile ) {
+        if (maskfile) {
             ilp = ilbmrow;
             cbit = 7;
-            for( col = 0; col < cols; col++, cbit-- ) {
-                if( cbit < 0 ) {
+            for (col = 0; col < cols; ++col, --cbit) {
+                if (cbit < 0) {
                     cbit = 7;
-                    ilp++;
+                    ++ilp;
                 }
-                if( *ilp & bit_mask[cbit] )
+                if (*ilp & bit_mask[cbit])
                     maskrow[col] = PBM_BLACK;
                 else
                     maskrow[col] = PBM_WHITE;
             }
             pbm_writepbmrow(maskfile, maskrow, cols, 0);
-            wrotemask = 1;
+            wrotemask = true;
         }
         break;
     case mskHasTransparentColor:
-        if( !chunkyrow )
+        if (!chunkyrow)
             pm_error("decode_mask(): chunkyrow == NULL - can't happen");
         
-        if( maskfile ) {
-            for( col = 0; col < cols; col++ ) {
-                if( chunkyrow[col] == bmhdP->transparentColor )
+        if (maskfile) {
+            for (col = 0; col < cols; ++col) {
+                if (chunkyrow[col] == bmhdP->transparentColor)
                     maskrow[col] = PBM_WHITE;
                 else
                     maskrow[col] = PBM_BLACK;
             }
             pbm_writepbmrow(maskfile, maskrow, cols, 0);
-                wrotemask = 1;
+                wrotemask = true;
         }
         break;
     case mskLasso:
@@ -760,83 +773,66 @@ multi_free(cmap)
 }
 
 
+
 /****************************************************************************
  Colormap handling
  ****************************************************************************/
 
+
+
 static void
-prepareCmap(const BitMapHeader * const bmhd,
-            ColorMap *           const cmap) {
-/*----------------------------------------------------------------------------
-   This is a really ugly subroutine that 1) analyzes a colormap and its
-   context (returning the analysis in global variables); and 2) modifies that
-   color map, because it's really one type of data structure as input and
-   another as output.
+analyzeCmapSamples(const ColorMap * const cmapP,
+                   pixval *         const maxSampleP,
+                   bool *           const shiftedP) {
 
------------------------------------------------------------------------------*/
-    pixval colmaxval = 0;
-    int shifted = 1;
-    int i, r, g, b;
-
-    if( bmhd ) {
-        if( bmhd->masking == mskHasTransparentColor || 
-            bmhd->masking == mskLasso ) {
-            unsigned short const transpIdx = bmhd->transparentColor;
-            if( !transpName ) {
-                MALLOCVAR_NOFAIL(transpColor);
-                if (HAS_COLORMAP(cmap)) {
-                    if( transpIdx >= cmap->ncolors ) {
-                        pm_message("using default transparent color (black)");
-                        PPM_ASSIGN(*transpColor, 0, 0, 0);
-                    } else
-                        *transpColor = cmap->color[transpIdx];
-                } else {
-                    /* The color index is just a direct gray level */
-                    PPM_ASSIGN(*transpColor, transpIdx, transpIdx, transpIdx);
-                }
-            }
-        }
+    pixval       maxSample;
+    bool         shifted;
+    unsigned int i;
+        
+    for (i = 0, maxSample = 0, shifted = true; i < cmapP->ncolors; ++i) {
+        pixval const r = PPM_GETR(cmapP->color[i]);
+        pixval const g = PPM_GETG(cmapP->color[i]);
+        pixval const b = PPM_GETB(cmapP->color[i]);
 
-        if( bmhd->flags & BMHD_FLAGS_CMAPOK )
-            return;
+        maxSample = MAX(maxSample, MAX(r, MAX(g, b)));
+
+        if (r & 0x0f || g & 0x0f || b & 0x0f)
+            shifted = false;
     }
+    *shiftedP   = shifted;
+    *maxSampleP = maxSample;
+}
 
-    if( !HAS_COLORMAP(cmap) )
-        return;
 
-    for( i = 0; i < cmap->ncolors; i++ ) {
-        r = PPM_GETR(cmap->color[i]);
-        if( r > colmaxval ) colmaxval = r;
-        if( r & 0x0f ) shifted = 0;
 
-        g = PPM_GETG(cmap->color[i]);
-        if( g > colmaxval ) colmaxval = g;
-        if( g & 0x0f ) shifted = 0;
+static void
+transformCmap(ColorMap * const cmapP) {
 
-        b = PPM_GETB(cmap->color[i]);
-        if( b > colmaxval ) colmaxval = b;
-        if( b & 0x0f ) shifted = 0;
-    }
+    pixval maxSample;
+        /* The maximum sample value in *cmapP input */
+    bool shifted;
+        /* Samples in the *cmapP input appear to be 4 bit (maxval 15) original
+           values shifted left 4 places to make 8 bit (maxval 255) samples.
+        */
 
-#ifdef DEBUG
-    pm_message("colormap maxval is %d", colmaxval);
-#endif
-    if( colmaxval == 0 )
+    analyzeCmapSamples(cmapP, &maxSample, &shifted);
+
+    if (maxSample == 0)
         pm_message("warning - black colormap");
-    else
-    if( shifted || colmaxval <= 15 ) {
-        if( !adjustcolors ) {
+    else if (shifted || maxSample <= 15) {
+        if (!adjustcolors) {
             pm_message("warning - probably %s4-bit colormap",
-                        shifted ? "shifted " : "");
-            pm_message("    use '-adjustcolors' to scale colormap to 8 bits");
-        }
-        else {
+                       shifted ? "shifted " : "");
+            pm_message("Use '-adjustcolors' to scale colormap to 8 bits");
+        } else {
+            unsigned int i;
             pm_message("scaling colormap to 8 bits");
-            for( i = 0; i < cmap->ncolors; i++ ) {
-                r = PPM_GETR(cmap->color[i]);
-                g = PPM_GETG(cmap->color[i]);
-                b = PPM_GETB(cmap->color[i]);
-                if( shifted ) {
+            for (i = 0; i < cmapP->ncolors; ++i) {
+                pixval r, g, b;
+                r = PPM_GETR(cmapP->color[i]);
+                g = PPM_GETG(cmapP->color[i]);
+                b = PPM_GETB(cmapP->color[i]);
+                if (shifted) {
                     r >>= 4;
                     g >>= 4;
                     b >>= 4;
@@ -844,13 +840,74 @@ prepareCmap(const BitMapHeader * const bmhd,
                 r *= FACTOR_4BIT;
                 g *= FACTOR_4BIT;
                 b *= FACTOR_4BIT;
-                PPM_ASSIGN(cmap->color[i], r, g, b);
+                PPM_ASSIGN(cmapP->color[i], r, g, b);
             }
         }
     }
 }
 
 
+
+static pixel *
+transpColor(const BitMapHeader * const bmhdP,
+            ColorMap *           const cmapP,
+            const char *         const transpName,
+            pixval               const maxval) {
+
+    pixel * transpColorP;
+
+    if (bmhdP) {
+        if (bmhdP->masking == mskHasTransparentColor || 
+            bmhdP->masking == mskLasso) {
+            MALLOCVAR_NOFAIL(transpColorP);
+
+            if (transpName)
+                *transpColorP = ppm_parsecolor(transpName, maxval);
+            else {
+                unsigned short const transpIdx = bmhdP->transparentColor;
+                if (HAS_COLORMAP(cmapP)) {
+                    if (transpIdx >= cmapP->ncolors) {
+                        pm_message("using default transparent color (black)");
+                        PPM_ASSIGN(*transpColorP, 0, 0, 0);
+                    } else
+                        *transpColorP = cmapP->color[transpIdx];
+                } else {
+                    /* The color index is just a direct gray level */
+                    PPM_ASSIGN(*transpColorP, transpIdx, transpIdx, transpIdx);
+                }
+            }
+        } else
+            transpColorP = NULL;
+    } else
+        transpColorP = NULL;
+
+    return transpColorP;
+}
+
+
+
+static void
+prepareCmap(const BitMapHeader * const bmhdP,
+            ColorMap *           const cmapP) {
+/*----------------------------------------------------------------------------
+   This is a really ugly subroutine that 1) analyzes a colormap and its
+   context (returning the analysis in global variables); and 2) modifies that
+   color map, because it's really one type of data structure as input and
+   another as output.
+-----------------------------------------------------------------------------*/
+    bool bmhdCmapOk;
+
+    if (bmhdP)
+        bmhdCmapOk = (bmhdP->flags & BMHD_FLAGS_CMAPOK);
+    else
+        bmhdCmapOk = false;
+
+    if (HAS_COLORMAP(cmapP) && !bmhdCmapOk)
+        transformCmap(cmapP);
+}
+
+
+
 static pixval
 lookup_red(cmap, oldval)
     ColorMap *cmap;
@@ -990,18 +1047,18 @@ get_color(cmap, idx, red, green, blue)
  ****************************************************************************/
 
 static void
-std_to_ppm(FILE *         const ifp, 
+std_to_ppm(FILE *         const ifP, 
            long           const chunksize, 
-           BitMapHeader * const bmhd, 
+           BitMapHeader * const bmhdP, 
            ColorMap *     const cmap, 
            long           const viewportmodes);
 
 
 
 static void
-ham_to_ppm(FILE *         const ifp, 
+ham_to_ppm(FILE *         const ifP, 
            long           const chunksize, 
-           BitMapHeader * const bmhd, 
+           BitMapHeader * const bmhdP, 
            ColorMap *     const cmap, 
            long           const viewportmodes) {
 
@@ -1010,9 +1067,9 @@ ham_to_ppm(FILE *         const ifp,
     rawtype *rawrow;
     unsigned char hamlut[256];
 
-    cols = bmhd->w;
-    rows = bmhd->h;
-    hambits = bmhd->nPlanes - 2;
+    cols = bmhdP->w;
+    rows = bmhdP->h;
+    hambits = bmhdP->nPlanes - 2;
     hammask = (1 << hambits) - 1;
     hamshift = 8 - hambits;
     hammask2 = (1 << hamshift) - 1;
@@ -1021,15 +1078,16 @@ ham_to_ppm(FILE *         const ifp,
         int const assumed_viewportmodes = viewportmodes & ~(vmHAM);
 
         pm_message("%d-plane HAM?? - interpreting image as a normal ILBM", 
-                   bmhd->nPlanes);
-        std_to_ppm(ifp, chunksize, bmhd, cmap, assumed_viewportmodes);
+                   bmhdP->nPlanes);
+        std_to_ppm(ifP, chunksize, bmhdP, cmap, assumed_viewportmodes);
         return;
     } else {
         unsigned long remainingChunksize;
+        pixel * transpColorP;
 
         pm_message("input is a %sHAM%d file", 
                    HAS_MULTIPALETTE(cmap) ? "multipalette " : "", 
-                   bmhd->nPlanes);
+                   bmhdP->nPlanes);
 
         if( HAS_COLORLUT(cmap) || HAS_MONOLUT(cmap) ) {
             pm_message("warning - color lookup tables ignored in HAM");
@@ -1048,10 +1106,7 @@ ham_to_ppm(FILE *         const ifp,
             cmap->monolut = hamlut;
         }
 
-        if( transpName ) {
-            MALLOCVAR_NOFAIL(transpColor);
-            *transpColor = ppm_parsecolor(transpName, MAXCOLVAL);
-        }
+        transpColorP = transpColor(bmhdP, cmap, transpName, MAXCOLVAL);
 
         if( HAS_MULTIPALETTE(cmap) )
             multi_init(cmap, viewportmodes);
@@ -1068,15 +1123,15 @@ ham_to_ppm(FILE *         const ifp,
             if( HAS_MULTIPALETTE(cmap) )
                 multi_update(cmap, row);
 
-            decode_row(ifp, &remainingChunksize, rawrow, bmhd->nPlanes, bmhd);
-            decode_mask(ifp, &remainingChunksize, rawrow, bmhd);
+            decode_row(ifP, &remainingChunksize, rawrow, bmhdP->nPlanes, bmhdP);
+            decode_mask(ifP, &remainingChunksize, rawrow, bmhdP);
 
             r = g = b = 0;
             for( col = 0; col < cols; col++ ) {
                 int idx = rawrow[col] & hammask;
 
-                if( transpColor && maskrow && maskrow[col] == PBM_WHITE )
-                    pixelrow[col] = *transpColor;
+                if( transpColorP && maskrow && maskrow[col] == PBM_WHITE )
+                    pixelrow[col] = *transpColorP;
                 else {
                     switch((rawrow[col] >> hambits) & 0x03) {
                     case HAMCODE_CMAP:
@@ -1103,7 +1158,7 @@ ham_to_ppm(FILE *         const ifp,
             }
             ppm_writeppmrow(stdout, pixelrow, cols, MAXCOLVAL, 0);
         }
-        chunk_end(ifp, ID_BODY, remainingChunksize);
+        chunk_end(ifP, ID_BODY, remainingChunksize);
     }
 }
 
@@ -1112,27 +1167,28 @@ ham_to_ppm(FILE *         const ifp,
 static void
 std_to_ppm(FILE *         const ifP, 
            long           const chunksize, 
-           BitMapHeader * const bmhd, 
+           BitMapHeader * const bmhdP, 
            ColorMap *     const cmap, 
            long           const viewportmodes) {
 
     if (viewportmodes & vmHAM) {
-        ham_to_ppm(ifP, chunksize, bmhd, cmap, viewportmodes);
+        ham_to_ppm(ifP, chunksize, bmhdP, cmap, viewportmodes);
     } else {
-        unsigned int const cols = bmhd->w;
-        unsigned int const rows = bmhd->h;
+        unsigned int const cols = bmhdP->w;
+        unsigned int const rows = bmhdP->h;
 
         rawtype *rawrow;
         unsigned int row, col;
         pixval maxval;
         unsigned long remainingChunksize;
+        pixel * transpColorP;
 
-        pm_message("input is a %d-plane %s%sILBM", bmhd->nPlanes,
+        pm_message("input is a %d-plane %s%sILBM", bmhdP->nPlanes,
                    HAS_MULTIPALETTE(cmap) ? "multipalette " : "",
                    viewportmodes & vmEXTRA_HALFBRITE ? "EHB " : ""
             );
 
-        if( bmhd->nPlanes > MAXPLANES )
+        if( bmhdP->nPlanes > MAXPLANES )
             pm_error("too many planes (max %d)", MAXPLANES);
 
         if( HAS_COLORMAP(cmap) ) {
@@ -1142,15 +1198,12 @@ std_to_ppm(FILE *         const ifP,
         }
         else {
             pm_message("no colormap - interpreting values as grayscale");
-            maxval = lut_maxval(cmap, pm_bitstomaxval(bmhd->nPlanes));
+            maxval = lut_maxval(cmap, pm_bitstomaxval(bmhdP->nPlanes));
             if( maxval > PPM_OVERALLMAXVAL )
                 pm_error("nPlanes is too large");
         }
 
-        if( transpName ) {
-            MALLOCVAR_NOFAIL(transpColor);
-            *transpColor = ppm_parsecolor(transpName, maxval);
-        }
+        transpColorP = transpColor(bmhdP, cmap, transpName, maxval);
 
         rawrow = alloc_rawrow(cols);
 
@@ -1166,13 +1219,13 @@ std_to_ppm(FILE *         const ifP,
             if( HAS_MULTIPALETTE(cmap) )
                 multi_update(cmap, row);
 
-            decode_row(ifP, &remainingChunksize, rawrow, bmhd->nPlanes, bmhd);
-            decode_mask(ifP, &remainingChunksize, rawrow, bmhd);
+            decode_row(ifP, &remainingChunksize, rawrow, bmhdP->nPlanes, bmhdP);
+            decode_mask(ifP, &remainingChunksize, rawrow, bmhdP);
 
             for( col = 0; col < cols; col++ ) {
                 pixval r, g, b;
-                if( transpColor && maskrow && maskrow[col] == PBM_WHITE )
-                    pixelrow[col] = *transpColor;
+                if( transpColorP && maskrow && maskrow[col] == PBM_WHITE )
+                    pixelrow[col] = *transpColorP;
                 else {
                     get_color(cmap, rawrow[col], &r, &g, &b);
                     PPM_ASSIGN(pixelrow[col], r, g, b);
@@ -1200,6 +1253,7 @@ deep_to_ppm(FILE *         const ifP,
     rawtype *Rrow, *Grow, *Brow;
     pixval maxval;
     unsigned long remainingChunksize;
+    pixel * transpColorP;
 
     pm_message("input is a deep (%d-bit) ILBM", bmhdP->nPlanes);
     if( planespercolor > MAXPLANES )
@@ -1216,11 +1270,8 @@ deep_to_ppm(FILE *         const ifP,
     if( maxval > PPM_OVERALLMAXVAL )
         pm_error("nPlanes is too large");
 
-    if( transpName ) {
-        MALLOCVAR_NOFAIL(transpColor);
-        *transpColor = ppm_parsecolor(transpName, maxval);
-    }
-
+    transpColorP = transpColor(bmhdP, cmap, transpName, maxval);
+        
     Rrow = alloc_rawrow(cols);
     Grow = alloc_rawrow(cols);
     Brow = alloc_rawrow(cols);
@@ -1236,8 +1287,8 @@ deep_to_ppm(FILE *         const ifP,
         decode_mask(ifP, &remainingChunksize, NULL, bmhdP);
 
         for( col = 0; col < cols; col++ ) {
-            if( transpColor && maskrow && maskrow[col] == PBM_WHITE )
-                pixelrow[col] = *transpColor;
+            if( transpColorP && maskrow && maskrow[col] == PBM_WHITE )
+                pixelrow[col] = *transpColorP;
             else
                 PPM_ASSIGN(pixelrow[col],   lookup_red(cmap, Rrow[col]),
                                             lookup_green(cmap, Grow[col]),
@@ -1268,6 +1319,7 @@ dcol_to_ppm(FILE *         const ifP,
     pixval maxval, redmaxval, greenmaxval, bluemaxval;
     pixval *redtable, *greentable, *bluetable;
     unsigned long remainingChunksize;
+    pixel * transpColorP;
 
     pm_message("input is a %d:%d:%d direct color ILBM",
                 redplanes, greenplanes, blueplanes);
@@ -1318,10 +1370,7 @@ dcol_to_ppm(FILE *         const ifP,
         for (i = 0; i <= bluemaxval; ++i)
             bluetable[i] = ROUNDDIV(i * maxval, bluemaxval);
     }
-    if( transpName ) {
-        MALLOCVAR_NOFAIL(transpColor);
-        *transpColor = ppm_parsecolor(transpName, maxval);
-    }
+    transpColorP = transpColor(bmhdP, cmap, transpName, maxval);
 
     Rrow = alloc_rawrow(cols);
     Grow = alloc_rawrow(cols);
@@ -1338,8 +1387,8 @@ dcol_to_ppm(FILE *         const ifP,
         decode_mask(ifP, &remainingChunksize, NULL, bmhdP);
 
         for( col = 0; col < cols; col++ ) {
-            if( transpColor && maskrow && maskrow[col] == PBM_WHITE )
-                pixelrow[col] = *transpColor;
+            if( transpColorP && maskrow && maskrow[col] == PBM_WHITE )
+                pixelrow[col] = *transpColorP;
             else
                 PPM_ASSIGN( pixelrow[col],  redtable[Rrow[col]],
                                             greentable[Grow[col]],
@@ -1374,6 +1423,7 @@ ipbm_to_ppm(FILE *         const ifP,
     int col, row;
     pixval maxval;
     unsigned long remainingChunksize;
+    pixel * transpColorP;
 
     pm_message("input is a %sPBM ", 
                HAS_MULTIPALETTE(cmap) ? "multipalette " : "");
@@ -1392,10 +1442,7 @@ ipbm_to_ppm(FILE *         const ifP,
         maxval = lut_maxval(cmap, pm_bitstomaxval(bmhdP->nPlanes));
     }
 
-    if( transpName ) {
-        MALLOCVAR_NOFAIL(transpColor);
-        *transpColor = ppm_parsecolor(transpName, maxval);
-    }
+    transpColorP = transpColor(bmhdP, cmap, transpName, maxval);
 
     if( HAS_MULTIPALETTE(cmap) )
         multi_init(cmap, viewportmodes);
@@ -1414,8 +1461,8 @@ ipbm_to_ppm(FILE *         const ifP,
 
         for( col = 0; col < cols; col++ ) {
             pixval r, g, b;
-            if( transpColor && maskrow && maskrow[col] == PBM_WHITE )
-                pixelrow[col] = *transpColor;
+            if( transpColorP && maskrow && maskrow[col] == PBM_WHITE )
+                pixelrow[col] = *transpColorP;
             else {
                 get_color(cmap, ilbmrow[col], &r, &g, &b);
                 PPM_ASSIGN(pixelrow[col], r, g, b);
@@ -1438,48 +1485,54 @@ rgbn_to_ppm(FILE *         const ifP,
     unsigned int const rows = bmhdP->h;
     unsigned int const cols = bmhdP->w;
 
-    int row, col, count, genlock, tries;
-    pixval r, g, b, maxval;
+    unsigned int row;
+    unsigned int count;
+    pixval maxval;
     unsigned long remainingChunksize;
+    pixel * transpColorP;
 
     pm_message("input is a %d-bit RGB image", (typeid == ID_RGB8 ? 8 : 4));
 
-    if( bmhdP->compression != 4 )
+    if (bmhdP->compression != 4)
         pm_error("invalid compression mode for %s: %d (must be 4)", 
                  ID2string(typeid), bmhdP->compression);
-
-    switch( typeid ) {
-        case ID_RGBN:
-            if( bmhdP->nPlanes != 13 )
-                pm_error("invalid number of planes for %s: %d (must be 13)", 
-                         ID2string(typeid), bmhdP->nPlanes);
-            maxval = lut_maxval(cmap, 15);
-            break;
-        case ID_RGB8:
-            if( bmhdP->nPlanes != 25 )
-                pm_error("invalid number of planes for %s: %d (must be 25)", 
-                         ID2string(typeid), bmhdP->nPlanes);
-            maxval = 255;
-            break;
-        default:
-            pm_error("rgbn_to_ppm(): invalid IFF ID %s - can't happen", 
-                     ID2string(typeid));
+    
+    switch (typeid) {
+    case ID_RGBN:
+        if (bmhdP->nPlanes != 13)
+            pm_error("invalid number of planes for %s: %d (must be 13)", 
+                     ID2string(typeid), bmhdP->nPlanes);
+        maxval = lut_maxval(cmap, 15);
+        break;
+    case ID_RGB8:
+        if (bmhdP->nPlanes != 25)
+            pm_error("invalid number of planes for %s: %d (must be 25)", 
+                     ID2string(typeid), bmhdP->nPlanes);
+        maxval = 255;
+        break;
+    default:
+        pm_error("rgbn_to_ppm(): invalid IFF ID %s - can't happen", 
+                 ID2string(typeid));
     }
 
-    if( transpName ) {
-        MALLOCVAR_NOFAIL(transpColor);
-        *transpColor = ppm_parsecolor(transpName, maxval);
-    }
+    transpColorP = transpColor(bmhdP, cmap, transpName, maxval);
 
     ppm_writeppminit(stdout, cols, rows, maxval, 0);
 
-    remainingChunksize = chunksize;  /* initial value */
-    count = 0;
-    for( row = 0; row < rows; row++ ) {
-        for( col = 0; col < cols; col++ ) {
+    for (row = 0, count = 0, remainingChunksize = chunksize;
+         row < rows;
+         ++row) {
+
+        unsigned int col;
+
+        for (col = 0; col < cols; ++col) {
+            unsigned int tries;
+            unsigned int genlock;
+            pixval r, g, b;
+
             tries = 0;
-            while( !count ) {
-                if( typeid == ID_RGB8 ) {
+            while (count == 0) {
+                if (typeid == ID_RGB8) {
                     r = lookup_red(cmap,   get_byte(ifP, ID_BODY, 
                                                     &remainingChunksize));
                     g = lookup_green(cmap, get_byte(ifP, ID_BODY,
@@ -1489,47 +1542,46 @@ rgbn_to_ppm(FILE *         const ifP,
                     count = get_byte(ifP, ID_BODY, &remainingChunksize);
                     genlock = count & 0x80;
                     count &= 0x7f;
-                }
-                else {
-                    int word;
-                    word = get_big_short(ifP, ID_BODY, &remainingChunksize);
+                } else {
+                    unsigned int const word =
+                        get_big_short(ifP, ID_BODY, &remainingChunksize);
                     r = lookup_red(cmap, (word & 0xf000) >> 12);
                     g = lookup_green(cmap, (word & 0x0f00) >> 8);
                     b = lookup_blue(cmap, (word & 0x00f0) >> 4);
                     genlock = word & 0x0008;
                     count = word & 0x0007;
                 }
-                if( !count ) {
+                if (!count) {
                     count = get_byte(ifP, ID_BODY, &remainingChunksize);
-                    if( !count )
+                    if (count == 0)
                         count =
                             get_big_short(ifP, ID_BODY, &remainingChunksize);
-                        if( !count )
-                            ++tries;
+                    if (count == 0)
+                        ++tries;
                 }
             }
-            if( tries ) {
-                pm_message("warning - repeat count 0 at col %d row %d: "
-                           "skipped %d RGB entr%s",
+            if (tries > 0) {
+                pm_message("warning - repeat count 0 at col %u row %u: "
+                           "skipped %u RGB entr%s",
                             col, row, tries, (tries == 1 ? "y" : "ies"));
             }
-            if( maskfile ) {
+            if (maskfile) {
                 /* genlock bit set -> transparent */
-                if( genlock )
+                if (genlock)
                     maskrow[col] = PBM_WHITE;
                 else
                     maskrow[col] = PBM_BLACK;
             }
-            if( transpColor && maskrow && maskrow[col] == PBM_WHITE )
-                pixelrow[col] = *transpColor;
+            if (transpColorP && maskrow && maskrow[col] == PBM_WHITE)
+                pixelrow[col] = *transpColorP;
             else
                 PPM_ASSIGN(pixelrow[col], r, g, b);
             --count;
         }
         ppm_writeppmrow(stdout, pixelrow, cols, maxval, 0);
-        if( maskfile ) {
+        if (maskfile) {
             pbm_writepbmrow(maskfile, maskrow, cols, 0);
-            wrotemask = 1;
+            wrotemask = true;
         }
     }
     chunk_end(ifP, ID_BODY, remainingChunksize);
@@ -1918,13 +1970,13 @@ PCHG_ConvertBig(PCHGHeader *    const PCHG,
 
 
 static void
-read_pchg(FILE *     const ifp,
+read_pchg(FILE *     const ifP,
           IFF_ID     const iffid,
           long       const chunksize,
           ColorMap * const cmap) {
 
     if( cmap->mp_type >= MP_TYPE_PCHG ) {
-        skip_chunk(ifp, iffid, chunksize);
+        skip_chunk(ifP, iffid, chunksize);
     } else {
         PCHGHeader      PCHG;
         unsigned char   *data;
@@ -1938,15 +1990,15 @@ read_pchg(FILE *     const ifp,
 
         remainingChunksize = chunksize;  /* initial value */
 
-        PCHG.Compression = get_big_short(ifp, iffid, &remainingChunksize);
-        PCHG.Flags       = get_big_short(ifp, iffid, &remainingChunksize);
-        PCHG.StartLine   = get_big_short(ifp, iffid, &remainingChunksize);
-        PCHG.LineCount   = get_big_short(ifp, iffid, &remainingChunksize);
-        PCHG.ChangedLines= get_big_short(ifp, iffid, &remainingChunksize);
-        PCHG.MinReg      = get_big_short(ifp, iffid, &remainingChunksize);
-        PCHG.MaxReg      = get_big_short(ifp, iffid, &remainingChunksize);
-        PCHG.MaxChanges  = get_big_short(ifp, iffid, &remainingChunksize);
-        PCHG.TotalChanges= get_big_long(ifp, iffid, &remainingChunksize);
+        PCHG.Compression = get_big_short(ifP, iffid, &remainingChunksize);
+        PCHG.Flags       = get_big_short(ifP, iffid, &remainingChunksize);
+        PCHG.StartLine   = get_big_short(ifP, iffid, &remainingChunksize);
+        PCHG.LineCount   = get_big_short(ifP, iffid, &remainingChunksize);
+        PCHG.ChangedLines= get_big_short(ifP, iffid, &remainingChunksize);
+        PCHG.MinReg      = get_big_short(ifP, iffid, &remainingChunksize);
+        PCHG.MaxReg      = get_big_short(ifP, iffid, &remainingChunksize);
+        PCHG.MaxChanges  = get_big_short(ifP, iffid, &remainingChunksize);
+        PCHG.TotalChanges= get_big_long(ifP, iffid, &remainingChunksize);
 
 #ifdef DEBUG
         pm_message("PCHG StartLine   : %d", PCHG.StartLine);
@@ -1961,17 +2013,17 @@ read_pchg(FILE *     const ifp,
             long treesize, compsize;
 
             CompHdr.CompInfoSize     =
-                get_big_long(ifp, iffid, &remainingChunksize);
+                get_big_long(ifP, iffid, &remainingChunksize);
             CompHdr.OriginalDataSize =
-                get_big_long(ifp, iffid, &remainingChunksize);
+                get_big_long(ifP, iffid, &remainingChunksize);
 
             treesize = CompHdr.CompInfoSize;
             MALLOCARRAY_NOFAIL(comptree, treesize);
-            read_bytes(ifp, treesize, comptree, iffid, &remainingChunksize);
+            read_bytes(ifP, treesize, comptree, iffid, &remainingChunksize);
 
             compsize = remainingChunksize;
             MALLOCARRAY_NOFAIL(compdata, compsize);
-            read_bytes(ifp, compsize, compdata, iffid, &remainingChunksize);
+            read_bytes(ifP, compsize, compdata, iffid, &remainingChunksize);
 
             datasize = CompHdr.OriginalDataSize;
             MALLOCARRAY_NOFAIL(data, datasize);
@@ -1986,7 +2038,7 @@ read_pchg(FILE *     const ifp,
 #endif
             datasize = remainingChunksize;
             MALLOCARRAY_NOFAIL(data, datasize);
-            read_bytes(ifp, datasize, data, iffid, &remainingChunksize);
+            read_bytes(ifP, datasize, data, iffid, &remainingChunksize);
         }
 
         if( PCHG.Flags & PCHGF_USE_ALPHA )
@@ -2025,7 +2077,7 @@ read_pchg(FILE *     const ifp,
                          ID2string(iffid));
         }
         free(data);
-        chunk_end(ifp, iffid, remainingChunksize);
+        chunk_end(ifP, iffid, remainingChunksize);
     }
 }
 
@@ -2050,7 +2102,7 @@ ignored_iffid(IFF_ID       const iffid,
 
 
 static void 
-process_body( FILE *          const ifp,
+process_body( FILE *          const ifP,
               long            const chunksize,
               BitMapHeader *  const bmhdP,
               ColorMap *      const cmap,
@@ -2060,19 +2112,19 @@ process_body( FILE *          const ifp,
               DirectColor *   const dcol,
               int *           const viewportmodesP) {
     
-    if( bmhdP == NULL )
+    if (bmhdP == NULL)
         pm_error("%s chunk without %s chunk", 
                  ID2string(ID_BODY), ID2string(ID_BMHD));
 
     prepareCmap(bmhdP, cmap);
 
     pixelrow = ppm_allocrow(bmhdP->w);
-    if( maskfile ) {
+    if (maskfile) {
         maskrow = pbm_allocrow(bmhdP->w);
         pbm_writepbminit(maskfile, bmhdP->w, bmhdP->h, 0);
     }
 
-    if( typeid == ID_ILBM ) {
+    if (typeid == ID_ILBM) {
         int isdeep;
 
         MALLOCARRAY_NOFAIL(ilbmrow, RowBytes(bmhdP->w));
@@ -2086,27 +2138,27 @@ process_body( FILE *          const ifp,
         } else
             isdeep = isdeepopt;
         
-        if( isdeep > 0 )
-            deep_to_ppm(ifp, chunksize, bmhdP, cmap);
-        else if( dcol )
-            dcol_to_ppm(ifp, chunksize, bmhdP, cmap, dcol);
-        else if( bmhdP->nPlanes > 8 ) {
-            if( bmhdP->nPlanes <= 16 && HAS_COLORMAP(cmap) )
-                std_to_ppm(ifp, chunksize, bmhdP, cmap, *viewportmodesP);
-            else if( isdeep >= 0 && (bmhdP->nPlanes % 3 == 0) )
-                deep_to_ppm(ifp, chunksize, bmhdP, cmap);
-            else if( bmhdP->nPlanes <= 16 )   
+        if (isdeep > 0)
+            deep_to_ppm(ifP, chunksize, bmhdP, cmap);
+        else if (dcol)
+            dcol_to_ppm(ifP, chunksize, bmhdP, cmap, dcol);
+        else if (bmhdP->nPlanes > 8) {
+            if (bmhdP->nPlanes <= 16 && HAS_COLORMAP(cmap))
+                std_to_ppm(ifP, chunksize, bmhdP, cmap, *viewportmodesP);
+            else if (isdeep >= 0 && (bmhdP->nPlanes % 3 == 0))
+                deep_to_ppm(ifP, chunksize, bmhdP, cmap);
+            else if (bmhdP->nPlanes <= 16)
                 /* will be interpreted as grayscale */
-                std_to_ppm(ifp, chunksize, bmhdP, cmap, *viewportmodesP);
+                std_to_ppm(ifP, chunksize, bmhdP, cmap, *viewportmodesP);
             else
                 pm_error("don't know how to interpret %d-plane image", 
                          bmhdP->nPlanes);
         } else
-            std_to_ppm(ifp, chunksize, bmhdP, cmap, *viewportmodesP);
+            std_to_ppm(ifP, chunksize, bmhdP, cmap, *viewportmodesP);
     } else if( typeid == ID_PBM )
-        ipbm_to_ppm(ifp, chunksize, bmhdP, cmap, *viewportmodesP);
+        ipbm_to_ppm(ifP, chunksize, bmhdP, cmap, *viewportmodesP);
     else   /* RGBN or RGB8 */
-        rgbn_to_ppm(ifp, chunksize, bmhdP, cmap);
+        rgbn_to_ppm(ifP, chunksize, bmhdP, cmap);
 }
 
 
@@ -2378,6 +2430,8 @@ main(int argc, char *argv[]) {
     if( argn != argc )
         pm_usage(usage);
 
+    wrotemask = false;  /* initial value */
+
     /* Read in the ILBM file. */
 
     firstIffid = get_big_long(ifP, ID_FORM, NULL);
diff --git a/converter/ppm/pc1toppm.c b/converter/ppm/pc1toppm.c
index 5ba247e9..ec6678a4 100644
--- a/converter/ppm/pc1toppm.c
+++ b/converter/ppm/pc1toppm.c
@@ -170,7 +170,7 @@ writePpm(FILE *         const ofP,
            is represented by 4 shorts (16 bit integers).  The
            first is for Plane 0, the second for Plane 1, etc.  Each short
            contains the bits for that plane for each of the 16 columns,
-           arranged from most signficant bit to least in increasing column
+           arranged from most significant bit to least in increasing column
            number.
         */
         unsigned int col0ScreenIndex = cols/16*planes * row;
diff --git a/converter/ppm/pcxtoppm.c b/converter/ppm/pcxtoppm.c
index 25a81531..e252ba22 100644
--- a/converter/ppm/pcxtoppm.c
+++ b/converter/ppm/pcxtoppm.c
@@ -84,7 +84,7 @@ parseCommandLine ( int argc, char ** argv,
    was passed to us as the argv array.  We also trash *argv.
 -----------------------------------------------------------------------------*/
     optEntry *option_def = malloc( 100*sizeof( optEntry ) );
-        /* Instructions to optParseOptions3 on how to parse our options.
+        /* Instructions to pm_optParseOptions3 on how to parse our options.
          */
     optStruct3 opt;
 
@@ -100,7 +100,7 @@ parseCommandLine ( int argc, char ** argv,
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
 
-    optParseOptions3( &argc, argv, opt, sizeof(opt), 0 );
+    pm_optParseOptions3( &argc, argv, opt, sizeof(opt), 0 );
         /* Uses and sets argc, argv, and some of *cmdline_p and others. */
 
     if (argc-1 < 1)
@@ -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;
@@ -532,14 +532,14 @@ pcx_256col_to_ppm(FILE *       const ifP,
     } else
         cols = headerCols;
 
-    image = (unsigned char **)pm_allocarray(BytesPerLine, rows, 
-                                            sizeof(unsigned char));
+    MALLOCARRAY2(image, rows, BytesPerLine);
+
     for (row = 0; row < rows; ++row)
         GetPCXRow(ifP, image[row], BytesPerLine);
 
     /*
      * 256 color images have their color map at the end of the file
-     * preceeded by a magic byte
+     * preceded by a magic byte
      */
     colormapSignature = GetByte(ifP);
     if (colormapSignature != PCX_256_COLORS)
diff --git a/converter/ppm/picttoppm.c b/converter/ppm/picttoppm.c
index 77efc6f2..b14675c7 100644
--- a/converter/ppm/picttoppm.c
+++ b/converter/ppm/picttoppm.c
@@ -40,10 +40,10 @@
 /*
  * Typical byte, 2 byte and 4 byte integers.
  */
-typedef unsigned char byte;
-typedef char signed_byte;
-typedef unsigned short word;
-typedef unsigned long longword;
+typedef unsigned char Byte;
+typedef char SignedByte;
+typedef unsigned short Word;
+typedef unsigned long Longword;
 
 
 /*
@@ -51,47 +51,47 @@ typedef unsigned long longword;
  */
 
 struct Rect {
-    word top;
-    word left;
-    word bottom;
-    word right;
+    Word top;
+    Word left;
+    Word bottom;
+    Word right;
 };
 
 struct pixMap {
     struct Rect Bounds;
-    word version;
-    word packType;
-    longword packSize;
-    longword hRes;
-    longword vRes;
-    word pixelType;
-    word pixelSize;
-    word cmpCount;
-    word cmpSize;
-    longword planeBytes;
-    longword pmTable;
-    longword pmReserved;
+    Word version;
+    Word packType;
+    Longword packSize;
+    Longword hRes;
+    Longword vRes;
+    Word pixelType;
+    Word pixelSize;
+    Word cmpCount;
+    Word cmpSize;
+    Longword planeBytes;
+    Longword pmTable;
+    Longword pmReserved;
 };
 
 struct RGBColor {
-    word red;
-    word grn;
-    word blu;
+    Word red;
+    Word grn;
+    Word blu;
 };
 
 struct Point {
-    word x;
-    word y;
+    Word x;
+    Word y;
 };
 
 struct Pattern {
-    byte pix[64];
+    Byte pix[64];
 };
 
 struct rgbPlanes {
-    word * red;
-    word * grn;
-    word * blu;
+    Word * red;
+    Word * grn;
+    Word * blu;
 };
 
 struct canvas {
@@ -102,8 +102,8 @@ typedef void (*transfer_func) (struct RGBColor* src, struct RGBColor* dst);
 
 static const char * stage;
 static struct Rect picFrame;
-static word rowlen;
-static word collen;
+static Word rowlen;
+static Word collen;
 static int verbose;
 static int fullres;
 static int recognize_comment;
@@ -121,23 +121,23 @@ static struct Rect clip_rect;
 static struct Rect cur_rect;
 static struct Point current;
 static struct Pattern pen_pat;
-static word pen_width;
-static word pen_height;
-static word pen_mode;
+static Word pen_width;
+static Word pen_height;
+static Word pen_mode;
 static transfer_func pen_trf;
-static word text_font;
-static byte text_face;
-static word text_mode;
+static Word text_font;
+static Byte text_face;
+static Word text_mode;
 static transfer_func text_trf;
-static word text_size;
+static Word text_size;
 static struct font* tfont;
 
 /* state for magic printer comments */
 static int ps_text;
-static byte ps_just;
-static byte ps_flip;
-static word ps_rotation;
-static byte ps_linespace;
+static Byte ps_just;
+static Byte ps_flip;
+static Word ps_rotation;
+static Byte ps_linespace;
 static int ps_cent_x;
 static int ps_cent_y;
 static int ps_cent_set;
@@ -277,6 +277,10 @@ typedef void (drawFn)(struct canvas *, blitList *, int);
 struct opdef {
     const char* name;
     int len;
+        /* If non-negative, this is the length of the argument of the
+           instruction.  If negative, it has special meaning; WORD_LEN
+           is the only value negative value.
+        */
     drawFn * impl;
     const char* description;
 };
@@ -291,11 +295,11 @@ struct opdef {
  */
 
 /* for reserved opcodes of known length */
-#define res(length) \
+#define RESERVED_OP(length)                                   \
 { "reserved", (length), NULL, "reserved for Apple use" }
 
 /* for reserved opcodes of length determined by a function */
-#define resf(skipfunction) \
+#define RESERVED_OP_F(skipfunction) \
 { "reserved", NA, (skipfunction), "reserved for Apple use" }
 
 /* seems like RGB colors are 6 bytes, but Apple says they're variable */
@@ -308,8 +312,8 @@ static int align = 0;
 
 
 
-static byte
-read_byte(void) {
+static Byte
+readByte(void) {
     int c;
 
     if ((c = fgetc(ifp)) == EOF)
@@ -321,52 +325,52 @@ read_byte(void) {
 
 
 
-static word
-read_word(void) {
-    byte b;
+static Word
+readWord(void) {
 
-    b = read_byte();
+    Byte const hi = readByte();
+    Byte const lo = readByte();
 
-    return (b << 8) | read_byte();
+    return (hi << 8) | (lo << 0);
 }
 
 
 
-static void read_point(struct Point * const p) {
-    p->y = read_word();
-    p->x = read_word();
+static void readPoint(struct Point * const p) {
+    p->y = readWord();
+    p->x = readWord();
 }
 
 
 
-static longword
-read_long(void) {
-    word i;
+static Longword
+readLong(void) {
+    Word const hi = readWord();
+    Word const lo = readWord();
 
-    i = read_word();
-    return (i << 16) | read_word();
+    return (hi << 16) | (lo << 0);
 }
 
 
 
-static signed_byte
-read_signed_byte(void) {
-    return (signed_byte)read_byte();
+static SignedByte
+readSignedByte(void) {
+    return (SignedByte)readByte();
 }
 
 
 
 static void 
-read_short_point(struct Point * const p) {
-    p->x = read_signed_byte();
-    p->y = read_signed_byte();
+readShortPoint(struct Point * const p) {
+    p->x = readSignedByte();
+    p->y = readSignedByte();
 }
 
 
 
 static void
 skip(int const byteCount) {
-    static byte buf[1024];
+    static Byte buf[1024];
     int n;
 
     align += byteCount;
@@ -461,7 +465,7 @@ const_name(const struct const_name * const table,
 
 
 static void 
-picComment(word const type, 
+picComment(Word const type, 
            int const length) {
 
     unsigned int remainingLength;
@@ -470,10 +474,10 @@ picComment(word const type,
     case 150:
         if (verbose) pm_message("TextBegin");
         if (length >= 6) {
-            ps_just = read_byte();
-            ps_flip = read_byte();
-            ps_rotation = read_word();
-            ps_linespace = read_byte();
+            ps_just = readByte();
+            ps_flip = readByte();
+            ps_rotation = readWord();
+            ps_linespace = readByte();
             remainingLength = length - 5;
             if (recognize_comment)
                 ps_text = 1;
@@ -506,11 +510,11 @@ picComment(word const type,
         if (length < 8)
             remainingLength = length;
         else {
-            ps_cent_y = read_word();
+            ps_cent_y = readWord();
             if (ps_cent_y > 32767)
                 ps_cent_y -= 65536;
             skip(2); /* ignore fractional part */
-            ps_cent_x = read_word();
+            ps_cent_x = readWord();
             if (ps_cent_x > 32767)
                 ps_cent_x -= 65536;
             skip(2); /* ignore fractional part */
@@ -621,7 +625,7 @@ ShortComment(struct canvas * const canvasP,
              blitList *      const blitListP,
              int             const version) {
 
-    picComment(read_word(), 0);
+    picComment(readWord(), 0);
 }
 
 
@@ -633,10 +637,10 @@ LongComment(struct canvas * const canvasP,
             blitList *      const blitListP,
             int             const version) {
 
-    word type;
+    Word type;
 
-    type = read_word();
-    picComment(type, read_word());
+    type = readWord();
+    picComment(type, readWord());
 }
 
 
@@ -649,7 +653,7 @@ skip_poly_or_region(struct canvas * const canvasP,
                     int             const version) {
 
     stage = "skipping polygon or region";
-    skip(read_word() - 2);
+    skip(readWord() - 2);
 }
 
 
@@ -788,7 +792,7 @@ dumpRect(const char * const label,
 
 
 static void
-read_rect(struct Rect * const r) {
+readRect(struct Rect * const r) {
 
     /* We don't have a formal specification for the Pict format, but we have
        seen samples that have the rectangle corners either in top left, bottom
@@ -800,10 +804,10 @@ read_rect(struct Rect * const r) {
        So now we accept all 4 possibilities.
     */
 
-    word const y1 = read_word();
-    word const x1 = read_word();
-    word const y2 = read_word();
-    word const x2 = read_word();
+    Word const y1 = readWord();
+    Word const x1 = readWord();
+    Word const y2 = readWord();
+    Word const x2 = readWord();
 
     r->top    = MIN(y1, y2);
     r->left   = MIN(x1, x2);
@@ -1202,7 +1206,7 @@ doDiffSize(struct Rect       const clipsrc,
 
     unsigned int const dstadd = dstwid - xsize;
 
-    FILE * pnmscalePipeP;
+    FILE * pamscalePipeP;
     const char * command;
     FILE * scaled;
     int cols, rows, format;
@@ -1211,9 +1215,9 @@ doDiffSize(struct Rect       const clipsrc,
     pixel * rowp;
     FILE * tempFileP;
     const char * tempFilename;
-    word * reddst;
-    word * grndst;
-    word * bludst;
+    Word * reddst;
+    Word * grndst;
+    Word * bludst;
 
     reddst = dst.red;  /* initial value */
     grndst = dst.grn;  /* initial value */
@@ -1223,19 +1227,19 @@ doDiffSize(struct Rect       const clipsrc,
 
     pm_close(tempFileP);
 
-    asprintfN(&command, "pnmscale -xsize %d -ysize %d > %s",
-              rectwidth(&clipdst), rectheight(&clipdst), tempFilename);
+    pm_asprintf(&command, "pamscale -xsize %d -ysize %d > %s",
+                rectwidth(&clipdst), rectheight(&clipdst), tempFilename);
 
     pm_message("running command '%s'", command);
 
-    pnmscalePipeP = popen(command, "w");
-    if (pnmscalePipeP == NULL)
+    pamscalePipeP = popen(command, "w");
+    if (pamscalePipeP == NULL)
         pm_error("cannot execute command '%s'  popen() errno = %s (%d)",
                  command, strerror(errno), errno);
 
-    strfree(command);
+    pm_strfree(command);
 
-    fprintf(pnmscalePipeP, "P6\n%d %d\n%d\n",
+    fprintf(pamscalePipeP, "P6\n%d %d\n%d\n",
             rectwidth(&clipsrc), rectheight(&clipsrc), PPM_MAXMAXVAL);
 
     switch (pixSize) {
@@ -1247,9 +1251,9 @@ doDiffSize(struct Rect       const clipsrc,
             for (colNumber = 0; colNumber < xsize; ++colNumber) {
                 unsigned int const colorIndex = row[colNumber];
                 struct RGBColor * const ct = &color_map[colorIndex];
-                fputc(redepth(ct->red, 65535L), pnmscalePipeP);
-                fputc(redepth(ct->grn, 65535L), pnmscalePipeP);
-                fputc(redepth(ct->blu, 65535L), pnmscalePipeP);
+                fputc(redepth(ct->red, 65535L), pamscalePipeP);
+                fputc(redepth(ct->grn, 65535L), pamscalePipeP);
+                fputc(redepth(ct->blu, 65535L), pamscalePipeP);
             }
         }
     }
@@ -1261,9 +1265,9 @@ doDiffSize(struct Rect       const clipsrc,
             unsigned int colNumber;
             for (colNumber = 0; colNumber < xsize; ++colNumber) {
                 struct RGBColor const color = decode16(&row[colNumber * 2]);
-                fputc(redepth(color.red, 32), pnmscalePipeP);
-                fputc(redepth(color.grn, 32), pnmscalePipeP);
-                fputc(redepth(color.blu, 32), pnmscalePipeP);
+                fputc(redepth(color.red, 32), pamscalePipeP);
+                fputc(redepth(color.grn, 32), pamscalePipeP);
+                fputc(redepth(color.blu, 32), pamscalePipeP);
             }
         }
     }
@@ -1280,17 +1284,17 @@ doDiffSize(struct Rect       const clipsrc,
 
             unsigned int colNumber;
             for (colNumber = 0; colNumber < xsize; ++colNumber) {
-                fputc(redepth(redPlane[colNumber], 256), pnmscalePipeP);
-                fputc(redepth(grnPlane[colNumber], 256), pnmscalePipeP);
-                fputc(redepth(bluPlane[colNumber], 256), pnmscalePipeP);
+                fputc(redepth(redPlane[colNumber], 256), pamscalePipeP);
+                fputc(redepth(grnPlane[colNumber], 256), pamscalePipeP);
+                fputc(redepth(bluPlane[colNumber], 256), pamscalePipeP);
             }
         }
     }
     break;
     }
 
-    if (pclose(pnmscalePipeP))
-        pm_error("pnmscale failed.  pclose() returned Errno %s (%d)",
+    if (pclose(pamscalePipeP))
+        pm_error("pamscale failed.  pclose() returned Errno %s (%d)",
                  strerror(errno), errno);
 
     ppm_readppminit(scaled = pm_openr(tempFilename), &cols, &rows,
@@ -1337,7 +1341,7 @@ doDiffSize(struct Rect       const clipsrc,
 
     pm_close(scaled);
     ppm_freerow(row);
-    strfree(tempFilename);
+    pm_strfree(tempFilename);
     unlink(tempFilename);
 }
 
@@ -1713,9 +1717,9 @@ allocPlanes(unsigned int       const width,
         pm_error("not enough memory to hold picture");
 
     /* initialize background to white */
-    memset(planes.red, 255, planelen * sizeof(word));
-    memset(planes.grn, 255, planelen * sizeof(word));
-    memset(planes.blu, 255, planelen * sizeof(word));
+    memset(planes.red, 255, planelen * sizeof(Word));
+    memset(planes.grn, 255, planelen * sizeof(Word));
+    memset(planes.blu, 255, planelen * sizeof(Word));
 
     *planesP = planes;
 }
@@ -1733,7 +1737,7 @@ freePlanes(struct rgbPlanes const planes) {
 
 
 static unsigned char
-compact(word const input) {
+compact(Word const input) {
 
     return (input >> 8) & 0xff;
 }
@@ -1919,41 +1923,49 @@ outputPpm(FILE *           const ofP,
  * All data in version 2 is 2-byte word aligned.  Odd size data
  * is padded with a null.
  */
-static word
+static Word
 get_op(int const version) {
     if ((align & 1) && version == 2) {
         stage = "aligning for opcode";
-        read_byte();
+        readByte();
     }
 
     stage = "reading opcode";
 
     if (version == 1)
-        return read_byte();
+        return readByte();
     else
-        return read_word();
+        return readWord();
 }
 
 
 
-static drawFn Clip;
+static drawFn ClipRgn;
 
 static void
-Clip(struct canvas * const canvasP,
-     blitList *      const blitListP,
-     int             const version) {
+ClipRgn(struct canvas * const canvasP,
+        blitList *      const blitListP,
+        int             const version) {
+
+    Word const len = readWord();
+        /* Length in bytes of the parameter (including this word) */
 
-    word len;
+    if (len == 10) {    /* null rgn */
+        /* Parameter is 2 bytes of length, 8 bytes of rectangle corners */
 
-    len = read_word();
+        /* In March 2011, I saw a supposed PICT file (reported to work with
+           Apple pictureViewer) with what looked like signed numbers for the
+           rectangle: (-32767,-32767), (32767, 32767).  This code has always
+           assumed all words in a PICT are unsigned.  But even when I changed
+           it to accept this clip rectangle, this program found the image to
+           have an invalid raster.
+        */
 
-    if (len == 0x000a) {    /* null rgn */
-        read_rect(&clip_rect);
+        readRect(&clip_rect);
         /* XXX should clip this by picFrame */
         if (verbose)
             dumpRect("clipping to", clip_rect);
-    }
-    else
+    } else
         skip(len - 2);
 }
 
@@ -1966,31 +1978,31 @@ OpColor(struct canvas * const canvasP,
         blitList *      const blitListP,
         int             const version) {
 
-    op_color.red = read_word();
-    op_color.grn = read_word();
-    op_color.blu = read_word();
+    op_color.red = readWord();
+    op_color.grn = readWord();
+    op_color.blu = readWord();
 }
 
 
 
 static void
-read_pixmap(struct pixMap * const p) {
+readPixmap(struct pixMap * const p) {
 
     stage = "getting pixMap header";
 
-    read_rect(&p->Bounds);
-    p->version    = read_word();
-    p->packType   = read_word();
-    p->packSize   = read_long();
-    p->hRes       = read_long();
-    p->vRes       = read_long();
-    p->pixelType  = read_word();
-    p->pixelSize  = read_word();
-    p->cmpCount   = read_word();
-    p->cmpSize    = read_word();
-    p->planeBytes = read_long();
-    p->pmTable    = read_long();
-    p->pmReserved = read_long();
+    readRect(&p->Bounds);
+    p->version    = readWord();
+    p->packType   = readWord();
+    p->packSize   = readLong();
+    p->hRes       = readLong();
+    p->vRes       = readLong();
+    p->pixelType  = readWord();
+    p->pixelSize  = readWord();
+    p->cmpCount   = readWord();
+    p->cmpSize    = readWord();
+    p->planeBytes = readLong();
+    p->pmTable    = readLong();
+    p->pmReserved = readLong();
 
     if (verbose) {
         pm_message("pixelType: %d", p->pixelType);
@@ -2013,19 +2025,19 @@ read_pixmap(struct pixMap * const p) {
 
 
 static struct RGBColor*
-read_color_table(void) {
-    longword ctSeed;
-    word ctFlags;
-    word ctSize;
-    word val;
+readColorTable(void) {
+    Longword ctSeed;
+    Word ctFlags;
+    Word ctSize;
+    Word val;
     int i;
     struct RGBColor* color_table;
 
     stage = "getting color table info";
 
-    ctSeed = read_long();
-    ctFlags = read_word();
-    ctSize = read_word();
+    ctSeed = readLong();
+    ctFlags = readWord();
+    ctSize = readWord();
 
     if (verbose) {
         pm_message("ctSeed:  %ld", ctSeed);
@@ -2040,7 +2052,7 @@ read_color_table(void) {
         pm_error("no memory for color table");
 
     for (i = 0; i <= ctSize; i++) {
-        val = read_word();
+        val = readWord();
         /* The indices in a device color table are bogus and usually == 0.
          * so I assume we allocate up the list of colors in order.
          */
@@ -2048,9 +2060,9 @@ read_color_table(void) {
             val = i;
         if (val > ctSize)
             pm_error("pixel value greater than color table size");
-        color_table[val].red = read_word();
-        color_table[val].grn = read_word();
-        color_table[val].blu = read_word();
+        color_table[val].red = readWord();
+        color_table[val].grn = readWord();
+        color_table[val].blu = readWord();
 
         if (verbose > 1)
             pm_message("Color %3u: [%u,%u,%u]", val,
@@ -2537,7 +2549,7 @@ interpretCompressedLine(unsigned char * const linebuf,
   So with 200 being the cutoff, it's actually impossible to represent some 
   16 bpp images with 200 pixels per row.
 
-  We have not been able to find an offical spec for PICT.
+  We have not been able to find an official spec for PICT.
 
   Some day, we may have to make a user option for this.
 */
@@ -2579,9 +2591,9 @@ unpackCompressedBits(FILE *          const ifP,
         unsigned int linelen;
 
         if (llsize == 2)
-            linelen = read_word();
+            linelen = readWord();
         else
-            linelen = read_byte();
+            linelen = readByte();
 
         reportValidateCompressedLineLen(row, linelen, raster.rowSize);
 
@@ -2604,7 +2616,7 @@ unpackCompressedBits(FILE *          const ifP,
 static void
 unpackbits(FILE *           const ifP,
            struct Rect *    const boundsP,
-           word             const rowBytesArg, 
+           Word             const rowBytesArg, 
            int              const bitsPerPixel,
            struct raster *  const rasterP) {
 
@@ -2639,7 +2651,7 @@ unpackbits(FILE *           const ifP,
 
 
 static void
-interpretRowBytesWord(word           const rowBytesWord,
+interpretRowBytesWord(Word           const rowBytesWord,
                       bool *         const pixMapP,
                       unsigned int * const rowBytesP) {
 
@@ -2657,13 +2669,13 @@ interpretRowBytesWord(word           const rowBytesWord,
  * a pattern in the fabled complete version.
  */
 static void
-read_pattern(void) {
+readPattern(void) {
 
-    word PatType;
+    Word PatType;
 
     stage = "Reading a pattern";
 
-    PatType = read_word();
+    PatType = readWord();
 
     switch (PatType) {
     case 2:
@@ -2671,7 +2683,7 @@ read_pattern(void) {
         skip(5); /* RGB for pattern */
         break;
     case 1: {
-        word rowBytesWord;
+        Word rowBytesWord;
         bool pixMap;
         unsigned int rowBytes;
         struct pixMap p;
@@ -2679,16 +2691,16 @@ read_pattern(void) {
         struct RGBColor * ct;
 
         skip(8); /* old pattern data */
-        rowBytesWord = read_word();
+        rowBytesWord = readWord();
         interpretRowBytesWord(rowBytesWord, &pixMap, &rowBytes);
-        read_pixmap(&p);
-        ct = read_color_table();
+        readPixmap(&p);
+        ct = readColorTable();
         unpackbits(ifp, &p.Bounds, rowBytes, p.pixelSize, &raster);
         freeRaster(raster);
         free(ct);
     } break;
     default:
-        pm_error("unknown pattern type in read_pattern");
+        pm_error("unknown pattern type in readPattern");
     }
 }
 
@@ -2703,7 +2715,7 @@ BkPixPat(struct canvas * const canvasP,
          blitList *      const blitListP,
          int             const version) {
 
-    read_pattern();
+    readPattern();
 }
 
 
@@ -2715,7 +2727,7 @@ PnPixPat(struct canvas * const canvasP,
          blitList *      const blitListP,
          int             const version) {
 
-    read_pattern();
+    readPattern();
 }
 
 
@@ -2727,13 +2739,13 @@ FillPixPat(struct canvas * const canvasP,
            blitList *      const blitListP,
            int             const version) {
 
-    read_pattern();
+    readPattern();
 }
 
 
 
 static void
-read_8x8_pattern(struct Pattern * const pat) {
+read8x8Pattern(struct Pattern * const pat) {
     unsigned char buf[8];
     unsigned char * exp;
     unsigned int len;
@@ -2762,7 +2774,7 @@ BkPat(struct canvas * const canvasP,
       blitList *      const blitListP,
       int             const version) {
 
-    read_8x8_pattern(&bkpat);
+    read8x8Pattern(&bkpat);
 }
 
 
@@ -2774,7 +2786,7 @@ PnPat(struct canvas * const canvasP,
       blitList *      const blitListP,
       int             const version) {
 
-    read_8x8_pattern(&pen_pat);
+    read8x8Pattern(&pen_pat);
 }
 
 
@@ -2786,7 +2798,7 @@ FillPat(struct canvas * const canvasP,
         blitList *      const blitListP,
         int             const version) {
 
-    read_8x8_pattern(&fillpat);
+    read8x8Pattern(&fillpat);
 }
 
 
@@ -2798,8 +2810,8 @@ PnSize(struct canvas * const canvasP,
        blitList *      const blitListP,
        int             const version) {
 
-    pen_height = read_word();
-    pen_width = read_word();
+    pen_height = readWord();
+    pen_width = readWord();
     if (verbose)
         pm_message("pen size %d x %d", pen_width, pen_height);
 }
@@ -2813,7 +2825,7 @@ PnMode(struct canvas * const canvasP,
        blitList *      const blitListP,
        int             const version) {
 
-    pen_mode = read_word();
+    pen_mode = readWord();
 
     if (pen_mode >= 8 && pen_mode < 15)
         pen_mode -= 8;
@@ -2827,10 +2839,10 @@ PnMode(struct canvas * const canvasP,
 
 
 static void 
-read_rgb(struct RGBColor * const rgb) {
-    rgb->red = read_word();
-    rgb->grn = read_word();
-    rgb->blu = read_word();
+readRgb(struct RGBColor * const rgb) {
+    rgb->red = readWord();
+    rgb->grn = readWord();
+    rgb->blu = readWord();
 }
 
 
@@ -2842,7 +2854,7 @@ RGBFgCol(struct canvas * const canvasP,
          blitList *      const blitListP,
          int             const version) {
 
-    read_rgb(&foreground);
+    readRgb(&foreground);
     if (verbose)
         pm_message("foreground now [%d,%d,%d]", 
             foreground.red, foreground.grn, foreground.blu);
@@ -2857,7 +2869,7 @@ RGBBkCol(struct canvas * const canvasP,
          blitList *      const blitListP,
          int             const version) {
 
-    read_rgb(&background);
+    readRgb(&background);
     if (verbose)
         pm_message("background now [%d,%d,%d]", 
             background.red, background.grn, background.blu);
@@ -2875,7 +2887,7 @@ draw_pixel(struct canvas *   const canvasP,
            transfer_func           trf) {
 
     if (x < clip_rect.left || x >= clip_rect.right ||
-        y < clip_rect.top || y >= clip_rect.bottom) {
+        y < clip_rect.top  || y >= clip_rect.bottom) {
     } else {
         unsigned int const i = PIXEL_INDEX(x, y);
 
@@ -3017,8 +3029,8 @@ Line(struct canvas * const canvasP,
      int             const version) {
 
   struct Point p1;
-  read_point(&p1);
-  read_point(&current);
+  readPoint(&p1);
+  readPoint(&current);
   if (verbose)
     pm_message("(%d,%d) to (%d, %d)",
            p1.x,p1.y,current.x,current.y);
@@ -3035,7 +3047,7 @@ LineFrom(struct canvas * const canvasP,
          int             const version) {
 
     struct Point p1;
-    read_point(&p1);
+    readPoint(&p1);
     if (verbose)
         pm_message("(%d,%d) to (%d, %d)", current.x, current.y, p1.x, p1.y);
 
@@ -3056,8 +3068,8 @@ ShortLine(struct canvas * const canvasP,
           int             const version) {
 
     struct Point p1;
-    read_point(&p1);
-    read_short_point(&current);
+    readPoint(&p1);
+    readShortPoint(&current);
     if (verbose)
         pm_message("(%d,%d) delta (%d, %d)", p1.x, p1.y, current.x, current.y);
     current.x += p1.x;
@@ -3077,7 +3089,7 @@ ShortLineFrom(struct canvas * const canvasP,
               int             const version) {
 
     struct Point p1;
-    read_short_point(&p1);
+    readShortPoint(&p1);
     if (verbose)
         pm_message("(%d,%d) delta (%d, %d)",
                    current.x,current.y,p1.x,p1.y);
@@ -3114,7 +3126,7 @@ paintRect(struct canvas * const canvasP,
           blitList *      const blitListP,
           int             const version) {
 
-    read_rect(&cur_rect);
+    readRect(&cur_rect);
     if (!blitListP)
         do_paintRect(canvasP, cur_rect);
 }
@@ -3165,7 +3177,7 @@ frameRect(struct canvas * const canvasP,
           blitList *      const blitListP,
           int             const version) {
 
-    read_rect(&cur_rect);
+    readRect(&cur_rect);
     if (!blitListP)
         do_frameRect(canvasP, cur_rect);
 }
@@ -3185,7 +3197,7 @@ frameSameRect(struct canvas * const canvasP,
 
 
 
-/* a stupid shell sort - I'm so embarassed  */
+/* a stupid shell sort - I'm so embarrassed  */
 
 static void 
 poly_sort(int const sort_index, struct Point points[]) {
@@ -3332,11 +3344,11 @@ paintPoly(struct canvas * const canvasP,
 
   struct Rect bb;
   struct Point pts[100];
-  int i, np = (read_word() - 10) >> 2;
+  int i, np = (readWord() - 10) >> 2;
 
-  read_rect(&bb);
+  readRect(&bb);
   for (i=0; i<np; ++i)
-    read_point(&pts[i]);
+    readPoint(&pts[i]);
 
   /* scan convert poly ... */
   if (!blitListP)
@@ -3352,7 +3364,7 @@ PnLocHFrac(struct canvas * const canvasP,
            blitList *      const blitListP,
            int             const version) {
 
-    word frac = read_word();
+    Word frac = readWord();
 
     if (verbose)
         pm_message("PnLocHFrac = %d", frac);
@@ -3367,7 +3379,7 @@ TxMode(struct canvas * const canvasP,
        blitList *      const blitListP,
        int             const version) {
 
-    text_mode = read_word();
+    text_mode = readWord();
 
     if (text_mode >= 8 && text_mode < 15)
         text_mode -= 8;
@@ -3388,7 +3400,7 @@ TxFont(struct canvas * const canvasP,
        blitList *      const blitListP,
        int             const version) {
 
-    text_font = read_word();
+    text_font = readWord();
     if (verbose)
         pm_message("text font %s", const_name(font_name, text_font));
 }
@@ -3402,7 +3414,7 @@ TxFace(struct canvas * const canvasP,
        blitList *      const blitListP,
        int             const version) {
 
-    text_face = read_byte();
+    text_face = readByte();
     if (verbose)
         pm_message("text face %d", text_face);
 }
@@ -3416,7 +3428,7 @@ TxSize(struct canvas * const canvasP,
        blitList *      const blitListP,
        int             const version) {
 
-    text_size = read_word();
+    text_size = readWord();
     if (verbose)
         pm_message("text size %d", text_size);
 }
@@ -3426,7 +3438,7 @@ TxSize(struct canvas * const canvasP,
 static void
 skip_text(blitList * const blitListP) {
 
-    skip(read_byte());
+    skip(readByte());
 
     blitListP->unblittableText = true;
 }
@@ -3510,11 +3522,11 @@ rotate(int * const x,
 
 static void
 do_ps_text(struct canvas * const canvasP,
-           word            const tx, 
-           word            const ty) {
+           Word            const tx, 
+           Word            const ty) {
 
     int len, width, i, w, h, x, y, rx, ry, o;
-    byte str[256], ch;
+    Byte str[256], ch;
     struct glyph* glyph;
 
     current.x = tx;
@@ -3526,12 +3538,12 @@ do_ps_text(struct canvas * const canvasP,
         ps_cent_set = 1;
     }
 
-    len = read_byte();
+    len = readByte();
 
     /* XXX this width calculation is not completely correct */
     width = 0;
     for (i = 0; i < len; i++) {
-        ch = str[i] = read_byte();
+        ch = str[i] = readByte();
         if (tfont->glyph[ch])
             width += tfont->glyph[ch]->xadd;
     }
@@ -3580,8 +3592,8 @@ do_ps_text(struct canvas * const canvasP,
 static void
 do_text(struct canvas *  const canvasP,
         blitList *       const blitListP,
-        word             const startx, 
-        word             const starty) {
+        Word             const startx, 
+        Word             const starty) {
 
     if (blitListP)
         skip_text(blitListP);
@@ -3593,12 +3605,12 @@ do_text(struct canvas *  const canvasP,
             do_ps_text(canvasP, startx, starty);
         else {
             int len;
-            word x, y;
+            Word x, y;
 
             x = startx;
             y = starty;
-            for (len = read_byte(); len > 0; --len) {
-                struct glyph* const glyph = tfont->glyph[read_byte()];
+            for (len = readByte(); len > 0; --len) {
+                struct glyph* const glyph = tfont->glyph[readByte()];
                 if (glyph) {
                     int dy;
                     int h;
@@ -3634,7 +3646,7 @@ LongText(struct canvas * const canvasP,
 
     struct Point p;
 
-    read_point(&p);
+    readPoint(&p);
 
     do_text(canvasP, blitListP, p.x, p.y);
 }
@@ -3648,7 +3660,7 @@ DHText(struct canvas * const canvasP,
        blitList *      const blitListP,
        int             const version) {
 
-    current.x += read_byte();
+    current.x += readByte();
 
     do_text(canvasP, blitListP, current.x, current.y);
 }
@@ -3662,7 +3674,7 @@ DVText(struct canvas * const canvasP,
        blitList *      const blitListP,
        int             const version) {
 
-    current.y += read_byte();
+    current.y += readByte();
 
     do_text(canvasP, blitListP, current.x, current.y);
 }
@@ -3675,10 +3687,10 @@ static void
 DHDVText(struct canvas * const canvasP,
          blitList *      const blitListP,
          int             const version) {
-    byte dh, dv;
+    Byte dh, dv;
 
-    dh = read_byte();
-    dv = read_byte();
+    dh = readByte();
+    dv = readByte();
 
     if (verbose)
         pm_message("dh, dv = %d, %d", dh, dv);
@@ -3692,7 +3704,7 @@ DHDVText(struct canvas * const canvasP,
 
 
 /*
- * This could use read_pixmap, but I'm too lazy to hack read_pixmap.
+ * This could use readPixmap, but I'm too lazy to hack readPixmap.
  */
 
 static void
@@ -3705,36 +3717,36 @@ directBits(struct canvas * const canvasP,
     struct Rect     srcRect;
     struct Rect     dstRect;
     struct raster   raster;
-    word            mode;
+    Word            mode;
     unsigned int    rectWidth;
 
     /* skip fake len, and fake EOF */
     skip(4);    /* Ptr baseAddr == 0x000000ff */
-    read_word();    /* version */
-    read_rect(&p.Bounds);
+    readWord();    /* version */
+    readRect(&p.Bounds);
     rectWidth = p.Bounds.right - p.Bounds.left;
-    p.packType = read_word();
-    p.packSize = read_long();
-    p.hRes = read_long();
-    p.vRes = read_long();
-    p.pixelType = read_word();
-    p.pixelSize = read_word();
-    p.pixelSize = read_word();    /* XXX twice??? */
-    p.cmpCount = read_word();
-    p.cmpSize = read_word();
-    p.planeBytes = read_long();
-    p.pmTable = read_long();
-    p.pmReserved = read_long();
-
-    read_rect(&srcRect);
+    p.packType = readWord();
+    p.packSize = readLong();
+    p.hRes = readLong();
+    p.vRes = readLong();
+    p.pixelType = readWord();
+    p.pixelSize = readWord();
+    p.pixelSize = readWord();    /* XXX twice??? */
+    p.cmpCount = readWord();
+    p.cmpSize = readWord();
+    p.planeBytes = readLong();
+    p.pmTable = readLong();
+    p.pmReserved = readLong();
+
+    readRect(&srcRect);
     if (verbose)
         dumpRect("source rectangle:", srcRect);
 
-    read_rect(&dstRect);
+    readRect(&dstRect);
     if (verbose)
         dumpRect("destination rectangle:", dstRect);
 
-    mode = read_word();
+    mode = readWord();
     if (verbose)
         pm_message("transfer mode = %s", const_name(transfer_name, mode));
 
@@ -3782,38 +3794,38 @@ static void
 do_pixmap(struct canvas * const canvasP,
           blitList *      const blitListP,
           int             const version, 
-          word            const rowBytes, 
+          Word            const rowBytes, 
           int             const is_region) {
 /*----------------------------------------------------------------------------
    Do a paletted image.
 -----------------------------------------------------------------------------*/
-    word mode;
+    Word mode;
     struct pixMap p;
     struct raster raster;
     struct RGBColor * color_table;
     struct Rect srcRect;
     struct Rect dstRect;
 
-    read_pixmap(&p);
+    readPixmap(&p);
 
     if (verbose)
         pm_message("%u x %u paletted image",
                    p.Bounds.right - p.Bounds.left,
                    p.Bounds.bottom - p.Bounds.top);
 
-    color_table = read_color_table();
+    color_table = readColorTable();
 
-    read_rect(&srcRect);
+    readRect(&srcRect);
 
     if (verbose)
         dumpRect("source rectangle:", srcRect);
 
-    read_rect(&dstRect);
+    readRect(&dstRect);
 
     if (verbose)
         dumpRect("destination rectangle:", dstRect);
 
-    mode = read_word();
+    mode = readWord();
 
     if (verbose)
         pm_message("transfer mode = %s", const_name(transfer_name, mode));
@@ -3849,7 +3861,7 @@ do_bitmap(FILE *          const ifP,
     struct Rect Bounds;
     struct Rect srcRect;
     struct Rect dstRect;
-    word mode;
+    Word mode;
     struct raster raster;
         /* This raster contains padding on the right to make a multiple
            of 16 pixels per row.
@@ -3857,10 +3869,10 @@ do_bitmap(FILE *          const ifP,
     static struct RGBColor color_table[] = { 
         {65535L, 65535L, 65535L}, {0, 0, 0} };
 
-    read_rect(&Bounds);
-    read_rect(&srcRect);
-    read_rect(&dstRect);
-    mode = read_word();
+    readRect(&Bounds);
+    readRect(&srcRect);
+    readRect(&dstRect);
+    mode = readWord();
     if (verbose)
         pm_message("transfer mode = %s", const_name(transfer_name, mode));
 
@@ -3886,12 +3898,12 @@ BitsRect(struct canvas * const canvasP,
          blitList *      const blitListP,
          int             const version) {
 
-    word rowBytesWord;
+    Word rowBytesWord;
     bool pixMap;
     unsigned int rowBytes;
 
     stage = "Reading rowBytes word for bitsrect";
-    rowBytesWord = read_word();
+    rowBytesWord = readWord();
 
     interpretRowBytesWord(rowBytesWord, &pixMap, &rowBytes);
 
@@ -3910,12 +3922,12 @@ BitsRegion(struct canvas * const canvasP,
            blitList *      const blitListP,
            int             const version) {
     
-    word rowBytesWord;
+    Word rowBytesWord;
     bool pixMap;
     unsigned int rowBytes;
 
     stage = "Reading rowBytes for bitsregion";
-    rowBytesWord = read_word();
+    rowBytesWord = readWord();
 
     interpretRowBytesWord(rowBytesWord, &pixMap, &rowBytes);
 
@@ -3933,7 +3945,7 @@ BitsRegion(struct canvas * const canvasP,
   */
 static struct opdef const optable[] = {
 /* 0x00 */  { "NOP", 0, NULL, "nop" },
-/* 0x01 */  { "Clip", NA, Clip, "clip" },
+/* 0x01 */  { "ClipRgn", NA, ClipRgn, "clip region" },
 /* 0x02 */  { "BkPat", 8, BkPat, "background pattern" },
 /* 0x03 */  { "TxFont", 2, TxFont, "text font (word)" },
 /* 0x04 */  { "TxFace", 1, TxFace, "text face (byte)" },
@@ -3955,9 +3967,9 @@ static struct opdef const optable[] = {
 /* 0x14 */  { "FillPixPat", NA, FillPixPat, "color fill pattern" },
 /* 0x15 */  { "PnLocHFrac", 2, PnLocHFrac, "fractional pen position" },
 /* 0x16 */  { "ChExtra", 2, NULL, "extra for each character" },
-/* 0x17 */  res(0),
-/* 0x18 */  res(0),
-/* 0x19 */  res(0),
+/* 0x17 */  RESERVED_OP(0),
+/* 0x18 */  RESERVED_OP(0),
+/* 0x19 */  RESERVED_OP(0),
 /* 0x1a */  { "RGBFgCol", RGB_LEN, RGBFgCol, "RGB foreColor" },
 /* 0x1b */  { "RGBBkCol", RGB_LEN, RGBBkCol, "RGB backColor" },
 /* 0x1c */  { "HiliteMode", 0, NULL, "hilite mode flag" },
@@ -3969,134 +3981,134 @@ static struct opdef const optable[] = {
 /* 0x22 */  { "ShortLine", 6, ShortLine, 
               "pnLoc (point, dh, dv (-128 .. 127))" },
 /* 0x23 */  { "ShortLineFrom", 2, ShortLineFrom, "dh, dv (-128 .. 127)" },
-/* 0x24 */  res(WORD_LEN),
-/* 0x25 */  res(WORD_LEN),
-/* 0x26 */  res(WORD_LEN),
-/* 0x27 */  res(WORD_LEN),
+/* 0x24 */  RESERVED_OP(WORD_LEN),
+/* 0x25 */  RESERVED_OP(WORD_LEN),
+/* 0x26 */  RESERVED_OP(WORD_LEN),
+/* 0x27 */  RESERVED_OP(WORD_LEN),
 /* 0x28 */  { "LongText", NA, LongText, 
               "txLoc (point), count (0..255), text" },
 /* 0x29 */  { "DHText", NA, DHText, "dh (0..255), count (0..255), text" },
 /* 0x2a */  { "DVText", NA, DVText, "dv (0..255), count (0..255), text" },
 /* 0x2b */  { "DHDVText", NA, DHDVText, 
               "dh, dv (0..255), count (0..255), text" },
-/* 0x2c */  res(WORD_LEN),
-/* 0x2d */  res(WORD_LEN),
-/* 0x2e */  res(WORD_LEN),
-/* 0x2f */  res(WORD_LEN),
+/* 0x2c */  RESERVED_OP(WORD_LEN),
+/* 0x2d */  RESERVED_OP(WORD_LEN),
+/* 0x2e */  RESERVED_OP(WORD_LEN),
+/* 0x2f */  RESERVED_OP(WORD_LEN),
 /* 0x30 */  { "frameRect", 8, frameRect, "rect" },
 /* 0x31 */  { "paintRect", 8, paintRect, "rect" },
 /* 0x32 */  { "eraseRect", 8, NULL, "rect" },
 /* 0x33 */  { "invertRect", 8, NULL, "rect" },
 /* 0x34 */  { "fillRect", 8, NULL, "rect" },
-/* 0x35 */  res(8),
-/* 0x36 */  res(8),
-/* 0x37 */  res(8),
+/* 0x35 */  RESERVED_OP(8),
+/* 0x36 */  RESERVED_OP(8),
+/* 0x37 */  RESERVED_OP(8),
 /* 0x38 */  { "frameSameRect", 0, frameSameRect, "rect" },
 /* 0x39 */  { "paintSameRect", 0, paintSameRect, "rect" },
 /* 0x3a */  { "eraseSameRect", 0, NULL, "rect" },
 /* 0x3b */  { "invertSameRect", 0, NULL, "rect" },
 /* 0x3c */  { "fillSameRect", 0, NULL, "rect" },
-/* 0x3d */  res(0),
-/* 0x3e */  res(0),
-/* 0x3f */  res(0),
+/* 0x3d */  RESERVED_OP(0),
+/* 0x3e */  RESERVED_OP(0),
+/* 0x3f */  RESERVED_OP(0),
 /* 0x40 */  { "frameRRect", 8, NULL, "rect" },
 /* 0x41 */  { "paintRRect", 8, NULL, "rect" },
 /* 0x42 */  { "eraseRRect", 8, NULL, "rect" },
 /* 0x43 */  { "invertRRect", 8, NULL, "rect" },
 /* 0x44 */  { "fillRRrect", 8, NULL, "rect" },
-/* 0x45 */  res(8),
-/* 0x46 */  res(8),
-/* 0x47 */  res(8),
+/* 0x45 */  RESERVED_OP(8),
+/* 0x46 */  RESERVED_OP(8),
+/* 0x47 */  RESERVED_OP(8),
 /* 0x48 */  { "frameSameRRect", 0, NULL, "rect" },
 /* 0x49 */  { "paintSameRRect", 0, NULL, "rect" },
 /* 0x4a */  { "eraseSameRRect", 0, NULL, "rect" },
 /* 0x4b */  { "invertSameRRect", 0, NULL, "rect" },
 /* 0x4c */  { "fillSameRRect", 0, NULL, "rect" },
-/* 0x4d */  res(0),
-/* 0x4e */  res(0),
-/* 0x4f */  res(0),
+/* 0x4d */  RESERVED_OP(0),
+/* 0x4e */  RESERVED_OP(0),
+/* 0x4f */  RESERVED_OP(0),
 /* 0x50 */  { "frameOval", 8, NULL, "rect" },
 /* 0x51 */  { "paintOval", 8, NULL, "rect" },
 /* 0x52 */  { "eraseOval", 8, NULL, "rect" },
 /* 0x53 */  { "invertOval", 8, NULL, "rect" },
 /* 0x54 */  { "fillOval", 8, NULL, "rect" },
-/* 0x55 */  res(8),
-/* 0x56 */  res(8),
-/* 0x57 */  res(8),
+/* 0x55 */  RESERVED_OP(8),
+/* 0x56 */  RESERVED_OP(8),
+/* 0x57 */  RESERVED_OP(8),
 /* 0x58 */  { "frameSameOval", 0, NULL, "rect" },
 /* 0x59 */  { "paintSameOval", 0, NULL, "rect" },
 /* 0x5a */  { "eraseSameOval", 0, NULL, "rect" },
 /* 0x5b */  { "invertSameOval", 0, NULL, "rect" },
 /* 0x5c */  { "fillSameOval", 0, NULL, "rect" },
-/* 0x5d */  res(0),
-/* 0x5e */  res(0),
-/* 0x5f */  res(0),
+/* 0x5d */  RESERVED_OP(0),
+/* 0x5e */  RESERVED_OP(0),
+/* 0x5f */  RESERVED_OP(0),
 /* 0x60 */  { "frameArc", 12, NULL, "rect, startAngle, arcAngle" },
 /* 0x61 */  { "paintArc", 12, NULL, "rect, startAngle, arcAngle" },
 /* 0x62 */  { "eraseArc", 12, NULL, "rect, startAngle, arcAngle" },
 /* 0x63 */  { "invertArc", 12, NULL, "rect, startAngle, arcAngle" },
 /* 0x64 */  { "fillArc", 12, NULL, "rect, startAngle, arcAngle" },
-/* 0x65 */  res(12),
-/* 0x66 */  res(12),
-/* 0x67 */  res(12),
+/* 0x65 */  RESERVED_OP(12),
+/* 0x66 */  RESERVED_OP(12),
+/* 0x67 */  RESERVED_OP(12),
 /* 0x68 */  { "frameSameArc", 4, NULL, "rect, startAngle, arcAngle" },
 /* 0x69 */  { "paintSameArc", 4, NULL, "rect, startAngle, arcAngle" },
 /* 0x6a */  { "eraseSameArc", 4, NULL, "rect, startAngle, arcAngle" },
 /* 0x6b */  { "invertSameArc", 4, NULL, "rect, startAngle, arcAngle" },
 /* 0x6c */  { "fillSameArc", 4, NULL, "rect, startAngle, arcAngle" },
-/* 0x6d */  res(4),
-/* 0x6e */  res(4),
-/* 0x6f */  res(4),
+/* 0x6d */  RESERVED_OP(4),
+/* 0x6e */  RESERVED_OP(4),
+/* 0x6f */  RESERVED_OP(4),
 /* 0x70 */  { "framePoly", NA, skip_poly_or_region, "poly" },
 /* 0x71 */  { "paintPoly", NA, paintPoly, "poly" },
 /* 0x72 */  { "erasePoly", NA, skip_poly_or_region, "poly" },
 /* 0x73 */  { "invertPoly", NA, skip_poly_or_region, "poly" },
 /* 0x74 */  { "fillPoly", NA, skip_poly_or_region, "poly" },
-/* 0x75 */  resf(skip_poly_or_region),
-/* 0x76 */  resf(skip_poly_or_region),
-/* 0x77 */  resf(skip_poly_or_region),
+/* 0x75 */  RESERVED_OP_F(skip_poly_or_region),
+/* 0x76 */  RESERVED_OP_F(skip_poly_or_region),
+/* 0x77 */  RESERVED_OP_F(skip_poly_or_region),
 /* 0x78 */  { "frameSamePoly", 0, NULL, "poly (NYI)" },
 /* 0x79 */  { "paintSamePoly", 0, NULL, "poly (NYI)" },
 /* 0x7a */  { "eraseSamePoly", 0, NULL, "poly (NYI)" },
 /* 0x7b */  { "invertSamePoly", 0, NULL, "poly (NYI)" },
 /* 0x7c */  { "fillSamePoly", 0, NULL, "poly (NYI)" },
-/* 0x7d */  res(0),
-/* 0x7e */  res(0),
-/* 0x7f */  res(0),
+/* 0x7d */  RESERVED_OP(0),
+/* 0x7e */  RESERVED_OP(0),
+/* 0x7f */  RESERVED_OP(0),
 /* 0x80 */  { "frameRgn", NA, skip_poly_or_region, "region" },
 /* 0x81 */  { "paintRgn", NA, skip_poly_or_region, "region" },
 /* 0x82 */  { "eraseRgn", NA, skip_poly_or_region, "region" },
 /* 0x83 */  { "invertRgn", NA, skip_poly_or_region, "region" },
 /* 0x84 */  { "fillRgn", NA, skip_poly_or_region, "region" },
-/* 0x85 */  resf(skip_poly_or_region),
-/* 0x86 */  resf(skip_poly_or_region),
-/* 0x87 */  resf(skip_poly_or_region),
+/* 0x85 */  RESERVED_OP_F(skip_poly_or_region),
+/* 0x86 */  RESERVED_OP_F(skip_poly_or_region),
+/* 0x87 */  RESERVED_OP_F(skip_poly_or_region),
 /* 0x88 */  { "frameSameRgn", 0, NULL, "region (NYI)" },
 /* 0x89 */  { "paintSameRgn", 0, NULL, "region (NYI)" },
 /* 0x8a */  { "eraseSameRgn", 0, NULL, "region (NYI)" },
 /* 0x8b */  { "invertSameRgn", 0, NULL, "region (NYI)" },
 /* 0x8c */  { "fillSameRgn", 0, NULL, "region (NYI)" },
-/* 0x8d */  res(0),
-/* 0x8e */  res(0),
-/* 0x8f */  res(0),
+/* 0x8d */  RESERVED_OP(0),
+/* 0x8e */  RESERVED_OP(0),
+/* 0x8f */  RESERVED_OP(0),
 /* 0x90 */  { "BitsRect", NA, BitsRect, "copybits, rect clipped" },
 /* 0x91 */  { "BitsRgn", NA, BitsRegion, "copybits, rgn clipped" },
-/* 0x92 */  res(WORD_LEN),
-/* 0x93 */  res(WORD_LEN),
-/* 0x94 */  res(WORD_LEN),
-/* 0x95 */  res(WORD_LEN),
-/* 0x96 */  res(WORD_LEN),
-/* 0x97 */  res(WORD_LEN),
+/* 0x92 */  RESERVED_OP(WORD_LEN),
+/* 0x93 */  RESERVED_OP(WORD_LEN),
+/* 0x94 */  RESERVED_OP(WORD_LEN),
+/* 0x95 */  RESERVED_OP(WORD_LEN),
+/* 0x96 */  RESERVED_OP(WORD_LEN),
+/* 0x97 */  RESERVED_OP(WORD_LEN),
 /* 0x98 */  { "PackBitsRect", NA, BitsRect, "packed copybits, rect clipped" },
 /* 0x99 */  { "PackBitsRgn", NA, BitsRegion, "packed copybits, rgn clipped" },
 /* 0x9a */  { "DirectBitsRect", NA, DirectBitsRect, 
               "PixMap, srcRect, dstRect, int copymode, PixData" },
 /* 0x9b */  { "DirectBitsRgn", NA, DirectBitsRgn, 
               "PixMap, srcRect, dstRect, int copymode, maskRgn, PixData" },
-/* 0x9c */  res(WORD_LEN),
-/* 0x9d */  res(WORD_LEN),
-/* 0x9e */  res(WORD_LEN),
-/* 0x9f */  res(WORD_LEN),
+/* 0x9c */  RESERVED_OP(WORD_LEN),
+/* 0x9d */  RESERVED_OP(WORD_LEN),
+/* 0x9e */  RESERVED_OP(WORD_LEN),
+/* 0x9f */  RESERVED_OP(WORD_LEN),
 /* 0xa0 */  { "ShortComment", 2, ShortComment, "kind (word)" },
 /* 0xa1 */  { "LongComment", NA, LongComment, 
               "kind (word), size (word), data" }
@@ -4105,7 +4117,7 @@ static struct opdef const optable[] = {
 
 
 static void
-processOpcode(word const opcode, 
+processOpcode(Word            const opcode, 
               struct canvas * const canvasP,
               blitList *      const blitListP,
               unsigned int    const version) {
@@ -4124,13 +4136,14 @@ processOpcode(word const opcode,
         else if (optable[opcode].len >= 0)
             skip(optable[opcode].len);
         else {
+            /* It's a special length code */
             switch (optable[opcode].len) {
             case WORD_LEN: {
-                word const len = read_word();
+                Word const len = readWord();
                 skip(len);
-                } break;
+            } break;
             default:
-                pm_error("can't do length %u", optable[opcode].len);
+                pm_error("can't do length %d", optable[opcode].len);
             }
         }
     } else if (opcode == 0xc00) {
@@ -4142,7 +4155,7 @@ processOpcode(word const opcode,
         stage = "skipping reserved";
         if (verbose)
             pm_message("%s 0x%x", stage, opcode);
-        skip(read_word());
+        skip(readWord());
     } else if (opcode >= 0xb0 && opcode <= 0xcf) {
         /* just a reserved opcode, no data */
         if (verbose)
@@ -4151,21 +4164,21 @@ processOpcode(word const opcode,
         stage = "skipping reserved";
         if (verbose)
             pm_message("%s 0x%x", stage, opcode);
-        skip(read_long());
+        skip(readLong());
     } else if (opcode >= 0x100 && opcode <= 0x7fff) {
         stage = "skipping reserved";
         if (verbose)
             pm_message("%s 0x%x", stage, opcode);
         skip((opcode >> 7) & 255);
     } else if (opcode >= 0x8000 && opcode <= 0x80ff) {
-        /* just a reserved opcode */
+        /* just a reserved opcode, no data */
         if (verbose)
             pm_message("reserved 0x%x", opcode);
     } else if (opcode >= 0x8100) {
         stage = "skipping reserved";
         if (verbose)
             pm_message("%s 0x%x", stage, opcode);
-        skip(read_long());
+        skip(readLong());
     } else
         pm_error("This program does not understand opcode 0x%04x", opcode);
 }
@@ -4173,13 +4186,13 @@ processOpcode(word const opcode,
 
 
 static void
-interpret_pict(FILE * const ofP) {
+interpretPict(FILE * const ofP) {
 
-    byte ch;
-    word picSize;
-    word opcode;
+    Byte ch;
+    Word picSize;
+    Word opcode;
     unsigned int version;
-    int i;
+    unsigned int i;
     struct canvas canvas;
     blitList blitList;
 
@@ -4194,13 +4207,13 @@ interpret_pict(FILE * const ofP) {
     text_trf = transfer(text_mode);
 
     stage = "Reading picture size";
-    picSize = read_word();
+    picSize = readWord();
 
     if (verbose)
         pm_message("picture size = %u (0x%x)", picSize, picSize);
 
     stage = "reading picture frame";
-    read_rect(&picFrame);
+    readRect(&picFrame);
 
     if (verbose) {
         dumpRect("Picture frame:", picFrame);
@@ -4218,18 +4231,18 @@ interpret_pict(FILE * const ofP) {
         clip_rect = picFrame;
     }
 
-    while ((ch = read_byte()) == 0)
+    while ((ch = readByte()) == 0)
         ;
     if (ch != 0x11)
         pm_error("No version number");
 
-    version = read_byte();
+    version = readByte();
 
     switch (version) {
     case 1:
         break;
     case 2: {
-        unsigned char const subcode = read_byte();
+        unsigned char const subcode = readByte();
         if (subcode != 0xff)
             pm_error("The only Version 2 PICT images this program "
                      "undertands are subcode 0xff.  This image has "
@@ -4328,7 +4341,7 @@ main(int argc, char * argv[]) {
         skip(512);
     }
 
-    interpret_pict(stdout);
+    interpretPict(stdout);
 
     pm_close(stdout);
 
diff --git a/converter/ppm/ppmtoacad.c b/converter/ppm/ppmtoacad.c
index 4f927f02..b5ee4d65 100644
--- a/converter/ppm/ppmtoacad.c
+++ b/converter/ppm/ppmtoacad.c
@@ -20,10 +20,9 @@
 */
 
 #include <stdio.h>
-#include "ppm.h"
 
-#define TRUE     1
-#define FALSE    0
+#include "pm_c_util.h"
+#include "ppm.h"
 
 #define EOS     '\0'
 
diff --git a/converter/ppm/ppmtoapplevol.c b/converter/ppm/ppmtoapplevol.c
new file mode 100644
index 00000000..e1c7f2dc
--- /dev/null
+++ b/converter/ppm/ppmtoapplevol.c
@@ -0,0 +1,95 @@
+/* ppmtoapplevol.c - read a portable pixmap and produce an Apple volume label
+ *
+ * Copyright 2011 Red Hat <mjg@redhat.com>
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  This software is provided "as is" without express or
+ * implied warranty.
+ */
+
+#include "pm.h"
+#include "ppm.h"
+
+
+
+static unsigned char const map[] = {
+    0x00, 0xf6, 0xf7, 0x2a, 0xf8, 0xf9, 0x55, 0xfa,
+    0xfb, 0x80, 0xfc, 0xfd, 0xab, 0xfe, 0xff, 0xd6
+};
+
+
+
+static void
+writeHeader(unsigned int const cols,
+            FILE *       const ofP) {
+
+    unsigned char header[5];
+
+    header[0] = 0x01;
+    header[1] = 0x00;
+    header[2] = cols;
+    header[3] = 0x00;
+    header[4] = 0x0c;
+
+    fwrite(header, sizeof(header), 1, ofP);
+}
+
+
+
+int
+main (int argc, const char * argv[]) {
+
+    const char * inputFilename;
+    FILE * ifP;
+    int rows, cols;
+    pixval maxval;
+    int format;
+    pixel * pixelrow;
+    unsigned int row;
+
+    pm_proginit(&argc, argv);
+
+    if (argc-1 > 1)
+        pm_error("Too many arguments: %u.  There is at most one argument: "
+                 "the input file name", argc-1);
+
+    if (argc-1 >= 1)
+        inputFilename = argv[1];
+    else
+        inputFilename = "-";
+
+    ifP = pm_openr(inputFilename);
+
+    ppm_readppminit(ifP, &cols, &rows, &maxval, &format);
+
+    if (rows != 12)
+        pm_error("Input image must be 12 rows tall.  Yours is %u", rows);
+
+    writeHeader(cols, stdout);
+
+    pixelrow = ppm_allocrow(cols);
+
+    for (row = 0; row < rows; row++) {
+        unsigned int col;
+        
+        ppm_readppmrow(stdin, pixelrow, cols, maxval, format);
+
+        for (col = 0; col < cols; ++col) {
+            unsigned int const maxval15Value =
+                ((unsigned int)PPM_GETR(pixelrow[col]) * 15 + maxval/2) /
+                maxval;
+            unsigned char const appleValue =
+                (unsigned char)map[15 - maxval15Value];
+            fwrite(&appleValue, sizeof(appleValue), 1, stdout);
+        }
+    }
+
+    ppm_freerow(pixelrow);
+
+    pm_close(ifP);
+
+    return 0;
+}
diff --git a/converter/ppm/ppmtoarbtxt.c b/converter/ppm/ppmtoarbtxt.c
index df859c84..fc8927ce 100644
--- a/converter/ppm/ppmtoarbtxt.c
+++ b/converter/ppm/ppmtoarbtxt.c
@@ -1,4 +1,4 @@
-/* ppmtoarbtxt.c - convert portable pixmap to cleartext
+/* ppmtoarbtxt.c - convert PPM to a custom text-based format
 **
 ** Renamed from ppmtotxt.c by Bryan Henderson in January 2003.
 **
@@ -12,51 +12,151 @@
 ** implied warranty.
 */
 
+#include <assert.h>
 #include <string.h>
+#ifdef __GLIBC__
+  #include <printf.h>  /* Necessary for parse_printf_format() */
+#endif
 
-#include "ppm.h"
+#include "pm_c_util.h"
 #include "mallocvar.h"
 #include "nstring.h"
+#include "shhopt.h"
+#include "ppm.h"
+
+/* HAVE_PARSE_PRINTF_FORMAT means the system library has
+   parse_printf_format(), declared in <printf.h>.  This essentially means
+   systems with GNU libc.
+*/
+
+#ifndef HAVE_PARSE_PRINTF_FORMAT
+  #ifdef PA_FLAG_MASK                   /* Defined in printf.h */
+    #define HAVE_PARSE_PRINTF_FORMAT 1
+  #else
+    #define HAVE_PARSE_PRINTF_FORMAT 0
+  #endif
+#endif
+
+
+
+struct CmdlineInfo {
+    /* All the information the user supplied in the command line,
+       in a form easy for the program to use.
+    */
+    const char * inputFileName;
+    const char * bodySklFileName;
+    const char * hd;
+    const char * tl;
+    unsigned int debug;
+};
+
+
+
+static void
+parseCommandLine(int argc, const char ** argv,
+                 struct CmdlineInfo * const cmdlineP) {
+/*----------------------------------------------------------------------------
+   Note that many of the strings that this function returns in the
+   *cmdline_p structure are actually in the supplied argv array.  And
+   sometimes, one of these strings is actually just a suffix of an entry
+   in argv!
+-----------------------------------------------------------------------------*/
+    optEntry * option_def;
+        /* Instructions to OptParseOptions3 on how to parse our options.
+         */
+    optStruct3 opt;
+
+    unsigned int hdSpec, tlSpec;
+
+    unsigned int option_def_index;
+    
+    MALLOCARRAY(option_def, 100);
+
+    option_def_index = 0;   /* incremented by OPTENTRY */
+    OPTENT3(0,   "hd",   OPT_STRING, &cmdlineP->hd, 
+            &hdSpec,             0);
+    OPTENT3(0,   "tl",   OPT_STRING, &cmdlineP->tl,
+            &tlSpec,             0);
+    OPTENT3(0,   "debug", OPT_FLAG, NULL,
+            &cmdlineP->debug,      0);
+
+    opt.opt_table = option_def;
+    opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
+    opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
+
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
+    free(option_def);
+
+    if (!hdSpec)
+        cmdlineP->hd = NULL;
+
+    if (!tlSpec)
+        cmdlineP->tl = NULL;
+
+    if (argc-1 < 1)
+        pm_error("You must specify the body skeleton file name as an "
+                 "argument");
+    else {
+        cmdlineP->bodySklFileName = strdup(argv[1]);
+
+        if (argc-1 < 2)
+            cmdlineP->inputFileName = strdup("-");  /* he wants stdin */
+        else {
+            cmdlineP->inputFileName = strdup(argv[2]);
+            if (argc-1 > 2)
+                pm_error("Too many arguments.  The only possible arguments "
+                         "are the body skeleton file name and input image "
+                         "file name");
+        }
+    }
+}
+
+
+
 
 typedef enum {
 /* The types of object we handle */
     BDATA, IRED, IGREEN, IBLUE, ILUM, FRED, FGREEN, FBLUE, FLUM,
     WIDTH, HEIGHT, POSX, POSY
-} SKL_OBJ_TYP;
+} SkeletonObjectType;
 
 typedef enum {
     OBJTYP_ICOLOR, OBJTYP_FCOLOR, OBJTYP_INT, OBJTYP_BDATA
-} SKL_OBJ_CLASS;
+} SkeletonObjectClass;
 
 /* Maximum size for a format string ("%d" etc.) */
+/* Add one to this size for the terminating '\0'. */
 #define MAXFORMAT 16
 
+typedef union {
 /* The data we keep for each object */
-typedef union
- {
-  struct BNDAT { char *bdat;   /* Binary data (text with newlines etc.) */
-                 int ndat;
-               } bin_data;
-
-  struct ICDAT { char icformat[MAXFORMAT];  /* Integer colors */
-                 int icolmin, icolmax;
-               } icol_data;
-
-  struct FCDAT { char fcformat[MAXFORMAT];  /* Float colors */
-                 double fcolmin, fcolmax;
-               } fcol_data;
-
-  struct IDAT  { char iformat[MAXFORMAT];   /* Integer data */
-               } i_data;
- } SKL_OBJ_DATA;
+    struct Bndat {
+        char * bdat;   /* Binary data (text with newlines etc.) */
+        unsigned int ndat;
+    } binData;
+    
+    struct Icdat {
+        char icformat[MAXFORMAT+1];  /* Integer colors */
+        unsigned int icolmin, icolmax;
+    } icolData;
+
+    struct Fcdat {
+        char fcformat[MAXFORMAT+1];  /* Float colors */
+        double fcolmin, fcolmax;
+    } fcolData;
+    
+    struct Idat {
+        char iformat[MAXFORMAT+1];   /* Integer data */
+    } iData;
+} SkeletonObjectData;
 
 
 /* Each object has a type and some data */
-typedef struct
- { 
-   SKL_OBJ_TYP otyp;
-   SKL_OBJ_DATA odata;
- } SKL_OBJ;
+typedef struct { 
+    SkeletonObjectType objType;
+    SkeletonObjectData odata;
+} SkeletonObject;
+
 
 
 #define MAX_SKL_HEAD_OBJ 64
@@ -66,199 +166,168 @@ typedef struct
 #define MAX_OBJ_BUF 80
 
 
-static void write_txt (fout, nobj, obj, width, height, x, y, red, green, blue)
-FILE *fout;
-int nobj;
-SKL_OBJ *obj[];
-int width, height, x, y;
-double red, green, blue;
-
-{register int count;
-
-#define WRITE_BNDAT(fd,theobj) \
- {struct BNDAT *bdata = &((theobj)->odata.bin_data); \
-       fwrite (bdata->bdat,bdata->ndat,1,fd); }
-
-#define WRITE_ICOL(fd,theobj,thecol) \
- {struct ICDAT *icdata = &((theobj)->odata.icol_data); \
-  fprintf (fd,icdata->icformat,(int)(icdata->icolmin \
-                + (icdata->icolmax - icdata->icolmin)*(thecol))); }
-
-#define WRITE_FCOL(fd,theobj,thecol) \
- {struct FCDAT *fcdata = &((theobj)->odata.fcol_data); \
-  fprintf (fd,fcdata->fcformat,(double)(fcdata->fcolmin \
-                + (fcdata->fcolmax - fcdata->fcolmin)*(thecol))); }
-
-#define WRITE_IDAT(fd,theobj,thedat) \
- {struct IDAT *idata = &((theobj)->odata.i_data); \
-  fprintf (fd,idata->iformat,thedat); }
-
- for (count = 0; count < nobj; count++)
- {
-   switch (obj[count]->otyp)
-   {
-     case BDATA:
-       WRITE_BNDAT (fout,obj[count]);
-       break;
-     case IRED:
-       WRITE_ICOL (fout,obj[count],red);
-       break;
-     case IGREEN:
-       WRITE_ICOL (fout,obj[count],green);
-       break;
-     case IBLUE:
-       WRITE_ICOL (fout,obj[count],blue);
-       break;
-     case ILUM:
-       WRITE_ICOL (fout,obj[count],0.299*red+0.587*green+0.114*blue);
-       break;
-     case FRED:
-       WRITE_FCOL (fout,obj[count],red);
-       break;
-     case FGREEN:
-       WRITE_FCOL (fout,obj[count],green);
-       break;
-     case FBLUE:
-       WRITE_FCOL (fout,obj[count],blue);
-       break;
-     case FLUM:
-       WRITE_FCOL (fout,obj[count],0.299*red+0.587*green+0.114*blue);
-       break;
-     case WIDTH:
-       WRITE_IDAT (fout,obj[count],width);
-       break;
-     case HEIGHT:
-       WRITE_IDAT (fout,obj[count],height);
-       break;
-     case POSX:
-       WRITE_IDAT (fout,obj[count],x);
-       break;
-     case POSY:
-       WRITE_IDAT (fout,obj[count],y);
-       break;
-   }
- }
-}
 
+static void
+dumpSkeleton(SkeletonObject ** const skeletonPList,
+             unsigned int      const nSkeleton) {
 
-static SKL_OBJ *
-save_bin_data(int    const ndat, 
-              char * const bdat) {
+    unsigned int i;
 
-    /* Save binary data in Object */
+    pm_message("%u objects", nSkeleton);
 
-    SKL_OBJ *obj;
+    for (i = 0; i < nSkeleton; ++i) {
+        SkeletonObject * const skeletonP = skeletonPList[i];
 
-    obj = (SKL_OBJ *)malloc (sizeof (SKL_OBJ) + ndat);
-    if (obj != NULL)
-    {
-        obj->otyp = BDATA;
-        obj->odata.bin_data.ndat = ndat;
-        obj->odata.bin_data.bdat = ((char *)(obj))+sizeof (SKL_OBJ);
-        memcpy (obj->odata.bin_data.bdat,bdat,ndat);
+        pm_message("  Object: Type %u", skeletonP->objType);
     }
-    return (obj);
 }
 
 
 
-static SKL_OBJ *
-save_icol_data(SKL_OBJ_TYP  const ctyp,
-               const char * const format,
-               int          const icolmin,
-               int          const icolmax) {
-/* Save integer color data in Object */
-
-    SKL_OBJ * objP;
+static void
+dumpAllSkeleton(SkeletonObject ** const bodySkeletonPList,
+                unsigned int      const bodyNskl,
+                SkeletonObject ** const headSkeletonPList, 
+                unsigned int      const headNskl,
+                SkeletonObject ** const tailSkeletonPList,
+                unsigned int      const tailNskl) {
+    
+    pm_message("Body skeleton:");
+    dumpSkeleton(bodySkeletonPList, bodyNskl);
+
+    pm_message("Head skeleton:");
+    dumpSkeleton(headSkeletonPList, headNskl);
+
+    pm_message("Tail skeleton:");
+    dumpSkeleton(tailSkeletonPList, tailNskl);
+}
 
-    MALLOCVAR(objP);
 
-    if (objP) {
-        objP->otyp = ctyp;
-        strcpy(objP->odata.icol_data.icformat, format);
-        objP->odata.icol_data.icolmin = icolmin;
-        objP->odata.icol_data.icolmax = icolmax;
-    }
-    return objP;
-}
 
+static void
+writeBndat(FILE *           const ofP,
+           SkeletonObject * const objectP) {
 
+    struct Bndat * const bdataP = &objectP->odata.binData;
 
-static SKL_OBJ *
-save_fcol_data(SKL_OBJ_TYP  const ctyp,
-               const char * const format,
-               double       const fcolmin,
-               double       const fcolmax) {
-/* Save float color data in Object */
+    fwrite(bdataP->bdat, bdataP->ndat, 1, ofP);
+}
 
-    SKL_OBJ * objP;
 
-    MALLOCVAR(objP);
 
-    if (objP) {
-        objP->otyp = ctyp;
-        strcpy(objP->odata.fcol_data.fcformat, format);
-        objP->odata.fcol_data.fcolmin = fcolmin;
-        objP->odata.fcol_data.fcolmax = fcolmax;
-    }
-    return objP;
-}
+static void
+writeIcol(FILE *           const ofP,
+          SkeletonObject * const objectP,
+          double           const value) {
 
+    /* Unlike Netpbm, the output format does not have an upper limit for
+       maxval.  Here we allow all values representable by unsigned int.
+    */
 
+    struct Icdat * const icdataP = &objectP->odata.icolData;
+    unsigned int const outValue =
+        ROUNDU( icdataP->icolmin +
+                ((double)icdataP->icolmax - icdataP->icolmin) * value);
 
-static SKL_OBJ *
-save_i_data(SKL_OBJ_TYP  const ctyp,
-            const char * const format) {
+    fprintf(ofP, icdataP->icformat, outValue);
+}
 
-/* Save universal data in Object */
 
-    SKL_OBJ * objP;
 
-    MALLOCVAR(objP);
-    if (objP) {
-        objP->otyp = ctyp;
-        strcpy(objP->odata.i_data.iformat, format);
-    }
-    return objP;
+static void
+writeFcol(FILE *           const ofP,
+          SkeletonObject * const objectP,
+          double           const value) {
+
+    struct Fcdat * const fcdataP = &objectP->odata.fcolData;
+    
+    fprintf(ofP, fcdataP->fcformat,
+            (double)
+            (fcdataP->fcolmin
+             + (fcdataP->fcolmax - fcdataP->fcolmin) * value));
 }
 
 
 
-static char const escape = '#';
+static void
+writeIdat(FILE *           const ofP,
+          SkeletonObject * const objectP,
+          unsigned int     const value) {
+
+    struct Idat * const idataP = &objectP->odata.iData;
+    
+    fprintf(ofP, idataP->iformat, value);
+}
 
 
 
-static SKL_OBJ_TYP
-interpretObjType(const char * const typstr) {
+static void
+writeText(FILE *            const ofP,
+          unsigned int      const nObj,
+          SkeletonObject ** const obj,
+          unsigned int      const width,
+          unsigned int      const height,
+          unsigned int      const x,
+          unsigned int      const y,
+          double            const red,
+          double            const green,
+          double            const blue) {
+    
+    unsigned int i;
 
-    SKL_OBJ_TYP otyp;
-
-    /* Check for integer colors */
-    if      (streq(typstr, "ired")  ) otyp = IRED;
-    else if (streq(typstr, "igreen")) otyp = IGREEN;
-    else if (streq(typstr, "iblue") ) otyp = IBLUE;
-    else if (streq(typstr, "ilum")  ) otyp = ILUM;
-    /* Check for real colors */
-    else if (streq(typstr, "fred")  ) otyp = FRED;
-    else if (streq(typstr, "fgreen")) otyp = FGREEN;
-    else if (streq(typstr, "fblue") ) otyp = FBLUE;
-    else if (streq(typstr, "flum")  ) otyp = FLUM;
-    /* Check for integer data */
-    else if (streq(typstr, "width") ) otyp = WIDTH;
-    else if (streq(typstr, "height")) otyp = HEIGHT;
-    else if (streq(typstr, "posx")  ) otyp = POSX;
-    else if (streq(typstr, "posy")  ) otyp = POSY;
-    else                              otyp = BDATA;
-
-    return otyp;
+    for (i = 0; i < nObj; ++i) {
+        switch (obj[i]->objType) {
+        case BDATA:
+            writeBndat(ofP, obj[i]);
+            break;
+        case IRED:
+            writeIcol(ofP, obj[i], red);
+            break;
+        case IGREEN:
+            writeIcol(ofP, obj[i], green);
+            break;
+        case IBLUE:
+            writeIcol(ofP, obj[i], blue);
+            break;
+        case ILUM:
+            writeIcol(ofP, obj[i],
+                      PPM_LUMINR*red + PPM_LUMING*green + PPM_LUMINB*blue);
+            break;
+        case FRED:
+            writeFcol(ofP, obj[i], red);
+            break;
+        case FGREEN:
+            writeFcol(ofP, obj[i], green);
+            break;
+        case FBLUE:
+            writeFcol(ofP, obj[i], blue);
+            break;
+        case FLUM:
+            writeFcol(ofP, obj[i],
+                      PPM_LUMINR*red + PPM_LUMING*green + PPM_LUMINB*blue);
+            break;
+        case WIDTH:
+            writeIdat(ofP, obj[i], width);
+            break;
+        case HEIGHT:
+            writeIdat(ofP, obj[i], height);
+            break;
+        case POSX:
+            writeIdat(ofP, obj[i], x);
+            break;
+        case POSY:
+            writeIdat(ofP, obj[i], y);
+            break;
+        }
+    }
 }
 
 
 
-static SKL_OBJ_CLASS
-objClass(SKL_OBJ_TYP const otyp) {
+static SkeletonObjectClass
+objClass(SkeletonObjectType const objType) {
 
-    switch (otyp) {
+    switch (objType) {
     case IRED:
     case IGREEN:
     case IBLUE:
@@ -283,298 +352,873 @@ objClass(SKL_OBJ_TYP const otyp) {
 }
 
 
+/*----------------------------------------------------------------------------
+  Format string validation
+
+  We validate format strings (such as "%f" "%03d") found in the skeleton files
+  for convenience, even though behavior is documented as undefined when the
+  user supplies a bogus format string.  Certain strings, most notably those
+  with "%n", are especially risky; they pose a security threat.
+
+  On systems with Glibc, we check with parse_printf_format().  On other
+  systems we conduct a cursory scan of the characters in the format string,
+  looking for characters that trigger non-numeric conversions, etc.
+
+  Documentation for parse_printf_format() is usually available in texinfo
+  format on GNU/Linux systems.  As of Dec. 2014 there is no official man page.
+  
+  Online documentation is available from:
+  https://
+  www.gnu.org/software/libc/manual/html_node/Parsing-a-Template-String.html
+-----------------------------------------------------------------------------*/
 
+#if HAVE_PARSE_PRINTF_FORMAT
 static void
-addImpostorReplacementSeq(char *         const line,
-                          unsigned int   const startCursor,
-                          const char *   const seqContents,
-                          unsigned int   const seqContentsLen,
-                          unsigned int * const newCursorP) {
+validateParsePrintfFlag(int                const printfConversion,
+                        SkeletonObjectType const ctyp,
+                        const char **      const errorP) {
 /*----------------------------------------------------------------------------
-   Add to line line[], at position 'startCursor', text that looks like a
-   replacement sequence but doesn't have the proper contents (the
-   stuff between the parentheses) to be one.  For example,
+  Assuming 'printfConversion' is the value reported by parse_printf_format()
+  as the type of argument a format string requires, 
+  return an explanation of how it is incompatible with 'ctyp' as
+  *errorP -- return null string if it is compatible.
+-----------------------------------------------------------------------------*/
+    /* We first check for "%n", then the type modifiers, and finally the
+       actual conversion type (char, int, float, double, string or pointer.)
+    */
+    switch (printfConversion & PA_FLAG_MASK) {
+    case PA_FLAG_PTR:  /* This means %n */
+        pm_asprintf(errorP, "Contains a %%n conversion specifier");
+        break;
+
+    case PA_FLAG_SHORT:
+    case PA_FLAG_LONG:
+    case PA_FLAG_LONG_LONG:
+        /* We omit PA_FLAG_LONG_DOUBLE because it is a synonym for
+           PA_FLAG_LONG_LONG: listing both causes compilation errors.
+        */
+        pm_asprintf(errorP, "Invalid type modifier");
+        break;
+
+    default:
+        switch (printfConversion & ~PA_FLAG_MASK) {
+        case PA_CHAR:
+            pm_message("Warning: char type conversion."); 
+        case PA_INT:
+            if(objClass(ctyp) == OBJTYP_ICOLOR ||
+               objClass(ctyp) == OBJTYP_INT )
+                *errorP = NULL;
+            else
+                pm_asprintf(errorP, "Conversion specifier requires a "
+                            "character or integer argument, but it is in "
+                            "a replacement sequence for a different type");
+            break;
+        case PA_DOUBLE:
+            if(objClass(ctyp) == OBJTYP_FCOLOR)
+                *errorP = NULL;
+            else
+                pm_asprintf(errorP, "Conversion specifier requires a "
+                            "double precision floating point argument, "
+                            "but it is in "
+                            "a replacement sequence for a different type");
+            break;
+        case PA_FLOAT:
+        case PA_STRING:    /* %s */
+        case PA_POINTER:   /* %p */
+        default:
+            pm_asprintf(errorP, "Conversion specifier requires an argument of "
+                        "a type that this program never provides for "
+                        "any replacement sequence");
+        }
+    }
+}
+#endif
 
-     "#(fread x)"
 
-   seqContents[] is the contents; 'seqContentsLen' its length.
 
-   Return as *newCursorP where the line[] cursor ends up after adding
-   the sequence.
+#if HAVE_PARSE_PRINTF_FORMAT
+static void
+validateFormatWithPpf(const char *       const format,
+                      SkeletonObjectType const ctyp,
+                      const char **      const errorP) {
+/*----------------------------------------------------------------------------
+  Validate format string 'format' for use with a skeleton of type 'ctyp',
+  using the system parse_printf_format() function.
+
+  Return as *errorP an explanation of how it is invalid, or a null string
+  if it is valid.
 -----------------------------------------------------------------------------*/
-    unsigned int cursor;
-    unsigned int i;
+    /* We request parse_printf_format() to report the details of the first
+       8 conversions.  8 because the maximum length of format is 16 means it
+       can have up to 8 conversions: "%d%d%d%d%d%d%d%d".
+
+       Actually this is more than necessary: we are concerned with only the
+       first conversion and whether there it is the only one.
+    */
 
-    cursor = startCursor;
+    int printfConversion[MAXFORMAT/2] = {0, 0, 0, 0, 0, 0, 0, 0};
 
-    line[cursor++] = escape;
-    line[cursor++] = '(';
+    size_t const n =
+        parse_printf_format(format, MAXFORMAT/2, printfConversion);
+
+    switch (n) {
+    case 0:
+        pm_asprintf(errorP, "No transformation found");
+        break;
+
+    case 1:
+        validateParsePrintfFlag(printfConversion[0], ctyp, errorP);
+        break;
+
+    default:
+        pm_asprintf(errorP, "Has %lu extra transformation%s ",
+                    (unsigned long)n-1, n-1 > 1 ? "s" : "");
+        break;
+    }
+}
+#endif
 
-    for (i = 0; i < seqContentsLen; ++i)
-        line[cursor++] = seqContents[i];
 
-    line[cursor++] = ')';
 
-    *newCursorP = cursor;
+static void
+validateFormatOne(char               const typeSpecifier,
+                  bool               const isLastInString,
+                  SkeletonObjectType const ctyp,
+                  bool *             const validatedP,
+                  const char **      const errorP) {
+
+    switch (typeSpecifier) {
+        /* Valid character encountered.  Skip. */
+        /* ' ' (space) is listed here, but should never occur for
+           we use sscanf() to parse the fields.
+        */
+    case ' ': case '-': case '+': case '\'': case '#': case '.':
+    case '0': case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7': case '8': case '9':
+        break;
+        
+    case 'c': case 'C':
+        pm_message("Warning: char type conversion: %%%c.", typeSpecifier);
+    case 'i': case 'd': case 'u': case 'o': case 'x': case 'X':
+        if (!isLastInString)
+            pm_asprintf(errorP, "Extra characters at end");
+        else if(objClass(ctyp) != OBJTYP_ICOLOR &&
+                objClass(ctyp) != OBJTYP_INT )
+            pm_asprintf(errorP, "Conversion type mismatch");
+        else
+            *validatedP = true;
+        break;
+
+    case 'f': case 'F': case 'g': case 'G': case 'a': case 'A':
+        if (!isLastInString)
+            pm_asprintf(errorP, "Extra characters at end");
+        else if(objClass(ctyp) != OBJTYP_FCOLOR)
+            pm_asprintf(errorP, "Conversion type mismatch");
+        else
+            *validatedP = true;
+        break;
+
+    case '\0':
+        pm_asprintf(errorP, "No conversion specified");
+        break;
+    case '%':
+        pm_asprintf(errorP, "No more than one %% is allowed");
+        break;
+    case '$':
+    case '*':
+        pm_asprintf(errorP, "%c is not allowed", typeSpecifier);
+        break;
+    case 'h': case 'l': case 'L': case 'q': case 'j': case 'Z': case 't':
+        pm_asprintf(errorP, "Modifier %c is not allowed in format",
+                    typeSpecifier);
+        break;
+    case 's': case 'S': case 'm': case 'p': case 'n':
+        pm_asprintf(errorP, "Invalid conversion type");
+        break;
+    default:
+        pm_asprintf(errorP, "Abnormal character");
+        break;
+    }
 }
 
 
 
-static int
-read_skeleton(const char *   const filename,
-              unsigned int   const maxskl,
-              unsigned int * const nsklP,
-              SKL_OBJ **     const skl) {
+static void
+validateFormatGen(const char *       const format,
+                  SkeletonObjectType const ctyp,
+                  const char **      const errorP)  {
 /*----------------------------------------------------------------------------
-  Read skeleton file
+  Validate format string 'format' for use with a skeleton of type 'ctyp',
+  without using the system parse_printf_format() function.
+
+  The string must begin with "%" and end with the translation type character
+  ("%d", "%x", "%f", etc.)
+
+  We check only for invalid characters.  Invalid constructs, such as
+  "%00.00.00d" will pass this test.
+
+  Return as *errorP an explanation of how it is invalid, or a null string
+  if it is valid.
 -----------------------------------------------------------------------------*/
-    FILE * sklfile;
-    unsigned int slen;
-    unsigned int objlen;
-    int chr;
-    SKL_OBJ_TYP otyp;
-    char line[MAX_LINE_BUF+MAX_OBJ_BUF+16];
-    char objstr[MAX_OBJ_BUF],typstr[MAX_OBJ_BUF];
-    unsigned int nskl;
-
-#define SAVE_BIN(slen,line) \
-    { if (slen > 0 && (skl[nskl] = save_bin_data(slen,line)) != NULL) ++nskl; \
-      slen = 0; }
-
-    sklfile = pm_openr(filename);
-
-    /* Parse skeleton file */
-    nskl = 0;  /* initial value */
-
-    slen = 0;
-    while ((chr = getc (sklfile)) != EOF) {  /* Up to end of skeleton file */
-        if (nskl >= maxskl)
-            return -1;
-
-        if (slen+1 >= MAX_LINE_BUF) {
-            /* Buffer finished.  Save as binary object */
-            SAVE_BIN(slen,line);
+    if (format[0] != '%')
+        pm_asprintf(errorP, "Does not start with %%");
+    else {
+        unsigned int i;
+        bool validated;
+
+        for (i = 1, validated = false, *errorP = NULL;
+             !validated && !*errorP;
+             ++i) {
+
+            validateFormatOne(format[i], format[i+1] == '\0', ctyp,
+                              &validated, errorP);
         }
+    }
+}
 
-        if (chr != escape) {
-            /* Not a replacement sequence; just a literal character */
-            line[slen++] = chr;
-            continue;
-        }
 
-        chr = getc(sklfile);
-        if (chr == EOF) {
-            /* Not a valid replacement sequence */
-            line[slen++] = escape;
-            break;
-        }
-        if (chr != '(') {
-            /* Not a valid replacement sequence */
-            line[slen++] = escape;
-            line[slen++] = chr;
-            continue;
+
+static void
+validateFormat(const char *       const format,
+               SkeletonObjectType const ctyp) {
+
+    const char * error;
+
+    if (strlen(format) > MAXFORMAT)
+        pm_asprintf(&error, "Too long");
+    else {
+#if HAVE_PARSE_PRINTF_FORMAT
+        if (true)
+            validateFormatWithPpf(format, ctyp, &error);
+        else  /* Silence compiler warning about unused function */
+            validateFormatGen(format, ctyp, &error);
+#else
+        validateFormatGen(format, ctyp, &error);
+#endif
+    }
+
+    if (error)
+        pm_error("Invalid format string '%s'.  %s", format, error);
+}              
+               
+
+
+static SkeletonObject *
+newBinDataObj(unsigned int const nDat, 
+              const char * const bdat) {
+/*----------------------------------------------------------------------------
+  Create a binary data object.
+-----------------------------------------------------------------------------*/
+    SkeletonObject * objectP;
+
+    objectP = malloc(sizeof(*objectP) + nDat);
+
+    if (!objectP)
+        pm_error("Failed to allocate memory for binary data object "
+                 "with %u bytes", nDat);
+
+    objectP->objType = BDATA;
+    objectP->odata.binData.ndat = nDat;
+    objectP->odata.binData.bdat = ((char *)objectP) + sizeof(SkeletonObject);
+    memcpy(objectP->odata.binData.bdat, bdat, nDat);
+
+    return objectP;
+}
+
+
+
+static SkeletonObject *
+newIcolDataObj(SkeletonObjectType const ctyp,
+               const char *       const format,
+               unsigned int       const icolmin,
+               unsigned int       const icolmax) {
+/*----------------------------------------------------------------------------
+  Create integer color data object.
+-----------------------------------------------------------------------------*/
+    SkeletonObject * objectP;
+
+    MALLOCVAR(objectP);
+
+    if (!objectP)
+        pm_error("Failed to allocate memory for an integer color data "
+                 "object");
+
+    objectP->objType = ctyp;
+    validateFormat(format, ctyp);
+    strcpy(objectP->odata.icolData.icformat, format);
+    objectP->odata.icolData.icolmin = icolmin;
+    objectP->odata.icolData.icolmax = icolmax;
+
+    return objectP;
+}
+
+
+
+static SkeletonObject *
+newFcolDataObj(SkeletonObjectType  const ctyp,
+               const char *        const format,
+               double              const fcolmin,
+               double              const fcolmax) {
+/*----------------------------------------------------------------------------
+  Create float color data object.
+-----------------------------------------------------------------------------*/
+    SkeletonObject * objectP;
+
+    MALLOCVAR(objectP);
+
+    if (!objectP)
+        pm_error("Failed to allocate memory for a float color data object");
+
+    objectP->objType = ctyp;
+    validateFormat(format, ctyp);
+    strcpy(objectP->odata.fcolData.fcformat, format);
+    objectP->odata.fcolData.fcolmin = fcolmin;
+    objectP->odata.fcolData.fcolmax = fcolmax;
+
+    return objectP;
+}
+
+
+
+static SkeletonObject *
+newIdataObj(SkeletonObjectType const ctyp,
+            const char *       const format) {
+/*----------------------------------------------------------------------------
+  Create universal data object.
+-----------------------------------------------------------------------------*/
+    SkeletonObject * objectP;
+
+    MALLOCVAR(objectP);
+
+    if (!objectP)
+        pm_error("Failed to allocate memory for a universal data object");
+
+    objectP->objType = ctyp;
+    validateFormat(format, ctyp);
+    strcpy(objectP->odata.iData.iformat, format);
+
+    return objectP;
+}
+
+
+
+static char const escape = '#';
+
+
+
+static SkeletonObjectType
+interpretObjType(const char * const typstr) {
+
+    SkeletonObjectType objType;
+
+    /* handle integer colors */
+    if      (streq(typstr, "ired")  ) objType = IRED;
+    else if (streq(typstr, "igreen")) objType = IGREEN;
+    else if (streq(typstr, "iblue") ) objType = IBLUE;
+    else if (streq(typstr, "ilum")  ) objType = ILUM;
+    /* handle real colors */
+    else if (streq(typstr, "fred")  ) objType = FRED;
+    else if (streq(typstr, "fgreen")) objType = FGREEN;
+    else if (streq(typstr, "fblue") ) objType = FBLUE;
+    else if (streq(typstr, "flum")  ) objType = FLUM;
+    /* handle integer data */
+    else if (streq(typstr, "width") ) objType = WIDTH;
+    else if (streq(typstr, "height")) objType = HEIGHT;
+    else if (streq(typstr, "posx")  ) objType = POSX;
+    else if (streq(typstr, "posy")  ) objType = POSY;
+    else                              objType = BDATA;
+
+    return objType;
+}
+
+
+
+static SkeletonObject *
+newIcSkelFromReplString(const char *       const objstr,
+                        SkeletonObjectType const objType) {
+
+    SkeletonObject * retval;
+    unsigned int icolmin, icolmax;
+    char formstr[MAX_OBJ_BUF];
+    unsigned int nOdata;
+
+    nOdata = sscanf(objstr, "%*s%s%u%u", formstr, &icolmin, &icolmax);
+
+    if (nOdata == 3)
+        retval = newIcolDataObj(objType, formstr, icolmin, icolmax);
+    else if (nOdata == EOF) {
+        /* No arguments specified.  Use defaults */
+        retval = newIcolDataObj(objType, "%u", 0, 255);
+    } else
+        retval = NULL;
+
+    return retval;
+}
+
+
+
+static SkeletonObject *
+newFcSkelFromReplString(const char *       const objstr,
+                        SkeletonObjectType const objType) {
+
+    SkeletonObject * retval;
+    double fcolmin, fcolmax;
+    char formstr[MAX_OBJ_BUF];
+    unsigned int nOdata;
+
+    nOdata = sscanf(objstr, "%*s%s%lf%lf", formstr,
+                    &fcolmin, &fcolmax);
+
+    if (nOdata == 3)
+        retval = newFcolDataObj(objType, formstr, fcolmin, fcolmax);
+    else if (nOdata == EOF) {
+        /* No arguments specified.  Use defaults */
+        retval = newFcolDataObj(objType, "%f", 0.0, 1.0);
+    } else
+        retval = NULL;
+
+    return retval;
+} 
+
+
+
+static SkeletonObject *
+newISkelFromReplString(const char *       const objstr,
+                       SkeletonObjectType const objType) {
+
+    SkeletonObject * retval;
+    char formstr[MAX_OBJ_BUF];
+    unsigned int const nOdata = sscanf(objstr, "%*s%s", formstr);
+    
+    if (nOdata == 1)
+        retval = newIdataObj(objType, formstr);
+    else if (nOdata == EOF) {
+        /* No arguments specified.  Use defaults */
+        retval = newIdataObj(objType, "%u");
+    } else
+        retval = NULL;
+
+    return retval;
+} 
+
+
+
+static SkeletonObject *
+newSkeletonFromReplString(const char * const objstr) {
+/*----------------------------------------------------------------------------
+  Create a skeleton from the replacement string 'objstr' (the stuff
+  between the parentheses in #(...) ).
+
+  Return NULL if it isn't a valid replacement string.
+-----------------------------------------------------------------------------*/
+    /* We use sscanf() to parse the contents of objstr, giving it a format
+       template with the largest number of fields possible plus one extra to
+       pick up and check for the existence of invalid trailing characters.  We
+       read and discard fields beyond the first, if any.  The appropriate
+       new**SkelFromReplString() function determines their contents with a
+       separate call to sscanf().
+    */
+
+    SkeletonObject * retval;
+    char typstr[MAX_OBJ_BUF];
+    SkeletonObjectType objType;
+    int conversionCt;
+    char s1[MAX_OBJ_BUF];    /* Dry read. */
+    char s2[MAX_OBJ_BUF];    /* Extra tailing characters. */
+    float f1, f2;            /* Dry read. */ 
+
+    typstr[0] = '\0';  /* initial value */
+
+    conversionCt = sscanf(objstr, "%s%s%f%f%s", typstr, s1, &f1, &f2, s2);
+    switch (conversionCt) {
+    case 1: case 2: case 4:
+        objType = interpretObjType(typstr);
+      break;
+    default:
+        objType = BDATA;
+    }
+
+    switch (objClass(objType)) {
+    case OBJTYP_ICOLOR:
+        retval = newIcSkelFromReplString(objstr, objType);
+        break;
+    case OBJTYP_FCOLOR:
+        retval = newFcSkelFromReplString(objstr, objType);
+        break;
+    case OBJTYP_INT:
+        retval = newISkelFromReplString(objstr, objType);
+        break;
+    case OBJTYP_BDATA:
+        retval = NULL;
+    }
+    return retval;
+}
+
+
+
+static void
+readThroughCloseParen(FILE * const ifP,
+                      char * const objstr,
+                      size_t const objstrSize,
+                      bool * const unclosedP) {
+/*----------------------------------------------------------------------------
+   Read *ifP up through close parenthesis ( ')' ) into 'objstr', which
+   is of size 'objstrSize'.  Make it a NUL-terminated string.
+
+   Return *unclosedP true iff we run out of file or run out of objstr
+   before we see a close parenthesis.  In this case, return the rest of
+   the file, or as much as fits, in 'objstr', not NUL-terminated.
+-----------------------------------------------------------------------------*/
+    unsigned int i;
+    bool eof;
+    bool gotEscSeq;
+
+    for (i= 0, eof = false, gotEscSeq = false;
+         i < objstrSize - 1 && !gotEscSeq && !eof;
+         ++i) {
+
+        int rc;
+
+        rc = getc(ifP);
+        if (rc == EOF)
+            eof = true;
+        else {
+            char const chr = rc;
+            if (chr == ')') {
+                gotEscSeq = true;
+                objstr[i] = '\0';
+	        } else
+                objstr[i] = chr;
         }
-        /* Read replacement string up through ')'.  Put contents of
-           parentheses in objstr[].
+    }
+    *unclosedP = !gotEscSeq;
+}
+
+
+
+typedef struct {
+    unsigned int      capacity;
+    SkeletonObject ** skeletonPList;
+    unsigned int      nSkeleton;
+} SkeletonBuffer;
+
+
+
+static void
+SkeletonBuffer_init(SkeletonBuffer *  const bufferP,
+                    unsigned int      const capacity,
+                    SkeletonObject ** const skeletonPList) {
+
+    bufferP->capacity      = capacity;
+    bufferP->skeletonPList = skeletonPList;
+    bufferP->nSkeleton     = 0;
+}
+
+
+
+static void
+SkeletonBuffer_add(SkeletonBuffer * const bufferP,
+                   SkeletonObject * const skeletonP) {
+
+    if (bufferP->nSkeleton >= bufferP->capacity)
+        pm_error("Too many skeletons.  Max = %u", bufferP->capacity);
+
+    bufferP->skeletonPList[bufferP->nSkeleton++] = skeletonP;
+}                   
+
+
+
+typedef struct {
+
+    char data[MAX_LINE_BUF + MAX_OBJ_BUF + 16];
+
+    unsigned int length;
+
+    SkeletonBuffer * skeletonBufferP;
+        /* The buffer to which we flush.  Flushing means turning all the
+           characters currently in our buffer into a binary skeleton object
+           here.
         */
-        for (objlen = 0; objlen < sizeof(objstr)-1; ++objlen) {
-            chr = getc(sklfile);
-            if (chr == EOF) break;
-            if (chr == ')') break;
-            objstr[objlen] = chr;
-        }
-        objstr[objlen] = '\0';
-
-        if (chr != ')') {
-            /* Not valid replacement sequence */
-            unsigned int i;
-            line[slen++] = escape;
-            line[slen++] = chr;
-            for (i = 0; i < objlen; ++i)
-                line[slen++] = objstr[i];
-            if (chr == EOF)
-                break;
-            continue;
-        }
 
-        typstr[0] = '\0';           /* Get typ of data */
-        sscanf(objstr, "%s", typstr);
-
-        otyp = interpretObjType(typstr);
-
-        switch (objClass(otyp)) {
-        case OBJTYP_ICOLOR: {
-            int icolmin, icolmax;
-            char formstr[MAX_OBJ_BUF];
-            int n_odata;
-
-            n_odata = sscanf(objstr, "%*s%s%d%d", formstr, &icolmin, &icolmax);
-
-            if (n_odata == 3) {
-                SAVE_BIN(slen, line);
-                skl[nskl] = save_icol_data(otyp, formstr, icolmin, icolmax);
-                if (skl[nskl] != NULL)
-                    ++nskl;
-            } else if (n_odata == EOF) {
-                /* No arguments specified.  Use defaults */
-                SAVE_BIN(slen, line);
-                skl[nskl] = save_icol_data(otyp, "%d", 0, 255);
-                if (skl[nskl] != NULL)
-                    ++nskl;
-            } else
-                addImpostorReplacementSeq(line, slen, objstr, objlen, &slen);
-        } break;
-        case OBJTYP_FCOLOR: {
-            double fcolmin, fcolmax;
-            char formstr[MAX_OBJ_BUF];
-            int n_odata;
-
-            n_odata = sscanf(objstr, "%*s%s%lf%lf", formstr,
-                             &fcolmin, &fcolmax);
-
-            if (n_odata == 3) {
-                SAVE_BIN(slen, line);
-                skl[nskl] = save_fcol_data(otyp, formstr, fcolmin, fcolmax);
-                if (skl[nskl] != NULL)
-                    ++nskl;
-            } else if (n_odata == EOF) {
-                /* No arguments specified.  Use defaults */
-                SAVE_BIN(slen, line);
-                skl[nskl] = save_fcol_data(otyp, "%f", 0.0, 1.0);
-                if (skl[nskl] != NULL)
-                    ++nskl;
-            } else
-                addImpostorReplacementSeq(line, slen, objstr, objlen, &slen);
-        } break;
-
-        case OBJTYP_INT: {
-            char formstr[MAX_OBJ_BUF];
-            int const n_odata = sscanf(objstr, "%*s%s", formstr);
-
-            if (n_odata == 1) {
-                SAVE_BIN(slen, line);
-                skl[nskl] = save_i_data(otyp, formstr);
-                if (skl[nskl] != NULL)
-                    ++nskl;
-            } else if (n_odata == EOF) {
-                /* No arguments specified.  Use defaults */
-                SAVE_BIN(slen, line);
-                skl[nskl] = save_i_data(otyp, "%d");
-                if (skl[nskl] != NULL)
-                    ++nskl;
-            } else
-                addImpostorReplacementSeq(line, slen, objstr, objlen, &slen);
-        } break;
-        case OBJTYP_BDATA:
-            addImpostorReplacementSeq(line, slen, objstr, objlen, &slen);
+} Buffer;
+
+
+
+static void
+Buffer_init(Buffer *         const bufferP,
+            SkeletonBuffer * const skeletonBufferP) {
+
+    bufferP->skeletonBufferP = skeletonBufferP;
+    bufferP->length = 0;
+}
+
+
+
+static void
+Buffer_flush(Buffer * const bufferP) {
+/*----------------------------------------------------------------------------
+   Flush the buffer out to a binary skeleton object.
+-----------------------------------------------------------------------------*/
+    SkeletonBuffer_add(bufferP->skeletonBufferP,
+                       newBinDataObj(bufferP->length, bufferP->data));
+
+    bufferP->length = 0;
+}
+
+
+
+static void
+Buffer_add(Buffer * const bufferP,
+           char     const newChar) {
+
+    if (bufferP->length >= MAX_LINE_BUF)
+        Buffer_flush(bufferP);
+
+    assert(bufferP->length < MAX_LINE_BUF);
+
+    bufferP->data[bufferP->length++] = newChar;
+}
+
+
+
+static void
+Buffer_dropFinalNewline(Buffer * const bufferP) {
+/*----------------------------------------------------------------------------
+   If the last thing in the buffer is a newline, remove it.
+-----------------------------------------------------------------------------*/
+    if (bufferP->length >= 1 && bufferP->data[bufferP->length-1] == '\n') {
+            /* Drop finishing newline character */
+            --bufferP->length;
+    }
+}
+
+
+
+static void
+addImpostorReplacementSeq(Buffer *     const bufferP,
+                          const char * const seqContents) {
+/*----------------------------------------------------------------------------
+  Add to buffer *bufferP something that looks like a replacement sequence but
+  doesn't have the proper contents (the stuff between the parentheses) to be
+  one.  For example,
+
+  "#(fread x)"
+
+  seqContents[] is the contents, NUL-terminated.
+-----------------------------------------------------------------------------*/
+    const char * p;
+
+    Buffer_add(bufferP, escape);
+    Buffer_add(bufferP, '(');
+
+    for (p = &seqContents[0]; *p; ++p)
+        Buffer_add(bufferP, *p);
+
+    Buffer_add(bufferP, ')');
+}
+
+
+
+static void
+readSkeletonFile(const char *      const filename,
+                 unsigned int      const maxskl,
+                 const char **     const errorP,
+                 unsigned int *    const nSkeletonP,
+                 SkeletonObject ** const skeletonPList) {
+/*----------------------------------------------------------------------------
+-----------------------------------------------------------------------------*/
+    FILE * sklfileP;
+    SkeletonBuffer skeletonBuffer;
+        /* A buffer for accumulating skeleton objects */
+    Buffer buffer;
+        /* A buffer for accumulating binary (literal; unsubstituted) data, on
+           its way to becoming a binary skeleton object. 
+        */
+    bool eof;
+    const char * error;
+
+    SkeletonBuffer_init(&skeletonBuffer, maxskl, skeletonPList);
+
+    Buffer_init(&buffer, &skeletonBuffer);
+
+    sklfileP = pm_openr(filename);
+
+    for (eof = false, error = NULL; !eof && !error; ) {
+
+        int rc;
+
+        rc = getc(sklfileP);
+
+        if (rc == EOF)
+            eof = true;
+        else {
+            char const chr = rc;
+
+            if (chr != escape) {
+                /* Not a replacement sequence; just a literal character */
+                Buffer_add(&buffer, chr);
+            } else {
+                int rc;
+                rc = getc(sklfileP);
+                if (rc == EOF) {
+                    /* Not a replacement sequence, just an escape caharacter
+                       at the end of the file.
+                    */
+                    Buffer_add(&buffer, escape);
+                    eof = true;
+                } else {
+                    char const chr = rc;
+
+                    if (chr != '(') {
+                        /* Not a replacement sequence, just a lone escape
+                           character
+                        */
+                        Buffer_add(&buffer, escape);
+                        Buffer_add(&buffer, chr);
+                    } else {
+                        char objstr[MAX_OBJ_BUF];
+                        bool unclosed;
+                        readThroughCloseParen(sklfileP,
+                                              objstr, sizeof(objstr),
+                                              &unclosed);
+                        if (unclosed)
+                            pm_asprintf(&error, "Unclosed parentheses "
+                                        "in #() escape sequence");
+                        else {
+                            SkeletonObject * const skeletonP =
+                                newSkeletonFromReplString(objstr);
+
+                            if (skeletonP) {
+                                Buffer_flush(&buffer);
+                                SkeletonBuffer_add(&skeletonBuffer, skeletonP);
+                            } else
+                                addImpostorReplacementSeq(&buffer, objstr);
+                        }
+                    }
+                }
+            }
         }
-    } /* EOF of skeleton file */
+    }
 
-    if (slen >= 1 && line[slen-1] == '\n')
-        /* Drop finishing newline character */
-        --slen;
+    if (!error) {
+        Buffer_dropFinalNewline(&buffer);
+        Buffer_flush(&buffer);
+    }
+    *errorP = error;
+    *nSkeletonP = skeletonBuffer.nSkeleton;
 
-    SAVE_BIN(slen, line);  /* Save whatever is left */
+    fclose(sklfileP);
+}
 
-    *nsklP = nskl;
 
-    fclose(sklfile);
-    return 0;
+
+static void
+convertIt(FILE *            const ifP,
+          FILE *            const ofP,
+          SkeletonObject ** const bodySkeletonPList,
+          unsigned int      const bodyNskl,
+          SkeletonObject ** const headSkeletonPList, 
+          unsigned int      const headNskl,
+          SkeletonObject ** const tailSkeletonPList,
+          unsigned int      const tailNskl) {
+
+    pixel * pixelrow;
+    pixval maxval;
+    double dmaxval;
+    int rows, cols;
+    int format;
+    unsigned int row;
+
+    ppm_readppminit(ifP, &cols, &rows, &maxval, &format);
+
+    pixelrow = ppm_allocrow(cols);
+
+    dmaxval = (double)maxval;
+
+    /* Write header */
+    writeText(ofP, headNskl, headSkeletonPList, 
+              cols, rows , 0, 0, 0.0, 0.0, 0.0);
+
+    /* Write raster */
+    for (row = 0; row < rows; ++row) {
+        unsigned int col;
+
+        ppm_readppmrow(ifP, pixelrow, cols, maxval, format);
+
+        for (col = 0; col < cols; ++col) {
+            pixel const thisPixel = pixelrow[col];
+
+            writeText(ofP, bodyNskl, bodySkeletonPList,
+                      cols, rows, col, row,
+                      PPM_GETR(thisPixel)/dmaxval,
+                      PPM_GETG(thisPixel)/dmaxval,
+                      PPM_GETB(thisPixel)/dmaxval);
+        }
+    }
+
+    /* Write trailer */
+    writeText(ofP, tailNskl, tailSkeletonPList, 
+              cols, rows, 0, 0, 0.0, 0.0, 0.0);
 }
 
 
 
-int main( argc, argv )
-int argc;
-char* argv[];
-
-{register int col;
- register pixel* xP;
- pixel* pixelrow;
- pixval maxval,red,green,blue;
- double dmaxval;
- int argn, rows, cols, format, row;
- unsigned int head_nskl,body_nskl,tail_nskl;
- SKL_OBJ *head_skl[MAX_SKL_HEAD_OBJ];
- SKL_OBJ *body_skl[MAX_SKL_BODY_OBJ];
- SKL_OBJ *tail_skl[MAX_SKL_TAIL_OBJ];
- FILE *ifp;
- const char *usage = "bodyskl [ -hd headskl ] [ -tl tailskl ] [pnmfile]";
-
- ppm_init( &argc, argv );
-
- argn = 1;
- if (argn == argc)
-   pm_usage( usage );
-                          /* Read body skeleton file */
- if (read_skeleton (argv[argn],sizeof (body_skl)/sizeof (SKL_OBJ *),
-                    &body_nskl,body_skl) < 0)
-   pm_usage ( usage );
- ++argn;
-
- head_nskl = tail_nskl = 0;
-
- while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0')
- {
-   if ( pm_keymatch ( argv[argn], "-hd", 1) && argn+1 < argc )
-   {
-     argn++;           /* Read header skeleton */
-     if (read_skeleton (argv[argn],sizeof (head_skl)/sizeof (SKL_OBJ *),
-                        &head_nskl,head_skl) < 0)
-       pm_usage ( usage );
-   }
-   else if ( pm_keymatch ( argv[argn], "-tl", 1) && argn+1 < argc )
-   {
-     argn++;           /* Read tail skeleton */
-     if (read_skeleton (argv[argn],sizeof (tail_skl)/sizeof (SKL_OBJ *),
-                        &tail_nskl,tail_skl) < 0)
-       pm_usage ( usage );
-   }
-   else
-   {
-     pm_usage ( usage );
-   }
-   argn++;
- }
-
- if ( argn != argc )
- {
-   ifp = pm_openr( argv[argn] );
-   ++argn;
- }
- else 
- {
-   ifp = stdin;
- }
-
- if ( argn != argc )
-   pm_usage( usage );
-
- ppm_readppminit( ifp, &cols, &rows, &maxval, &format );
- pixelrow = ppm_allocrow( cols );
- dmaxval = (double)maxval;
-
- if (head_nskl > 0)    /* Write header */
-   write_txt (stdout,head_nskl,head_skl,cols,rows,0,0,0.0,0.0,0.0);
-
- for ( row = 0; row < rows; ++row )
- {
-   ppm_readppmrow( ifp, pixelrow, cols, maxval, format );
-
-   for ( col = 0, xP = pixelrow; col < cols; ++col, ++xP )
-   {
-     red = PPM_GETR( *xP );
-     green = PPM_GETG( *xP );
-     blue = PPM_GETB( *xP );
-     write_txt (stdout,body_nskl,body_skl,cols,rows,col,row,
-                red/dmaxval,green/dmaxval,blue/dmaxval);
-   }
- }
-
- if (tail_nskl > 0)    /* Write trailer */
-   write_txt (stdout,tail_nskl,tail_skl,cols,rows,0,0,0.0,0.0,0.0);
-
- pm_close( ifp );
-
- exit( 0 );
+int
+main(int           argc,
+     const char ** argv) {
+    
+    struct CmdlineInfo cmdline;
+
+    unsigned int headNskl, bodyNskl, tailNskl;
+    SkeletonObject * headSkeletonPList[MAX_SKL_HEAD_OBJ];
+    SkeletonObject * bodySkeletonPList[MAX_SKL_BODY_OBJ];
+    SkeletonObject * tailSkeletonPList[MAX_SKL_TAIL_OBJ];
+    FILE * ifP;
+    const char * error;
+
+    pm_proginit(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+
+    ifP = pm_openr(cmdline.inputFileName);
+
+    readSkeletonFile(cmdline.bodySklFileName, ARRAY_SIZE(bodySkeletonPList),
+                     &error, &bodyNskl, bodySkeletonPList);
+    if (error)
+        pm_error("Invalid body skeleton file '%s'.  %s",
+                 cmdline.bodySklFileName, error);
+
+    if (cmdline.hd) {
+        readSkeletonFile(cmdline.hd, ARRAY_SIZE(headSkeletonPList),
+                         &error, &headNskl, headSkeletonPList);
+        if (error)
+            pm_error("Invalid head skeleton file '%s'.  %s",
+                     cmdline.hd, error);
+    } else
+        headNskl = 0;
+
+    if (cmdline.tl) {
+        readSkeletonFile(cmdline.tl, ARRAY_SIZE(tailSkeletonPList),
+                         &error, &tailNskl, tailSkeletonPList);
+        if (error)
+            pm_error("Invalid tail skeleton file '%s'.  %s",
+                     cmdline.tl, error);
+    } else
+        tailNskl = 0;
+
+    if (cmdline.debug)
+        dumpAllSkeleton(bodySkeletonPList, bodyNskl,
+                        headSkeletonPList, headNskl,
+                        tailSkeletonPList, tailNskl);
+
+    convertIt(ifP, stdout,
+              bodySkeletonPList, bodyNskl,
+              headSkeletonPList, headNskl,
+              tailSkeletonPList, tailNskl);
+
+    pm_close(ifP);
+
+    return 0;
 }
+
+
diff --git a/converter/ppm/ppmtoascii.c b/converter/ppm/ppmtoascii.c
new file mode 100644
index 00000000..6b0b04d7
--- /dev/null
+++ b/converter/ppm/ppmtoascii.c
@@ -0,0 +1,236 @@
+/*=============================================================================
+                                  ppmtoascii
+===============================================================================
+
+  Convert a PPM image to ASCII with ANSI color graphics terminal controls
+
+  Based on pbmtoascii.
+  Copyright (C) 1988, 1992 by Jef Poskanzer.
+  Copyright (C) 2010 by Frank Ch. Eigler.
+
+  Permission to use, copy, modify, and distribute this software and its
+  documentation for any purpose and without fee is hereby granted, provided
+  that the above copyright notice appear in all copies and that both that
+  copyright notice and this permission notice appear in supporting
+  documentation.  This software is provided "as is" without express or
+  implied warranty.
+=============================================================================*/
+
+#include "pm_c_util.h"
+#include "mallocvar.h"
+#include "shhopt.h"
+#include "ppm.h"
+#include "pm_gamma.h"
+
+/* We use the same algorithm for converting many pixels into a character
+   as Pbmtoascii.  See pbmtoascii.c for a full explanation.
+*/
+
+
+#define SQQ '\''
+#define BSQ '\\'
+
+/* Bit-map for 1x2 mode:
+**     1
+**     2
+*/
+static char const carr1x2[4] = {
+/*   0    1    2    3   */
+    ' ', '"', 'o', 'M' };
+
+/* Bit-map for 2x4 mode (hex):
+**     1  2
+**     4  8
+**     10 20
+**     40 80
+** The idea here is first to preserve geometry, then to show density.
+*/
+#define D08 'M'
+#define D07 'H'
+#define D06 '&'
+#define D05 '$'
+#define D04 '?'
+static char const carr2x4[256] = {
+/*0  1    2   3    4   5    6   7    8   9    A   B    C   D    E   F  */
+' ',SQQ, '`','"', '-',SQQ, SQQ,SQQ, '-','`', '`','`', '-','^','^','"',/*00-0F*/
+'.',':', ':',':', '|','|', '/',D04, '/','>', '/','>', '~','+','/','*',/*10-1F*/
+'.',':', ':',':', BSQ,BSQ, '<','<', '|',BSQ, '|',D04, '~',BSQ,'+','*',/*20-2F*/
+'-',':', ':',':', '~',D04, '<','<', '~','>', D04,'>', '=','b','d','#',/*30-3F*/
+'.',':', ':',':', ':','!', '/',D04, ':',':', '/',D04, ':',D04,D04,'P',/*40-4F*/
+',','i', '/',D04, '|','|', '|','T', '/',D04, '/','7', 'r','}','/','P',/*50-5F*/
+',',':', ';',D04, '>',D04, 'S','S', '/',')', '|','7', '>',D05,D05,D06,/*60-6F*/
+'v',D04, D04,D05, '+','}', D05,'F', '/',D05, '/',D06, 'p','D',D06,D07,/*70-7F*/
+'.',':', ':',':', ':',BSQ, ':',D04, ':',BSQ, '!',D04, ':',D04,D04,D05,/*80-8F*/
+BSQ,BSQ, ':',D04, BSQ,'|', '(',D05, '<','%', D04,'Z', '<',D05,D05,D06,/*90-9F*/
+',',BSQ, 'i',D04, BSQ,BSQ, D04,BSQ, '|','|', '|','T', D04,BSQ,'4','9',/*A0-AF*/
+'v',D04, D04,D05, BSQ,BSQ, D05,D06, '+',D05, '{',D06, 'q',D06,D06,D07,/*B0-BF*/
+'_',':', ':',D04, ':',D04, D04,D05, ':',D04, D04,D05, ':',D05,D05,D06,/*C0-CF*/
+BSQ,D04, D04,D05, D04,'L', D05,'[', '<','Z', '/','Z', 'c','k',D06,'R',/*D0-DF*/
+',',D04, D04,D05, '>',BSQ, 'S','S', D04,D05, 'J',']', '>',D06,'1','9',/*E0-EF*/
+'o','b', 'd',D06, 'b','b', D06,'6', 'd',D06, 'd',D07, '#',D07,D07,D08 /*F0-FF*/
+};
+
+
+
+static const char* rgb2x2x2fg[2][2][2] = {
+  {{"\x1b[30m",   /* 000 black */
+    "\x1b[34m"},  /* 001 blue */
+   {"\x1b[32m",   /* 010 green */
+    "\x1b[36m"}}, /* 011 cyan */
+  {{"\x1b[31m",   /* 100 red */
+    "\x1b[35m"},  /* 101 magenta */
+   {"\x1b[33m",   /* 110 yellow */
+    "\x1b[37m"}}, /* 111 white */
+};
+
+
+
+struct cmdlineInfo {
+    /* All the information the user supplied in the command line,
+       in a form easy for the program to use.
+    */
+    const char * inputFileName;  /* Name of input file */
+    unsigned int cellWidth;
+    unsigned int cellHeight;
+    const char * carr;
+};
+
+
+
+static void
+parseCommandLine(int argc, const char **argv,
+                 struct cmdlineInfo * const cmdlineP) {
+
+    optEntry * option_def;
+        /* Instructions to OptParseOptions3 on how to parse our options */
+    optStruct3 opt;
+
+    unsigned int option_def_index;
+    unsigned int dim1x2Spec, dim2x4Spec;
+
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    option_def_index = 0;   /* incremented by OPTENTRY */
+    OPTENT3(0, "1x2", OPT_FLAG, NULL, &dim1x2Spec, 0);
+    OPTENT3(0, "2x4", OPT_FLAG, NULL, &dim2x4Spec, 0);
+
+    opt.opt_table = option_def;
+    opt.short_allowed = false;  /* We have no short (old-fashioned) options */
+    opt.allowNegNum = false;  /* We have no parms that are negative numbers */
+
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
+
+    if (dim1x2Spec && dim2x4Spec)
+        pm_error("You cannot specify both -1x2 and -2x4");
+    else if (dim2x4Spec) {
+        cmdlineP->cellWidth  = 2;
+        cmdlineP->cellHeight = 4;
+        cmdlineP->carr       = carr2x4;
+    } else {
+        cmdlineP->cellWidth  = 1;
+        cmdlineP->cellHeight = 2;
+        cmdlineP->carr       = carr1x2;
+    }
+
+    if (argc-1 < 1)
+        cmdlineP->inputFileName = "-";
+    else {
+        cmdlineP->inputFileName = argv[1];
+
+        if (argc-1 > 1)
+            pm_error("Too many arguments: %u.  The only possible argument "
+                     "is the input file name", argc-1);
+    }
+}
+
+
+
+static void
+ppmtoascii(pixel * const *    const pixels,
+           unsigned int       const cols,
+           unsigned int       const rows,
+           pixval             const maxval,
+           struct cmdlineInfo const cmdline,
+           FILE *             const ofP) {
+
+    unsigned int const cellHeight = cmdline.cellHeight;
+    unsigned int const cellWidth  = cmdline.cellWidth;
+    const char * const carr       = cmdline.carr;
+    unsigned int row;
+
+    fprintf(ofP, "\x1b[0m"); /* Clear initial ansi attributes */
+    /* TODO: set background to black */
+
+    for (row = 0; row < rows; row += cellHeight) {
+        unsigned int col;
+        for (col = 0; col < cols; col += cellWidth)	{
+            unsigned int const sumthresh = cellWidth * cellHeight * 1.0 / 2;
+
+            float sumr, sumg, sumb;
+                /* sum of intensity within cell so far, by component */
+            unsigned int b;
+            const char * colorstr;
+            unsigned int subrow;
+
+            sumr = sumg = sumb = 0;  /* initial value */
+            b = 0; /* initial value */
+
+            for (subrow = 0; subrow < cellHeight; ++subrow) {
+                unsigned int subcol;
+                for (subcol = 0; subcol < cellWidth; ++subcol) {
+                    pixel color;
+                    pixval value;
+                
+                    if (row + subrow < rows && col + subcol < cols)
+                        color = pixels[row + subrow][col + subcol];
+                    else
+                        color = ppm_whitepixel (maxval);
+
+                    sumr += pm_ungamma709((float)PPM_GETR(color)/maxval);
+                    sumg += pm_ungamma709((float)PPM_GETG(color)/maxval);
+                    sumb += pm_ungamma709((float)PPM_GETB(color)/maxval);
+
+                    value = ppm_colorvalue(color);
+                    b <<= 1;
+                    if (value > maxval/2)
+                        b |= 1;
+                }
+            }
+            colorstr = rgb2x2x2fg
+                [sumr >= sumthresh]
+                [sumg >= sumthresh]
+                [sumb >= sumthresh];
+            fprintf(ofP, "%s%c", colorstr, carr[b]);
+        }
+        fprintf(ofP, "\n");
+    }
+    fprintf(ofP, "\x1b[0m"); /* Clear final ansi attributes */
+}
+
+
+
+int
+main(int argc, const char ** argv) {
+
+    struct cmdlineInfo cmdline;
+    FILE * ifP;
+
+    pixval maxval;
+    pixel ** pixels;
+    int rows, cols;
+
+    pm_proginit(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+
+    ifP = pm_openr(cmdline.inputFileName);
+    
+    pixels = ppm_readppm(ifP, &cols, &rows, &maxval);
+
+    pm_close(ifP);
+
+    ppmtoascii(pixels, cols, rows, maxval, cmdline, stdout);
+
+    return 0;
+}
diff --git a/converter/ppm/ppmtobmp.c b/converter/ppm/ppmtobmp.c
index c295f70c..6d65d744 100644
--- a/converter/ppm/ppmtobmp.c
+++ b/converter/ppm/ppmtobmp.c
@@ -20,6 +20,7 @@
 #include <string.h>
 
 #include "pm_c_util.h"
+#include "nstring.h"
 #include "mallocvar.h"
 #include "shhopt.h"
 #include "bmp.h"
@@ -63,11 +64,11 @@ freeColorMap(const colorMap * const colorMapP) {
 
 
 
-struct cmdlineInfo {
+struct CmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
-    char *input_filename;
+    const char * inputFilename;
     int class;  /* C_WIN or C_OS2 */
     unsigned int bppSpec;
     unsigned int bpp;
@@ -77,7 +78,7 @@ struct cmdlineInfo {
 
 static void
 parseCommandLine(int argc, const char ** argv,
-                 struct cmdlineInfo * const cmdlineP) {
+                 struct CmdlineInfo * const cmdlineP) {
 /*----------------------------------------------------------------------------
    Note that many of the strings that this function returns in the
    *cmdline_p structure are actually in the supplied argv array.  And
@@ -107,7 +108,7 @@ parseCommandLine(int argc, const char ** argv,
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
 
-    optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
 
     if (windowsSpec && os2Spec) 
         pm_error("Can't specify both -windows and -os2 options.");
@@ -131,13 +132,22 @@ parseCommandLine(int argc, const char ** argv,
         cmdlineP->mapfile = NULL;
 
     if (argc - 1 == 0)
-        cmdlineP->input_filename = strdup("-");  /* he wants stdin */
+        cmdlineP->inputFilename = pm_strdup("-");  /* he wants stdin */
     else if (argc - 1 == 1)
-        cmdlineP->input_filename = strdup(argv[1]);
+        cmdlineP->inputFilename = pm_strdup(argv[1]);
     else 
         pm_error("Too many arguments.  The only argument accepted "
                  "is the input file specificaton");
 
+    free(option_def);
+}
+
+
+
+static void
+freeCommandLine(struct CmdlineInfo const cmdline) {
+
+    pm_strfree(cmdline.inputFilename);
 }
 
 
@@ -177,20 +187,18 @@ PutLong(FILE * const fp, long const v) {
  * BMP writing
  */
 
-static int
+static unsigned int
 BMPwritefileheader(FILE *        const fp, 
-                   int           const class, 
-                   unsigned long const bitcount, 
-                   unsigned long const x, 
-                   unsigned long const y) {
+                   unsigned int  const cbSize,
+                   unsigned int  const offBits) {
 /*----------------------------------------------------------------------------
-  Return the number of bytes written, or -1 on error.
+  Return the number of bytes written.
 -----------------------------------------------------------------------------*/
     PutByte(fp, 'B');
     PutByte(fp, 'M');
 
     /* cbSize */
-    PutLong(fp, BMPlenfile(class, bitcount, -1, x, y));
+    PutLong(fp, cbSize);
     
     /* xHotSpot */
     PutShort(fp, 0);
@@ -199,7 +207,7 @@ BMPwritefileheader(FILE *        const fp,
     PutShort(fp, 0);
     
     /* offBits */
-    PutLong(fp, BMPoffbits(class, bitcount, -1));
+    PutLong(fp, offBits);
     
     return 14;
 }
@@ -213,9 +221,9 @@ BMPwriteinfoheader(FILE *        const fp,
                    unsigned long const x, 
                    unsigned long const y) {
 /*----------------------------------------------------------------------------
-  Return the number of bytes written, or -1 on error.
+  Return the number of bytes written.
 ----------------------------------------------------------------------------*/
-    long cbFix;
+    unsigned int cbFix;
 
     switch (class) {
     case C_WIN: {
@@ -266,7 +274,7 @@ BMPwriteRgb(FILE * const fp,
             pixval const G, 
             pixval const B) {
 /*----------------------------------------------------------------------------
-  Return the number of bytes written, or -1 on error.
+  Return the number of bytes written.
 -----------------------------------------------------------------------------*/
     switch (class) {
     case C_WIN:
@@ -282,8 +290,8 @@ BMPwriteRgb(FILE * const fp,
         return 3;
     default:
         pm_error(er_internal, "BMPwriteRgb");
+        return -1;  /* avoid compiler warning. */
     }
-    return -1;
 }
 
 
@@ -294,7 +302,7 @@ BMPwriteColormap(FILE *           const ifP,
                  int              const bpp,
                  const colorMap * const colorMapP) {
 /*----------------------------------------------------------------------------
-  Return the number of bytes written, or -1 on error.
+  Return the number of bytes written.
 -----------------------------------------------------------------------------*/
     unsigned int const ncolors = (1 << bpp);
 
@@ -445,7 +453,7 @@ BMPwritebits(FILE *          const fp,
              pixval          const maxval,
              colorhash_table const cht) {
 /*----------------------------------------------------------------------------
-  Return the number of bytes written, or -1 on error.
+  Return the number of bytes written.
 -----------------------------------------------------------------------------*/
     unsigned int nbyte;
     int row;
@@ -490,6 +498,9 @@ bmpEncode(FILE *           const ifP,
 /*----------------------------------------------------------------------------
   Write a BMP file of the given class.
 -----------------------------------------------------------------------------*/
+    unsigned int const cbSize  = BMPlenfile(class, bpp, 0, x, y);
+    unsigned int const offbits = BMPoffbits(class, bpp, 0);
+
     unsigned long nbyte;
 
     if (colortype == PALETTE)
@@ -498,19 +509,17 @@ bmpEncode(FILE *           const ifP,
         pm_message("Writing %u bits per pixel truecolor (no palette)", bpp);
 
     nbyte = 0;  /* initial value */
-    nbyte += BMPwritefileheader(ifP, class, bpp, x, y);
+    nbyte += BMPwritefileheader(ifP, cbSize, offbits);
     nbyte += BMPwriteinfoheader(ifP, class, bpp, x, y);
     if (colortype == PALETTE)
         nbyte += BMPwriteColormap(ifP, class, bpp, colorMapP);
 
-    if (nbyte != (BMPlenfileheader(class)
-                  + BMPleninfoheader(class)
-                  + BMPlencolormap(class, bpp, 0)))
+    if (nbyte != offbits)
         pm_error(er_internal, "BmpEncode 1");
 
     nbyte += BMPwritebits(ifP, x, y, colortype, bpp, pixels, maxval,
                           colorMapP->cht);
-    if (nbyte != BMPlenfile(class, bpp, -1, x, y))
+    if (nbyte != cbSize)
         pm_error(er_internal, "BmpEncode 2");
 }
 
@@ -544,6 +553,8 @@ bmpEncodePbm(FILE *           const ifP,
        Only PBM input uses this routine.  Color images represented by 1 bpp via
        color palette use the general bmpEncode().
     */
+    unsigned int const cbSize       = BMPlenfile(class, 1, 0, cols, rows);
+    unsigned int const offbits      = BMPoffbits(class, 1, 0);
     unsigned int const adjustedCols = (cols + 31) / 32 * 32;
     unsigned int const packedBytes  = adjustedCols / 8;
 
@@ -555,18 +566,16 @@ bmpEncodePbm(FILE *           const ifP,
     pm_message("Writing 1 bit per pixel with a black-white palette");
 
     nbyte = 0;  /* initial value */
-    nbyte += BMPwritefileheader(ifP, class, 1, cols, rows);
+    nbyte += BMPwritefileheader(ifP, cbSize, offbits);
     nbyte += BMPwriteinfoheader(ifP, class, 1, cols, rows);
 
     makeBilevelColorMap(&bilevelColorMap);
 
     nbyte += BMPwriteColormap(ifP, class, 1, &bilevelColorMap);
 
-    if (nbyte != (BMPlenfileheader(class)
-                  + BMPleninfoheader(class)
-                  + BMPlencolormap(class, 1, 0)))
-        pm_error(er_internal, "bmpEncodePBM 1");
-   
+    if (nbyte != offbits)
+        pm_error(er_internal, "bmpEncodePbm 1");
+
     for (row = 0; row < rows; ++row){
         size_t bytesWritten;
 
@@ -581,7 +590,7 @@ bmpEncodePbm(FILE *           const ifP,
             nbyte += bytesWritten;
     }
 
-    if (nbyte != BMPlenfile(class, 1, -1, cols, rows))
+    if (nbyte != cbSize)
         pm_error(er_internal, "bmpEncodePbm 2");
 }
 
@@ -822,7 +831,6 @@ doPbm(FILE *       const ifP,
         32 bit borders and that in BMP the bottom row comes first in
         order.
     */
-    int const CHARBITS = (sizeof(unsigned char)*8); 
     int const colChars = pbm_packed_bytes(cols);
     int const adjustedCols = (cols+31) /32 * 32;
     int const packedBytes  =  adjustedCols /8;
@@ -854,11 +862,8 @@ doPbm(FILE *       const ifP,
            some BMP viewers may get confused with that.
         */
 
-        if (cols % 8 >0) {
-            /* adjust final partial byte */
-            thisRow[colChars-1] >>= CHARBITS - cols % CHARBITS;
-            thisRow[colChars-1] <<= CHARBITS - cols % CHARBITS;
-        }
+        /* Clean off remainder of fractional last character */
+        pbm_cleanrowend_packed(thisRow, cols);
     }
 
     bmpEncodePbm(ofP, class, cols, rows, bitrow);
@@ -908,6 +913,8 @@ doPgmPpm(FILE *       const ifP,
               cols, rows, (const pixel**)pixels, maxval, &colorMap);
     
     freeColorMap(&colorMap);
+
+    ppm_freearray(pixels, rows);
 }
 
 
@@ -916,7 +923,7 @@ int
 main(int           argc,
      const char ** argv) {
 
-    struct cmdlineInfo cmdline;
+    struct CmdlineInfo cmdline;
     FILE * ifP;
     int rows;
     int cols;
@@ -927,7 +934,7 @@ main(int           argc,
 
     parseCommandLine(argc, argv, &cmdline);
 
-    ifP = pm_openr(cmdline.input_filename);
+    ifP = pm_openr(cmdline.inputFilename);
     
     ppm_readppminit(ifP, &cols, &rows, &maxval, &ppmFormat);
     
@@ -938,6 +945,8 @@ main(int           argc,
                  cmdline.class, cmdline.bppSpec, cmdline.bpp, cmdline.mapfile,
                  stdout);
 
+    freeCommandLine(cmdline);
+
     pm_close(ifP);
     pm_close(stdout);
 
diff --git a/converter/ppm/ppmtogif.c b/converter/ppm/ppmtogif.c
index 93feaa95..fa7d1dbe 100644
--- a/converter/ppm/ppmtogif.c
+++ b/converter/ppm/ppmtogif.c
@@ -68,7 +68,7 @@ handleLatex2htmlHack(void) {
   This program used to put out a "usage" message when it saw an option
   it didn't understand.  Latex2html's configure program does a
   ppmtogif -h (-h was never a valid option) to elicit that message and
-  then parses the message to see if it included the strings
+  then parses the message to see if it includes the strings
   "-interlace" and "-transparent".  That way it knows if the
   'ppmtogif' program it found has those options or not.  I don't think
   any 'ppmtogif' you're likely to find today lacks those options, but
@@ -91,7 +91,7 @@ handleLatex2htmlHack(void) {
 
 
 static void
-parseCommandLine(int argc, char ** argv,
+parseCommandLine(int argc, const char ** argv,
                  struct cmdlineInfo * const cmdlineP) {
 /*----------------------------------------------------------------------------
    Parse the program arguments (given by argc and argv) into a form
@@ -146,7 +146,7 @@ parseCommandLine(int argc, char ** argv,
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
 
-    optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
     if (latex2htmlhack) 
@@ -183,8 +183,8 @@ openPnmremapStream(const char * const inputFileName,
     assert(inputFileName != NULL);
     assert(mapFileName != NULL);
 
-    asprintfN(&pnmremapCommand, "pnmremap -mapfile='%s' %s",
-              mapFileName, inputFileName);
+    pm_asprintf(&pnmremapCommand, "pnmremap -mapfile='%s' %s",
+                mapFileName, inputFileName);
 
     if (verbose)
         pm_message("Preprocessing Pamtogif input with shell command '%s'",
@@ -198,7 +198,7 @@ openPnmremapStream(const char * const inputFileName,
     else
         *pnmremapPipeP = pnmremapPipe;
 
-    strfree(pnmremapCommand);
+    pm_strfree(pnmremapCommand);
 }
 
 
@@ -221,39 +221,39 @@ pamtogifCommand(const char *       const arg0,
 
         struct stat statbuf;
 
-        asprintfN(&progName, "%s/%s", arg0DirName, pamtogifName);
+        pm_asprintf(&progName, "%s/%s", arg0DirName, pamtogifName);
 
         if (stat(progName, &statbuf) == 0)
             commandVerb = progName;
         else
             commandVerb = strdup(pamtogifName);
 
-        strfree(arg0DirName);
+        pm_strfree(arg0DirName);
     } else
         commandVerb = strdup(pamtogifName);
 
     if (cmdline.transparent)
-        asprintfN(&transparentOpt, "-transparent=%s", cmdline.transparent);
+        pm_asprintf(&transparentOpt, "-transparent=%s", cmdline.transparent);
     else
         transparentOpt = strdup("");
 
     if (cmdline.comment)
-        asprintfN(&commentOpt, "-comment=%s", cmdline.comment);
+        pm_asprintf(&commentOpt, "-comment=%s", cmdline.comment);
     else
         commentOpt = strdup("");
 
-    asprintfN(&retval, "%s - -alphacolor=%s %s %s %s %s %s %s",
-              commandVerb,
-              cmdline.alphacolor,
-              cmdline.interlace ? "-interlace" : "",
-              cmdline.sort ? "-sort" : "",
-              transparentOpt,
-              commentOpt,
-              cmdline.nolzw ? "-nolzw" : "",
-              cmdline.verbose ? "-verbose" : "");
+    pm_asprintf(&retval, "%s - -alphacolor=%s %s %s %s %s %s %s",
+                commandVerb,
+                cmdline.alphacolor,
+                cmdline.interlace ? "-interlace" : "",
+                cmdline.sort ? "-sort" : "",
+                transparentOpt,
+                commentOpt,
+                cmdline.nolzw ? "-nolzw" : "",
+                cmdline.verbose ? "-verbose" : "");
     
-    strfree(transparentOpt);
-    strfree(commentOpt);
+    pm_strfree(transparentOpt);
+    pm_strfree(commentOpt);
 
     return retval;
 }
@@ -374,8 +374,8 @@ feedPamtogif(struct pam * const inPamP,
 
 
 int
-main(int    argc,
-     char * argv[]) {
+main(int           argc,
+     const char ** argv) {
 
     struct cmdlineInfo cmdline;
     FILE * ifP;
@@ -384,7 +384,7 @@ main(int    argc,
     FILE * pipeToPamtogif;
     int rc;
 
-    pnm_init(&argc, argv);
+    pm_proginit(&argc, argv);
 
     parseCommandLine(argc, argv, &cmdline);
 
@@ -413,7 +413,7 @@ main(int    argc,
     if (rc != 0)
         pm_error("Pamtogif process failed.  pclose() failed.");
 
-    strfree(command);
+    pm_strfree(command);
 
     pm_close(ifP);
     pm_close(stdout);
diff --git a/converter/ppm/ppmtoicr.c b/converter/ppm/ppmtoicr.c
index feca0c18..3c8be421 100644
--- a/converter/ppm/ppmtoicr.c
+++ b/converter/ppm/ppmtoicr.c
@@ -10,311 +10,255 @@
 ** implied warranty.
 */
 
+#include <stdbool.h>
+#include <assert.h>
 #include "ppm.h"
 
-#define MAXCOLORS 256
-#define CLUTCOLORS 768
+#define MAXCOLORCT 256
+#define CLUTCOLORCT 768
 
-static int colorstobpp ARGS(( int colors ));
-static int GetPixel ARGS(( int x, int y ));
-static int rleit ARGS(( char* buf, char* bufto, int len ));
 
-static pixel** pixels;
-static colorhash_table cht;
-static char* testimage;
 
-int
-main(argc, argv)
-int argc;
-char* argv[];
-{
-	FILE* ifp;
-	int argn, rows, cols, colors, i, j, BitsPerPixel, newxsize;
-	pixval maxval;
-	colorhist_vector chv;
-	char rgb[CLUTCOLORS];
-	const char* windowname;
-	char* thischar;
-	char* thisline;
-	char* space;
-	register unsigned char c;
-	register char* p;
-	int display, expand;
-	int rleflag, winflag;
-	const char* const usage = "[-windowname windowname] [-expand expand] [-display display] [-rle] [ppmfile]";
-
-
-	ppm_init( &argc, argv );
-
-	argn = 1;
-	windowname = "untitled";
-	winflag = 0;
-	expand = 1;
-	display = 0;
-	rleflag = 0;
-
-	while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
-	    {
-	    if ( pm_keymatch(argv[argn],"-windowname",2) && argn + 1 < argc )
-		{
-		++argn;
-		windowname = argv[argn];
-		winflag = 1;
-		}
-	    else if ( pm_keymatch(argv[argn],"-expand",2) && argn + 1 < argc )
-		{
-		++argn;
-		if ( sscanf( argv[argn], "%d",&expand ) != 1 )
-		    pm_usage( usage );
-		}
-	    else if ( pm_keymatch(argv[argn],"-display",2) && argn + 1 < argc )
-		{
-		++argn;
-		if ( sscanf( argv[argn], "%d",&display ) != 1 )
-		    pm_usage( usage );
-		}
-	    else if ( pm_keymatch(argv[argn],"-rle",2) )
-		rleflag = 1;
-	    else if ( pm_keymatch(argv[argn],"-norle",2) )
-		rleflag = 0;
-	    else
-		pm_usage( usage );
-	    }
-
-	if ( argn < argc )
-	    {
-	    ifp = pm_openr( argv[argn] );
-	    if ( ! winflag )
-		windowname = argv[argn];
-	    ++argn;
-	    }
-	else
-	    ifp = stdin;
-
-	if ( argn != argc )
-	    pm_usage( usage );
-
-	pixels = ppm_readppm( ifp, &cols, &rows, &maxval );
-
-	pm_close( ifp );
-
-	for (i = 0; i < CLUTCOLORS; i++)
-	    rgb[i] = 0;
-
-	/* Figure out the colormap. */
-	pm_message("computing colormap..." );
-	chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &colors);
-	if (chv == (colorhist_vector) 0)
-	pm_error( "too many colors - try doing a 'pnmquant %d'", MAXCOLORS );
-	pm_message("%d colors found", colors );
-
-	/* Turn the ppm colormap into an ICR colormap. */
-	if (maxval > 255)
-	pm_message(
-		"maxval is not 255 - automatically rescaling colors" );
-	for (i = 0; i < colors; i++)
-	{
-	j = (3 * i);
-	if (maxval == 255)
-		{
-		rgb[j] = PPM_GETR(chv[i].color) ;
-		j++;
-		rgb[j] = PPM_GETG(chv[i].color) ;
-		j++;
-		rgb[j] = PPM_GETB(chv[i].color) ;
-		}
-	else
-		{
-		rgb[j] = (int) PPM_GETR(chv[i].color) * 255 / maxval;
-		j++;
-		rgb[j] = (int) PPM_GETG(chv[i].color) * 255 / maxval;
-		j++;
-		rgb[j] = (int) PPM_GETB(chv[i].color) * 255 / maxval;
-		}
-	}
-	BitsPerPixel = colorstobpp(colors);
-
-	/* And make a hash table for fast lookup. */
-	cht = ppm_colorhisttocolorhash(chv, colors);
-	ppm_freecolorhist(chv);
-
-
-	/************** Create a new window using ICR protocol *********/
-	/* Format is "ESC^W;left;top;width;height;display;windowname"  */
-
-	pm_message("creating window %s ...", windowname );
-	(void)printf("\033^W;%d;%d;%d;%d;%d;%s^",0,0,cols*expand,rows*expand,display,windowname);
-	fflush(stdout);
-
-
-	/****************** Download the colormap.  ********************/
-	pm_message("downloading colormap for %s ...", windowname );
-
-	(void)printf("\033^M;%d;%d;%d;%s^",0,MAXCOLORS,CLUTCOLORS,windowname);
-	thischar = rgb;
-	for (j=0; j<CLUTCOLORS; j++) {
-	c = *thischar++;
-		if (c > 31 && c < 123 ) {	 /* printable ASCII */
-		putchar(c);
-		}
-		else {
-		putchar((c>>6)+123);	 /* non-printable, so encode it */
-		putchar((c & 0x3f) + 32);
-		}
-	}
-	fflush(stdout);
-
-	/**************** send out picture *************************/
-	/* Protocol's RLE scheme is quicker but buggy              */
-
-	if (rleflag) {	
-		pm_message("sending run-length encoded picture data ..." );
-		testimage = (char*) malloc(rows*cols);
-		p = testimage;
-		for (i=0; i<rows; i++)
-			for (j=0; j<cols; j++) 
-			*p++ = GetPixel(j,i);
-		space = (char*) malloc(rows*3);
-		thisline = testimage;
-		for (i = 0; i < rows; i++) {
-			newxsize = rleit(thisline,space,cols);
-			thisline += cols;	/* increment to next line */
-		(void)printf("\033^R;%d;%d;%d;%d;%s^",0,i*expand,expand,newxsize,windowname);
-		thischar = space;
-		for (j=0; j< newxsize; j++) {
-			c= *thischar++;  /*get byte to send */
-			if (c>31 && c <123) {
-				putchar(c);
-				}
-			else {
-				putchar((c>>6) + 123);
-				putchar((c & 0x3f) + 32);
-				}
-			}
-			fflush(stdout);
-		}
-		free(space);
-		exit(0);
-		}
-
-	/* Otherwise, send out uncompressed pixel data via the slow method */
-
-		else {
-		pm_message("sending picture data ..." );
-		for (i = 0; i < rows; i++) {
-			(void)printf("\033^P;%d;%d;%d;%d;%s^",0,i*expand,expand,cols,windowname);
-			for (j = 0; j < cols; j++) {
-				c  = GetPixel(j,i);
-				if (c > 31 && c < 123) {
-						putchar(c);
-						}
-				else		{
-						putchar((c>>6)+123);
-						putchar((c & 0x3f) + 32);
-						}
-				}
-			}
-		fflush(stdout);
-		exit(0);
-		}
-	}
+static void
+makeIcrColormap(colorhist_vector const chv,
+                unsigned int     const colorCt,
+                pixval           const maxval,
+                char *           const rgb) {
+
+    unsigned int i;
+
+    if (maxval > 255)
+        pm_message("Maxval is not 255 - automatically rescaling colors" );
+
+    for (i = 0; i < CLUTCOLORCT; ++i)
+        rgb[i] = 0;
+
+    for (i = 0; i < colorCt; ++i) {
+        unsigned int j;
+
+        j = (3 * i);
+
+        if (maxval == 255) {
+            rgb[j++] = PPM_GETR(chv[i].color) ;
+            rgb[j++] = PPM_GETG(chv[i].color) ;
+            rgb[j++] = PPM_GETB(chv[i].color) ;
+        } else {
+            rgb[j++] = (unsigned int) PPM_GETR(chv[i].color) * 255 / maxval;
+            rgb[j++] = (unsigned int) PPM_GETG(chv[i].color) * 255 / maxval;
+            rgb[j++] = (unsigned int) PPM_GETB(chv[i].color) * 255 / maxval;
+        }
+    }
+}
+
+
 
 static int
-colorstobpp(colors)
-int colors;
-	{
-	int bpp;
-
-	if (colors <= 2)
-	bpp = 1;
-	else if (colors <= 4)
-	bpp = 2;
-	else if (colors <= 8)
-	bpp = 3;
-	else if (colors <= 16)
-	bpp = 4;
-	else if (colors <= 32)
-	bpp = 5;
-	else if (colors <= 64)
-	bpp = 6;
-	else if (colors <= 128)
-	bpp = 7;
-	else if (colors <= 256)
-	bpp = 8;
-	else
-	pm_error("can't happen" );
-	return bpp;
-	}
+bppFromColorCt(unsigned int const colorCt) {
+
+    unsigned int bpp;
+
+    if (colorCt <= 2)
+        bpp = 1;
+    else if (colorCt <= 4)
+        bpp = 2;
+    else if (colorCt <= 8)
+        bpp = 3;
+    else if (colorCt <= 16)
+        bpp = 4;
+    else if (colorCt <= 32)
+        bpp = 5;
+    else if (colorCt <= 64)
+        bpp = 6;
+    else if (colorCt <= 128)
+        bpp = 7;
+    else if (colorCt <= 256)
+        bpp = 8;
+    else
+        assert(false);
+
+    return bpp;
+}
+
+
 
 static int
-GetPixel(x, y)
-int x, y;
-	{
-	int color;
+colorIndexAtPosition(unsigned int    const x,
+                     unsigned int    const y,
+                     pixel **        const pixels,
+                     colorhash_table const cht) {
 
-	color = ppm_lookupcolor(cht, &pixels[y][x]);
-	return color;
-	}
+    int rc;
 
+    rc = ppm_lookupcolor(cht, &pixels[y][x]);
 
-/* rleit   compress with run length encoding as per NCSA's documentation */
+    /* Every color in the image is in the palette */
+    assert(rc >= 0);
 
-static int
-rleit(buf,bufto,len)
-	char* buf;
-	char* bufto;
-	int len;
-	{
-	register char* p;
-	register char* q;
-	register char* cfoll;
-	register char* clead;
-	char* begp;
-	int i;
-
-	p = buf;
-	cfoll = bufto;
-	clead = cfoll + 1;
-
-	begp = p;
-	while (len > 0 ) {		/* encode until gone */
-		
-		q = p + 1;
-		i = len-1;
-	while (*p == *q && i+120 > len && i) {
-		q++;
-		i--;
-	}
-
-	if (q > p +2) {			/* three in a row */
-		if (p > begp) {
-			*cfoll = p - begp;
-			cfoll = clead;
-		}
-		*cfoll++ = 128 | (q-p);		/*len of seq*/
-		*cfoll++ = *p;			/* char of seq */
-		len -= q-p;		/* subtract len of seq */
-		p = q;
-		clead = cfoll+1;
-		begp = p;
-	}
-	else {
-		*clead++ = *p++;	/* copy one char */
-		len--;
-		if (p>begp + 120) {
-			*cfoll = p - begp;
-			cfoll = clead++;
-			begp = p;
-		}
-	}
-	}
-
-/* fillin last bytecount */
-
-	if (p>begp)
-		*cfoll = (p - begp);
-	else
-		clead--;
-
-	return((int) (clead-bufto));	/*how many stored as encoded */
+    return rc;
 }
+
+
+
+static void
+downloadColormap(char         const rgb[CLUTCOLORCT],
+                 const char * const windowName) {
+
+    unsigned int i;
+
+    pm_message("Downloading colormap for %s ...", windowName);
+
+    printf("\033^M;%d;%d;%d;%s^",
+           0, MAXCOLORCT, CLUTCOLORCT, windowName);
+
+    for (i = 0; i < CLUTCOLORCT; ++i) {
+        unsigned char const c = rgb[i];
+
+        if (c > 31 && c < 123) {
+            /* printable ASCII */
+            putchar(c);
+        } else {
+            /* non-printable, so encode it */
+            putchar((c >> 6) + 123);
+            putchar((c & 0x3f) + 32);
+        }
+    }
+    fflush(stdout);
+}
+
+
+
+static void
+sendOutPicture(pixel **        const pixels,
+               unsigned int    const rows,
+               unsigned int    const cols,
+               colorhash_table const cht,
+               int             const expand,
+               const char *    const windowName) {
+
+    unsigned int row;
+
+    pm_message("Sending picture data ..." );
+
+    for (row = 0; row < rows; ++row) {
+        unsigned int col;
+        printf("\033^P;%d;%d;%d;%d;%s^",
+               0, row * expand, expand, cols, windowName);
+        for (col = 0; col < cols; ++col) {
+            unsigned char const c =
+                colorIndexAtPosition(col, row, pixels, cht);
+            if (c > 31 && c < 123) {
+                putchar(c);
+            } else {
+                putchar((c >> 6) + 123);
+                putchar((c & 0x3f) + 32);
+            }
+        }
+    }
+    fflush(stdout);
+}
+
+
+
+int
+main(int argc, const char ** const argv) {
+
+    FILE * ifP;
+    int rows, cols;
+    int colorCt;
+    int argn;
+    unsigned int bitsPerPixel;
+    pixval maxval;
+    colorhist_vector chv;
+    char rgb[CLUTCOLORCT];
+    const char * windowName;
+    int display, expand;
+    int winflag;
+    const char* const usage = "[-windowname windowname] [-expand expand] [-display display] [ppmfile]";
+    pixel** pixels;
+    colorhash_table cht;
+
+    pm_proginit(&argc, argv);
+
+    argn = 1;
+    windowName = "untitled";
+    winflag = 0;
+    expand = 1;
+    display = 0;
+
+    while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
+    {
+        if ( pm_keymatch(argv[argn],"-windowname",2) && argn + 1 < argc )
+        {
+            ++argn;
+            windowName = argv[argn];
+            winflag = 1;
+        }
+        else if ( pm_keymatch(argv[argn],"-expand",2) && argn + 1 < argc )
+        {
+            ++argn;
+            if ( sscanf( argv[argn], "%d",&expand ) != 1 )
+                pm_usage( usage );
+        }
+        else if ( pm_keymatch(argv[argn],"-display",2) && argn + 1 < argc )
+        {
+            ++argn;
+            if ( sscanf( argv[argn], "%d",&display ) != 1 )
+                pm_usage( usage );
+        }
+        else
+            pm_usage( usage );
+    }
+
+    if ( argn < argc )
+    {
+        ifP = pm_openr( argv[argn] );
+        if ( ! winflag )
+            windowName = argv[argn];
+        ++argn;
+    }
+    else
+        ifP = stdin;
+
+    if ( argn != argc )
+        pm_usage( usage );
+
+    pixels = ppm_readppm(ifP, &cols, &rows, &maxval);
+
+    pm_close(ifP);
+
+    /* Figure out the colormap. */
+    pm_message("Computing colormap..." );
+    chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORCT, &colorCt);
+    if (!chv)
+        pm_error("Too many colors - try doing a 'pnmquant %u'", MAXCOLORCT);
+    pm_message("%u colors found", colorCt );
+
+    makeIcrColormap(chv, colorCt, maxval, rgb);
+
+    bitsPerPixel = bppFromColorCt(colorCt);
+
+    /* And make a hash table for fast lookup. */
+    cht = ppm_colorhisttocolorhash(chv, colorCt);
+
+    ppm_freecolorhist(chv);
+
+    /************** Create a new window using ICR protocol *********/
+    /* Format is "ESC^W;left;top;width;height;display;windowname"  */
+
+    pm_message("Creating window %s ...", windowName);
+
+    printf("\033^W;%d;%d;%d;%d;%d;%s^",
+           0, 0, cols * expand, rows * expand, display, windowName);
+    fflush(stdout);
+
+    /****************** Download the colormap.  ********************/
+
+    downloadColormap(rgb, windowName);
+
+    sendOutPicture(pixels, rows, cols, cht, expand, windowName);
+
+    return 0;
+}
+
+
+
diff --git a/converter/ppm/ppmtoilbm.c b/converter/ppm/ppmtoilbm.c
index d296f498..595aa3f4 100644
--- a/converter/ppm/ppmtoilbm.c
+++ b/converter/ppm/ppmtoilbm.c
@@ -38,8 +38,11 @@
 **  - added IFF text chunks
 **
 **  Feb 2010: afu
-**  Added dimension check to prevent short int from overflowing.
-**  
+**  - added dimension check to prevent short int from overflowing.
+**
+**  June 2015: afu
+**  - moved byterun1 (or Packbits) compression to lib/util/runlenth.c
+**  - fixed bug with HAM -nocompress
 **
 **  TODO:
 **  - multipalette capability (PCHG chunk) for std and HAM
@@ -64,6 +67,7 @@
 ** implied warranty.
 */
 
+#include <assert.h>
 #include <string.h>
 
 #include "pm_c_util.h"
@@ -71,6 +75,7 @@
 #include "ppm.h"
 #include "ppmfloyd.h"
 #include "pbm.h"
+#include "runlength.h"
 #include "ilbm.h"
 #include "lum.h"
 
@@ -106,31 +111,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 +163,394 @@ 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 ************/
+
+
+
+static void
+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 */
+}
+
 
-#define NEWDEPTH(pix, table) PPM_ASSIGN((pix), (table)[PPM_GETR(pix)], (table)[PPM_GETG(pix)], (table)[PPM_GETB(pix)])
 
+/************ compression ************/
 
 static void
-report_too_many_colors(int         const ifmode,
-                       int         const maxplanes,
-                       int         const hamplanes,
-                       DirectColor const dcol,
-                       int         const deepbits) {
+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 unsigned int
+compressRow(unsigned int const bytes) {
+
+    size_t compressedByteCt;
+
+    switch (compmethod) {
+        case cmpByteRun1:
+            pm_rlenc_compressbyte(
+                coded_rowbuf, compr_rowbuf, PM_RLE_PACKBITS, bytes,
+                &compressedByteCt);
+            break;
+        default:
+            pm_error("compressRow(): unknown compression method %d", 
+                     compmethod);
+    }
+    storeBodyrow(compr_rowbuf, compressedByteCt);
+
+    assert((unsigned)compressedByteCt == compressedByteCt);
+
+    return (unsigned)compressedByteCt;
+}
+
+
+
+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 +586,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 +606,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 +622,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 +648,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 +671,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 +689,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 +712,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 +765,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 +845,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, stdout, 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 +896,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 +908,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 +1021,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 +1039,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 +1175,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, stdout, 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 +1228,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 +1247,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 +1267,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 +1348,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 +1380,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 +1479,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 +1509,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 +1525,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 +1648,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 +1688,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 +1699,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 +1739,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 +1795,7 @@ ppm_to_rgbn(ifP, cols, rows, maxval)
                 }
             }
         }
-        store_bodyrow(compr_row, compr_len);
+        storeBodyrow(compr_row, compr_len);
         bodysize += compr_len;
     }
 
@@ -1379,40 +1806,43 @@ 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
-    select upto <maxcolors> colors
+    select up to <maxcolors> colors
     build colormap from selected colors
     map slice to colormap
     write slice
     while( !finished ) {
         read next slice
-        compute distances for each pixel and select upto
+        compute distances for each pixel and select up to
             <maxchangesperslice> unused colors in this slice
         modify selected colors to the ones with maximum(?) distance
         map slice to colormap
@@ -1431,432 +1861,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 +1906,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 +1914,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 +1927,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:
@@ -1985,7 +1989,8 @@ main(int argc, char ** argv) {
             if( ++argn >= argc )
                 pm_error("-camg requires a value");
             value = strtol(argv[argn], &tail, 16);
-            /* TODO: should do some error checking here */
+            if(argv[argn] == tail)
+                pm_error("-camg requires a value");
             viewportmodes |= value;
             gen_camg = 1;
         }
@@ -2003,14 +2008,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 +2031,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 +2073,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 +2083,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 +2122,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 +2151,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 +2210,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 +2239,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 +2255,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 );
                 }
             }
@@ -2294,37 +2299,40 @@ main(int argc, char ** argv) {
         for (i = 0; i < RowBytes(cols); ++i)
             coded_rowbuf[i] = 0;
         if (DO_COMPRESS)
-            MALLOCARRAY_NOFAIL(compr_rowbuf, WORSTCOMPR(RowBytes(cols)));
+            pm_rlenc_allocoutbuf(&compr_rowbuf, RowBytes(cols), PM_RLE_PACKBITS);
     }
     
     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/BUGS b/converter/ppm/ppmtompeg/BUGS
index 64269dfb..9724014e 100644
--- a/converter/ppm/ppmtompeg/BUGS
+++ b/converter/ppm/ppmtompeg/BUGS
@@ -14,7 +14,7 @@ Known BUGS:
      REFERENCE_FRAME	DECODED
    does not work
 
-5. Cannot use both STDIN and CDL_FILEs (ok, since it doesnt make sense...)
+5. Cannot use both STDIN and CDL_FILEs (ok, since it doesn't make sense...)
 
 6. <fixed>
 
diff --git a/converter/ppm/ppmtompeg/CHANGES b/converter/ppm/ppmtompeg/CHANGES
index fffa7a65..efb8fdcf 100644
--- a/converter/ppm/ppmtompeg/CHANGES
+++ b/converter/ppm/ppmtompeg/CHANGES
@@ -28,7 +28,7 @@ Changes chronology
 	- non-integer frame rates now work for all machines
 	- fixed parsing of -mv_histogram
 	- fixed numPadding bug (file name problem)
-	- fixed full pixel assertation bug
+	- fixed full pixel assertion bug
         - corrected ASPECT_RATIO bug (was forced to 1)
 	- buffer size is now set correctly
         - complains when file is too small
diff --git a/converter/ppm/ppmtompeg/Makefile b/converter/ppm/ppmtompeg/Makefile
index a1004fdd..eeab9727 100644
--- a/converter/ppm/ppmtompeg/Makefile
+++ b/converter/ppm/ppmtompeg/Makefile
@@ -31,14 +31,17 @@ endif
 #	1) long's are 32 bits and
 #	2) int's are not
 #
-# if you are using a non-ANSI compiler, then use:
-#	-DNON_ANSI_COMPILER
-#
 # one other option:
 #	-DHEINOUS_DEBUG_MODE
 #
 
-MP_BASE_OBJS = mfwddct.o postdct.o huff.o bitio.o mheaders.o
+MP_BASE_OBJS = \
+  mfwddct.o \
+  postdct.o \
+  huff.o \
+  bitio.o \
+  mheaders.o \
+
 MP_ENCODE_OBJS = \
   frames.o \
   iframe.o \
@@ -46,12 +49,25 @@ MP_ENCODE_OBJS = \
   bframe.o \
   psearch.o \
   bsearch.o \
-  block.o 
-
-MP_OTHER_OBJS = mpeg.o subsample.o param.o rgbtoycc.o \
-	readframe.o combine.o jrevdct.o frame.o fsize.o frametype.o \
-	specifics.o rate.o opts.o input.o
-ifeq ($(OMIT_NETWORK),y)
+  block.o \
+
+MP_OTHER_OBJS = \
+  mpeg.o \
+  subsample.o \
+  param.o \
+  rgbtoycc.o \
+  readframe.o \
+  combine.o \
+  jrevdct.o \
+  frame.o \
+  fsize.o \
+  frametype.o \
+  specifics.o \
+  rate.o \
+  opts.o \
+  input.o \
+
+ifeq ($(OMIT_NETWORK),Y)
   MP_OTHER_OBJS += noparallel.o
 else
   MP_OTHER_OBJS += parallel.o psocket.o
@@ -62,14 +78,19 @@ else
   MP_OTHER_OBJS += gethostname.o
 endif
 
-NONMAIN_OBJS = $(MP_BASE_OBJS) $(MP_OTHER_OBJS) $(MP_ENCODE_OBJS) \
-	      	$(JPEG_MODULE).o
-OBJECTS = ppmtompeg.o $(NONMAIN_OBJS)
-MERGE_OBJECTS = ppmtompeg.o2 $(NONMAIN_OBJS)
+ADDL_OBJECTS = \
+  $(MP_BASE_OBJS) \
+  $(MP_OTHER_OBJS) \
+  $(MP_ENCODE_OBJS) \
+  $(JPEG_MODULE).o \
+
+OBJECTS = ppmtompeg.o $(ADDL_OBJECTS)
+MERGE_OBJECTS = ppmtompeg.o2 $(ADDL_OBJECTS)
 MP_INCLUDE = mproto.h mtypes.h huff.h bitio.h
 MP_MISC = Makefile huff.table parse_huff.pl
 
-BINARIES = ppmtompeg
+PORTBINARIES = ppmtompeg
+BINARIES = $(PORTBINARIES)
 MERGEBINARIES = $(BINARIES)
 SCRIPTS = 
 
@@ -84,18 +105,14 @@ else
   LIBOPTR =
 endif
 
-ppmtompeg: $(OBJECTS) $(NETPBMLIB) $(LIBOPT)
-	$(LD) -o $@ \
-          $(OBJECTS) $(shell $(LIBOPT) $(NETPBMLIB) $(LIBOPTR) $(JPEGLIBX)) \
-	  $(NETWORKLD) $(MATHLIB) $(LDFLAGS) $(LDLIBS) \
-	  $(RPATH) $(LADD)
-
-profile: $(OBJECTS) $(NETPBMLIB) $(LIBOPT)
-	$(LD) -o $@ -Bstatic -pg \
-          $(OBJECTS) $(shell $(LIBOPT) $(NETPBMLIB) $(LIBOPTR) $(JPEGLIBX)) \
-	  $(NETWORKLD) $(MATHLIB) $(LDFLAGS) $(LDLIBS) \
-	  $(RPATH) $(LADD)
+ppmtompeg: $(ADDL_OBJECTS) $(LIBOPT)
+ppmtompeg: LDFLAGS_TARGET = \
+  $(shell $(LIBOPT) $(LIBOPTR) $(JPEGLIBX)) $(NETWORKLD)
 
+profile: $(ADDL_OBJECTS) $(LIBOPT)
+profile: LDFLAGS_TARGET = \
+  -Bstatic -pg \
+  $(shell $(LIBOPT) $(LIBOPTR) $(JPEGLIBX)) $(NETWORKLD)
 
 #########
 # OTHER #
diff --git a/converter/ppm/ppmtompeg/bframe.c b/converter/ppm/ppmtompeg/bframe.c
index 1dbc1846..f5009d6c 100644
--- a/converter/ppm/ppmtompeg/bframe.c
+++ b/converter/ppm/ppmtompeg/bframe.c
@@ -523,7 +523,7 @@ makeNonSkipBlock(int              const y,
                  MpegFrame *      const curr, 
                  MpegFrame *      const prev, 
                  MpegFrame *      const next,
-                 boolean          const specificsOn,
+                 bool             const specificsOn,
                  int              const mbAddress,
                  int              const QScale,
                  const LumBlock * const currentBlockP,
diff --git a/converter/ppm/ppmtompeg/bitio.c b/converter/ppm/ppmtompeg/bitio.c
index e0dc4d4e..3812bc39 100644
--- a/converter/ppm/ppmtompeg/bitio.c
+++ b/converter/ppm/ppmtompeg/bitio.c
@@ -244,8 +244,8 @@ Bitio_Write(BitBucket * const bbPtr,
     assert(nbits <= 32 && nbits >= 0);
 
     /*
-     * Clear top bits if not part of data, necessary due to down and
-     * dirty calls of Bitio_Write with unecessary top bits set.
+     * Clear top bits if not part of data, necessary because of down and
+     * dirty calls of Bitio_Write with unnecessary top bits set.
      */
 
     bits &= lower_mask[nbits];
diff --git a/converter/ppm/ppmtompeg/bsearch.c b/converter/ppm/ppmtompeg/bsearch.c
index 70edfef6..c618bbd4 100644
--- a/converter/ppm/ppmtompeg/bsearch.c
+++ b/converter/ppm/ppmtompeg/bsearch.c
@@ -43,7 +43,7 @@
  * Changed copyrights
  *
  * Revision 1.6  1994/12/07  00:40:36  smoot
- * Added seperate P and B search ranges
+ * Added separate P and B search ranges
  *
  * Revision 1.5  1994/03/15  00:27:11  keving
  * nothing
@@ -834,7 +834,6 @@ BMotionSearchCross2(const LumBlock * const currentBlockP,
     interpErrF = FindBestMatch(&forwardBlock, currentBlockP,
                                next, by, bx, &newMotion.bwd,
                                bestErr, searchRangeB);
-    bestErr = min(bestErr, interpErr);
     interpErrB = FindBestMatch(&backBlock, currentBlockP,
                                prev, by, bx, &newMotion.fwd,
                                bestErr, searchRangeB);
diff --git a/converter/ppm/ppmtompeg/combine.c b/converter/ppm/ppmtompeg/combine.c
index 8e0d3281..c00f9c71 100644
--- a/converter/ppm/ppmtompeg/combine.c
+++ b/converter/ppm/ppmtompeg/combine.c
@@ -104,7 +104,7 @@ appendSpecifiedGopFiles(struct inputSource * const inputSourceP,
         FILE * ifP;
 
         GetNthInputFileName(inputSourceP, fileSeq, &inputFileName);
-        asprintfN(&fileName, "%s/%s", currentGOPPath, inputFileName);
+        pm_asprintf(&fileName, "%s/%s", currentGOPPath, inputFileName);
 
         for (nAttempts = 0, ifP = NULL;
              nAttempts < READ_ATTEMPTS && !ifP;
@@ -122,8 +122,8 @@ appendSpecifiedGopFiles(struct inputSource * const inputSourceP,
         } else
             pm_error("Unable to read file '%s' after %u attempts.",
                      fileName, READ_ATTEMPTS);
-        strfree(fileName);
-        strfree(inputFileName);
+        pm_strfree(fileName);
+        pm_strfree(inputFileName);
     }
 } 
 
@@ -140,7 +140,7 @@ appendDefaultGopFiles(const char * const outputFileName,
         const char * fileName;
         FILE * ifP;
 
-        asprintfN(&fileName, "%s.gop.%u", outputFileName, fileSeq);
+        pm_asprintf(&fileName, "%s.gop.%u", outputFileName, fileSeq);
         
         ifP = fopen(fileName, "rb");
         if (ifP == NULL)
@@ -151,7 +151,7 @@ appendDefaultGopFiles(const char * const outputFileName,
             
             AppendFile(ofP, ifP);
         }
-        strfree(fileName);
+        pm_strfree(fileName);
     }
 }
 
diff --git a/converter/ppm/ppmtompeg/docs/template.param b/converter/ppm/ppmtompeg/docs/template.param
index 66b6dd98..78ad5300 100644
--- a/converter/ppm/ppmtompeg/docs/template.param
+++ b/converter/ppm/ppmtompeg/docs/template.param
@@ -18,7 +18,7 @@
 # files in the order in which they must appear, followed by 'END_INPUT'
 #
 # Also, if you use the `command` method of generating input file names,
-# the command will only be executed in the INPUT_DIR if INPUT_DIR preceeds
+# the command will only be executed in the INPUT_DIR if INPUT_DIR precedes
 # the INPUT parameter.
 #
 # <option> MUST be in UPPER CASE
diff --git a/converter/ppm/ppmtompeg/examples/template.param b/converter/ppm/ppmtompeg/examples/template.param
index 66b6dd98..78ad5300 100644
--- a/converter/ppm/ppmtompeg/examples/template.param
+++ b/converter/ppm/ppmtompeg/examples/template.param
@@ -18,7 +18,7 @@
 # files in the order in which they must appear, followed by 'END_INPUT'
 #
 # Also, if you use the `command` method of generating input file names,
-# the command will only be executed in the INPUT_DIR if INPUT_DIR preceeds
+# the command will only be executed in the INPUT_DIR if INPUT_DIR precedes
 # the INPUT parameter.
 #
 # <option> MUST be in UPPER CASE
diff --git a/converter/ppm/ppmtompeg/frame.c b/converter/ppm/ppmtompeg/frame.c
index 09f46f66..75b209f8 100644
--- a/converter/ppm/ppmtompeg/frame.c
+++ b/converter/ppm/ppmtompeg/frame.c
@@ -753,7 +753,7 @@ Frame_AllocHalf(MpegFrame * const frameP) {
  *===========================================================================*/
 void
 Frame_AllocDecoded(MpegFrame * const frameP,
-                   boolean     const makeReference) {
+                   bool        const makeReference) {
 
     if (frameP->decoded_y != NULL) {
         /* already allocated */
diff --git a/converter/ppm/ppmtompeg/gethostname.c b/converter/ppm/ppmtompeg/gethostname.c
index 014b42e8..d20af17c 100644
--- a/converter/ppm/ppmtompeg/gethostname.c
+++ b/converter/ppm/ppmtompeg/gethostname.c
@@ -1,3 +1,4 @@
+#define _XOPEN_SOURCE 500  /* Make sure strdup() is in string.h */
 #define _BSD_SOURCE   /* Make sure strdup() is in string.h */
 
 #include <string.h>
diff --git a/converter/ppm/ppmtompeg/gethostname_win32.c b/converter/ppm/ppmtompeg/gethostname_win32.c
index 383f4e55..e37fbb37 100644
--- a/converter/ppm/ppmtompeg/gethostname_win32.c
+++ b/converter/ppm/ppmtompeg/gethostname_win32.c
@@ -94,7 +94,7 @@ get_string_version(push_string_t *str)
             return FALSE;
     }
 
-    /* Call GetNativeSystemInfo if supported or GetSystemInfo otherwise. */
+    /* Call GetNativeSystemInfo if available; GetSystemInfo otherwise. */
     pGNSI = (PGNSI)
             GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), 
             "GetNativeSystemInfo");
diff --git a/converter/ppm/ppmtompeg/headers/all.h b/converter/ppm/ppmtompeg/headers/all.h
index e350aab8..8f095d8e 100644
--- a/converter/ppm/ppmtompeg/headers/all.h
+++ b/converter/ppm/ppmtompeg/headers/all.h
@@ -33,7 +33,7 @@
  * added little_endian force for irizx
  *
  * Revision 1.8  1995/02/02  22:02:18  smoot
- * added ifdefs for compatability on stranger and stranger architectures...
+ * added ifdefs for compatibility on stranger and stranger architectures...
  *
  * Revision 1.7  1995/02/02  07:26:45  eyhung
  * added parens to all.h to remove compiler warning
@@ -80,7 +80,6 @@
 #include <time.h>
 #endif
 
-#include "ansi.h"
 #include "general.h"
 
 /* some machines have #define index strchr; get rid of this nonsense */
diff --git a/converter/ppm/ppmtompeg/headers/ansi.h b/converter/ppm/ppmtompeg/headers/ansi.h
deleted file mode 100644
index b3c3ab17..00000000
--- a/converter/ppm/ppmtompeg/headers/ansi.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*===========================================================================*
- * ansi.h								     *
- *									     *
- *	macro for non-ansi compilers					     *
- *									     *
- *===========================================================================*/
-
-/*
- * Copyright (c) 1995 The Regents of the University of California.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose, without fee, and without written agreement is
- * hereby granted, provided that the above copyright notice and the following
- * two paragraphs appear in all copies of this software.
- *
- * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
- * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- */
-
-/*  
- *  $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/headers/RCS/ansi.h,v 1.6 1995/08/15 23:43:13 smoot Exp $
- *  $Log: ansi.h,v $
- *  Revision 1.6  1995/08/15 23:43:13  smoot
- *  *** empty log message ***
- *
- *  Revision 1.5  1995/01/19 23:54:35  eyhung
- *  Changed copyrights
- *
- * Revision 1.4  1994/11/12  02:12:13  keving
- * nothing
- *
- * Revision 1.3  1993/07/22  22:24:23  keving
- * nothing
- *
- * Revision 1.2  1993/07/09  00:17:23  keving
- * nothing
- *
- * Revision 1.1  1993/06/14  22:50:22  keving
- * nothing
- *
- */
-
-
-#ifndef ANSI_INCLUDED
-#define ANSI_INCLUDED
-
-
-/*  
- *  _ANSI_ARGS_ macro stolen from Tcl6.5 by John Ousterhout
- */
-#undef _ANSI_ARGS_
-#undef const
-#ifdef NON_ANSI_COMPILER
-#define _ANSI_ARGS_(x)       ()
-#define CONST
-#else
-#define _ANSI_ARGS_(x)   x
-#define CONST const
-#ifdef __cplusplus
-#define VARARGS (...)
-#else
-#define VARARGS ()
-#endif
-#endif
-
-
-#endif /* ANSI_INCLUDED */
diff --git a/converter/ppm/ppmtompeg/headers/bitio.h b/converter/ppm/ppmtompeg/headers/bitio.h
index a24c21cd..931bcdd9 100644
--- a/converter/ppm/ppmtompeg/headers/bitio.h
+++ b/converter/ppm/ppmtompeg/headers/bitio.h
@@ -63,7 +63,6 @@
 #include <stdio.h>
 
 #include "general.h"
-#include "ansi.h"
 
 
 /*===========*
diff --git a/converter/ppm/ppmtompeg/headers/dct.h b/converter/ppm/ppmtompeg/headers/dct.h
index e024b6c1..3b824cf0 100644
--- a/converter/ppm/ppmtompeg/headers/dct.h
+++ b/converter/ppm/ppmtompeg/headers/dct.h
@@ -31,7 +31,6 @@
 #define DCT_INCLUDED
 
 
-#include "ansi.h"
 
 
 
@@ -47,11 +46,12 @@ typedef DCTELEM DCTBLOCK_2D[DCTSIZE][DCTSIZE];
 /*  
  *  from mfwddct.c:
  */
-extern void mp_fwd_dct_block2 _ANSI_ARGS_((DCTBLOCK_2D src, DCTBLOCK_2D dest));
+void init_fdct (void);
+extern void mp_fwd_dct_block2 (DCTBLOCK_2D src, DCTBLOCK_2D dest);
 
 /* jrevdct.c */
-extern void init_pre_idct _ANSI_ARGS_((void ));
-extern void mpeg_jrevdct _ANSI_ARGS_((DCTBLOCK data ));
+extern void init_pre_idct (void );
+extern void mpeg_jrevdct (DCTBLOCK data );
 
 
 /* We assume that right shift corresponds to signed division by 2 with
diff --git a/converter/ppm/ppmtompeg/headers/frame.h b/converter/ppm/ppmtompeg/headers/frame.h
index acd74419..e1f587a2 100644
--- a/converter/ppm/ppmtompeg/headers/frame.h
+++ b/converter/ppm/ppmtompeg/headers/frame.h
@@ -34,8 +34,7 @@
  * HEADER FILES *
  *==============*/
 
-#include "general.h"
-#include "ansi.h"
+#include "netpbm/pm_c_util.h"
 #include "mtypes.h"
 
 /*===========*
@@ -54,8 +53,10 @@ typedef struct mpegFrame {
     int type;
     char    inputFileName[256];
     int id;           /* the frame number -- starts at 0 */
-    boolean inUse;	/* TRUE iff this frame is currently being used */
-			/* FALSE means any data here can be thrashed */
+    bool inUse;
+	   /* this frame is currently being used (if not, any data here can be
+          thrashed)
+       */
 
     /*  
      *  now, the YCrCb data.  All pixel information is stored in unsigned
@@ -64,17 +65,17 @@ typedef struct mpegFrame {
      *
      *  if orig_y is NULL, then orig_cr, orig_cb are undefined
      */
-    uint8 **orig_y, **orig_cr, **orig_cb;
+    uint8_t **orig_y, **orig_cr, **orig_cb;
 
     /* now, the decoded data -- relevant only if
      *	    referenceFrame == DECODED_FRAME
      *
      * if decoded_y is NULL, then decoded_cr, decoded_cb are undefined 
      */
-    uint8 **decoded_y, **decoded_cr, **decoded_cb;
+    uint8_t **decoded_y, **decoded_cr, **decoded_cb;
 
     /* reference data */
-    uint8 **ref_y, **ref_cr, **ref_cb;
+    uint8_t **ref_y, **ref_cr, **ref_cb;
 
     /*  
      *  these are the Blocks which will ultimately compose MacroBlocks.
@@ -86,9 +87,9 @@ typedef struct mpegFrame {
     /*
      *  this is the half-pixel luminance data (for reference frames)
      */
-    uint8 **halfX, **halfY, **halfBoth;
+    uint8_t **halfX, **halfY, **halfBoth;
 
-    boolean   halfComputed;        /* TRUE iff half-pixels already computed */
+    bool   halfComputed;        /* TRUE iff half-pixels already computed */
 
     struct mpegFrame *next;  /* points to the next B-frame to be encoded, if
 		       * stdin is used as the input. 
@@ -120,7 +121,7 @@ Frame_AllocHalf(MpegFrame * const frameP);
 
 void
 Frame_AllocDecoded(MpegFrame * const frameP,
-                   boolean     const makeReference);
+                   bool        const makeReference);
 
 void
 Frame_Resize(MpegFrame * const omf,
diff --git a/converter/ppm/ppmtompeg/headers/frames.h b/converter/ppm/ppmtompeg/headers/frames.h
index f2bcf6ae..2ec11d69 100644
--- a/converter/ppm/ppmtompeg/headers/frames.h
+++ b/converter/ppm/ppmtompeg/headers/frames.h
@@ -13,7 +13,6 @@
  *==============*/
 
 #include "pm_config.h"  /* For __inline__ */
-#include "ansi.h"
 #include "mtypes.h"
 #include "mheaders.h"
 #include "iframe.h"
@@ -255,7 +254,6 @@ extern int gopSize;
 extern int slicesPerFrame;
 extern int blocksPerSlice;
 extern int referenceFrame;
-extern boolean specificsOn;
 extern int quietTime;       /* shut up for at least quietTime seconds;
                  * negative means shut up forever
                  */
diff --git a/converter/ppm/ppmtompeg/headers/frametype.h b/converter/ppm/ppmtompeg/headers/frametype.h
index 63bee964..33b604e6 100644
--- a/converter/ppm/ppmtompeg/headers/frametype.h
+++ b/converter/ppm/ppmtompeg/headers/frametype.h
@@ -7,7 +7,7 @@ FType_Type(unsigned int const frameNum);
 unsigned int
 FType_FutureRef(unsigned int const currFrameNum);
 
-int	FType_PastRef _ANSI_ARGS_((int currFrameNum));
+int	FType_PastRef (int currFrameNum);
 
 void SetFramePattern(const char * const pattern);
 
diff --git a/converter/ppm/ppmtompeg/headers/general.h b/converter/ppm/ppmtompeg/headers/general.h
index f29c9445..59c33c73 100644
--- a/converter/ppm/ppmtompeg/headers/general.h
+++ b/converter/ppm/ppmtompeg/headers/general.h
@@ -111,15 +111,7 @@ int pclose();
 #define NEWLINE '\n'
 
 
-/*==================*
- * TYPE DEFINITIONS *
- *==================*/
-
-#ifndef HAVE_BOOLEAN
 typedef int boolean;
-#define HAVE_BOOLEAN
-/* JPEG library also defines boolean */
-#endif
 
 /* In the following, we need the "signed" in order to make these typedefs
    match those in AIX system header files.  Otherwise, compile fails on 
@@ -167,8 +159,6 @@ typedef signed int int32;
 #define max(a,b) ((a) > (b) ? (a) : (b))
 #undef min
 #define min(a,b) ((a) < (b) ? (a) : (b))
-#undef abs
-#define abs(a) ((a) >= 0 ? (a) : -(a))
 
 
 #endif
diff --git a/converter/ppm/ppmtompeg/headers/huff.h b/converter/ppm/ppmtompeg/headers/huff.h
index 47ffb843..a6379248 100644
--- a/converter/ppm/ppmtompeg/headers/huff.h
+++ b/converter/ppm/ppmtompeg/headers/huff.h
@@ -24,8 +24,11 @@
  */
 
 /*  
- *  THIS FILE IS MACHINE GENERATED!  DO NOT EDIT!
+ *  THIS FILE WAS ORIGINALLY MACHINE GENERATED
  */
+
+#include "general.h"
+
 #define HUFF_MAXRUN	32
 #define HUFF_MAXLEVEL	41
 
diff --git a/converter/ppm/ppmtompeg/headers/jpeg.h b/converter/ppm/ppmtompeg/headers/jpeg.h
index 62c6f930..76d73d9e 100644
--- a/converter/ppm/ppmtompeg/headers/jpeg.h
+++ b/converter/ppm/ppmtompeg/headers/jpeg.h
@@ -1,5 +1,5 @@
-#include "ansi.h"
-
+#include <stdio.h>
+#include "frame.h"
 
 void
 JMovie2JPEG(const char * const infilename,
diff --git a/converter/ppm/ppmtompeg/headers/mheaders.h b/converter/ppm/ppmtompeg/headers/mheaders.h
index 21d43e3d..edd9552d 100644
--- a/converter/ppm/ppmtompeg/headers/mheaders.h
+++ b/converter/ppm/ppmtompeg/headers/mheaders.h
@@ -54,7 +54,6 @@
  *==============*/
 
 #include "general.h"
-#include "ansi.h"
 #include "bitio.h"
 
 
@@ -62,7 +61,7 @@
  * EXTERNAL PROCEDURE prototypes *
  *===============================*/
 
-void	SetGOPStartTime _ANSI_ARGS_((int index));
+void	SetGOPStartTime (int index);
 
 void
 Mhead_GenSequenceHeader(BitBucket *   const bbPtr, 
@@ -80,21 +79,21 @@ Mhead_GenSequenceHeader(BitBucket *   const bbPtr,
                         uint8 *       const user_data,
                         int32         const user_data_size);
 
-void	Mhead_GenSequenceEnder _ANSI_ARGS_((BitBucket *bbPtr));
-void	Mhead_GenGOPHeader _ANSI_ARGS_((BitBucket *bbPtr,
+void	Mhead_GenSequenceEnder (BitBucket *bbPtr);
+void	Mhead_GenGOPHeader (BitBucket *bbPtr,
 	   int32 drop_frame_flag,
            int32 tc_hrs, int32 tc_min,
            int32 tc_sec, int32 tc_pict,
            int32 closed_gop, int32 broken_link,
            uint8 *ext_data, int32 ext_data_size,
-           uint8 *user_data, int32 user_data_size));
-void	Mhead_GenPictureHeader _ANSI_ARGS_((BitBucket *bbPtr, int frameType,
-					    int pictCount, int f_code));
-void	Mhead_GenSliceHeader _ANSI_ARGS_((BitBucket *bbPtr, uint32 slicenum,
+           uint8 *user_data, int32 user_data_size);
+void	Mhead_GenPictureHeader (BitBucket *bbPtr, int frameType,
+					    int pictCount, int f_code);
+void	Mhead_GenSliceHeader (BitBucket *bbPtr, uint32 slicenum,
 					  uint32 qscale, uint8 *extra_info,
-					  uint32 extra_info_size));
-void	Mhead_GenSliceEnder _ANSI_ARGS_((BitBucket *bbPtr));
-void	Mhead_GenMBHeader _ANSI_ARGS_((BitBucket *bbPtr,
+					  uint32 extra_info_size);
+void	Mhead_GenSliceEnder (BitBucket *bbPtr);
+void	Mhead_GenMBHeader (BitBucket *bbPtr,
 	  uint32 pict_code_type, uint32 addr_incr,
           uint32 q_scale,
           uint32 forw_f_code, uint32 back_f_code,
@@ -103,7 +102,7 @@ void	Mhead_GenMBHeader _ANSI_ARGS_((BitBucket *bbPtr,
           int32 motion_forw, int32 m_horiz_forw,
           int32 m_vert_forw, int32 motion_back,
           int32 m_horiz_back, int32 m_vert_back,
-          uint32 mb_pattern, uint32 mb_intra));
+          uint32 mb_pattern, uint32 mb_intra);
 
 
 #endif /* MHEADERS_INCLUDED */
diff --git a/converter/ppm/ppmtompeg/headers/motion_search.h b/converter/ppm/ppmtompeg/headers/motion_search.h
index 62f3abab..d00509c4 100644
--- a/converter/ppm/ppmtompeg/headers/motion_search.h
+++ b/converter/ppm/ppmtompeg/headers/motion_search.h
@@ -9,7 +9,6 @@
  * HEADER FILES *
  *==============*/
 
-#include "ansi.h"
 
 
 /*===========*
@@ -140,7 +139,7 @@ extern int psearchAlg;
  *  Changed copyrights
  *
  * Revision 1.4  1994/12/07  00:42:01  smoot
- * Added seperate P and B search ranges
+ * Added separate P and B search ranges
  *
  * Revision 1.3  1994/11/12  02:12:58  keving
  * nothing
diff --git a/converter/ppm/ppmtompeg/headers/mpeg.h b/converter/ppm/ppmtompeg/headers/mpeg.h
index 56862c42..fbfaaf2c 100644
--- a/converter/ppm/ppmtompeg/headers/mpeg.h
+++ b/converter/ppm/ppmtompeg/headers/mpeg.h
@@ -34,7 +34,6 @@
 
 #include "pm_c_util.h"
 #include "ppm.h"
-#include "ansi.h"
 #include "mtypes.h"
 #include "frame.h"
 
@@ -80,7 +79,7 @@ ComputeGOPFrames(int            const whichGOP,
                  unsigned int * const lastFrameP, 
                  unsigned int   const numFrames);
 
-extern void	IncrementTCTime _ANSI_ARGS_((void));
+extern void	IncrementTCTime (void);
 void SetReferenceFrameType(const char * const type);
 
 boolean
@@ -93,7 +92,7 @@ ReadDecodedRefFrame(MpegFrame *  const frameP,
 void
 SetBitRateFileName(const char * const fileName);
 
-extern void	SetFrameRate _ANSI_ARGS_((void));
+extern void	SetFrameRate (void);
 
 
 /*==================*
diff --git a/converter/ppm/ppmtompeg/headers/mproto.h b/converter/ppm/ppmtompeg/headers/mproto.h
index d8fefd84..5b003b2e 100644
--- a/converter/ppm/ppmtompeg/headers/mproto.h
+++ b/converter/ppm/ppmtompeg/headers/mproto.h
@@ -70,7 +70,6 @@
  *==============*/
 
 #include "general.h"
-#include "ansi.h"
 #include "bitio.h"
 
 
@@ -86,39 +85,39 @@ typedef DCTELEM DCTBLOCK[DCTSIZE2];
 /*  
  *  from mbasic.c:
  */
-void mp_reset _ANSI_ARGS_((void));
-void mp_free _ANSI_ARGS_((MpegFrame *mf));
-MpegFrame *mp_new _ANSI_ARGS_((int fnumber, char type, MpegFrame *oldFrame));
-void mp_ycc_calc _ANSI_ARGS_((MpegFrame *mf));
-void mp_dct_blocks _ANSI_ARGS_((MpegFrame *mf));
-void	AllocDecoded _ANSI_ARGS_((MpegFrame *frame));
+void mp_reset (void);
+void mp_free (MpegFrame *mf);
+MpegFrame *mp_new (int fnumber, char type, MpegFrame *oldFrame);
+void mp_ycc_calc (MpegFrame *mf);
+void mp_dct_blocks (MpegFrame *mf);
+void	AllocDecoded (MpegFrame *frame);
 
 /*  
  *  from moutput.c:
  */
-boolean mp_quant_zig_block _ANSI_ARGS_((Block in, FlatBlock out, int qscale, int iblock));
-void	UnQuantZig _ANSI_ARGS_((FlatBlock in, Block out, int qscale, boolean iblock));
-void mp_rle_huff_block _ANSI_ARGS_((FlatBlock in, BitBucket *out));
-void mp_rle_huff_pblock _ANSI_ARGS_((FlatBlock in, BitBucket *out));
-void mp_create_blocks _ANSI_ARGS_((MpegFrame *mf));
+boolean mp_quant_zig_block (Block in, FlatBlock out, int qscale, int iblock);
+void	UnQuantZig (FlatBlock in, Block out, int qscale, boolean iblock);
+void mp_rle_huff_block (FlatBlock in, BitBucket *out);
+void mp_rle_huff_pblock (FlatBlock in, BitBucket *out);
+void mp_create_blocks (MpegFrame *mf);
 
 
 
 
-void	ReadEYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer, int width,
-			    int height));
-boolean	ReadPPM _ANSI_ARGS_((MpegFrame *mf, FILE *fpointer));
-void PPMtoYCC _ANSI_ARGS_((MpegFrame * mf));
+void	ReadEYUV (MpegFrame * mf, FILE *fpointer, int width,
+			    int height);
+boolean	ReadPPM (MpegFrame *mf, FILE *fpointer);
+void PPMtoYCC (MpegFrame * mf);
 
-void	ComputeHalfPixelData _ANSI_ARGS_((MpegFrame *frame));
-void mp_validate_size _ANSI_ARGS_((int *x, int *y));
-void AllocYCC _ANSI_ARGS_((MpegFrame * mf));
+void	ComputeHalfPixelData (MpegFrame *frame);
+void mp_validate_size (int *x, int *y);
+void AllocYCC (MpegFrame * mf);
 
 
 /* jrevdct.c */
-void init_pre_idct _ANSI_ARGS_((void ));
-void j_rev_dct_sparse _ANSI_ARGS_((DCTBLOCK data , int pos ));
-void j_rev_dct _ANSI_ARGS_((DCTBLOCK data ));
-void j_rev_dct_sparse _ANSI_ARGS_((DCTBLOCK data , int pos ));
-void j_rev_dct _ANSI_ARGS_((DCTBLOCK data ));
+void init_pre_idct (void );
+void j_rev_dct_sparse (DCTBLOCK data , int pos );
+void j_rev_dct (DCTBLOCK data );
+void j_rev_dct_sparse (DCTBLOCK data , int pos );
+void j_rev_dct (DCTBLOCK data );
 
diff --git a/converter/ppm/ppmtompeg/headers/mtypes.h b/converter/ppm/ppmtompeg/headers/mtypes.h
index 0db5a330..a44ce680 100644
--- a/converter/ppm/ppmtompeg/headers/mtypes.h
+++ b/converter/ppm/ppmtompeg/headers/mtypes.h
@@ -10,12 +10,7 @@
 #ifndef MTYPES_INCLUDED
 #define MTYPES_INCLUDED
 
-
-/*==============*
- * HEADER FILES *
- *==============*/
-
-#include "general.h"
+#include "netpbm/pm_config.h"
 #include "dct.h"
 
 
@@ -48,12 +43,12 @@ typedef struct motion {
 /*  
  *  your basic Block type
  */
-typedef int16 Block[DCTSIZE][DCTSIZE];
-typedef int16 FlatBlock[DCTSIZE_SQ];
+typedef int16_t Block[DCTSIZE][DCTSIZE];
+typedef int16_t FlatBlock[DCTSIZE_SQ];
 typedef	struct {
-    int32 l[2*DCTSIZE][2*DCTSIZE];
+    int32_t l[2*DCTSIZE][2*DCTSIZE];
 } LumBlock;
-typedef	int32 ChromBlock[DCTSIZE][DCTSIZE];
+typedef	int32_t ChromBlock[DCTSIZE][DCTSIZE];
 
 /*========*
  * MACROS *
diff --git a/converter/ppm/ppmtompeg/headers/opts.h b/converter/ppm/ppmtompeg/headers/opts.h
index 5901a677..1756334e 100644
--- a/converter/ppm/ppmtompeg/headers/opts.h
+++ b/converter/ppm/ppmtompeg/headers/opts.h
@@ -38,7 +38,6 @@
  */
 
 #include "general.h"
-#include "ansi.h"
 #include "mtypes.h"
 
 /*
@@ -110,14 +109,14 @@ extern int LaplaceNum, LaplaceCnum;
 extern boolean BSkipBlocks;
 
 /* Procedures Prototypes */
-int	GetIQScale _ANSI_ARGS_((void));
-int	GetPQScale _ANSI_ARGS_((void));
-int	GetBQScale _ANSI_ARGS_((void));
-void	Tune_Init _ANSI_ARGS_((void));
-int     CalcRLEHuffLength _ANSI_ARGS_((FlatBlock in));
+int	GetIQScale (void);
+int	GetPQScale (void);
+int	GetBQScale (void);
+void	Tune_Init (void);
+int     CalcRLEHuffLength (FlatBlock in);
 void    ParseTuneParam(const char * const charPtr);
-int     mse _ANSI_ARGS_((Block blk1, Block blk2));
-void    Mpost_UnQuantZigBlockLaplace _ANSI_ARGS_((FlatBlock in, Block out, int qscale, boolean iblock));
+int     mse (Block blk1, Block blk2);
+void    Mpost_UnQuantZigBlockLaplace (FlatBlock in, Block out, int qscale, boolean iblock);
 extern void CalcLambdas(void);
 
 
diff --git a/converter/ppm/ppmtompeg/headers/parallel.h b/converter/ppm/ppmtompeg/headers/parallel.h
index 90edd874..0a31fac2 100644
--- a/converter/ppm/ppmtompeg/headers/parallel.h
+++ b/converter/ppm/ppmtompeg/headers/parallel.h
@@ -30,7 +30,6 @@
  * HEADER FILES *
  *==============*/
 
-#include "ansi.h"
 #include "bitio.h"
 #include "frame.h"
 
diff --git a/converter/ppm/ppmtompeg/headers/param.h b/converter/ppm/ppmtompeg/headers/param.h
index c7f57b44..46a544b3 100644
--- a/converter/ppm/ppmtompeg/headers/param.h
+++ b/converter/ppm/ppmtompeg/headers/param.h
@@ -1,7 +1,6 @@
 /* COPYRIGHT information is at end of file */
 
 #include "pm_c_util.h"
-#include "ansi.h"
 #include "input.h"
 
 
@@ -51,7 +50,7 @@ extern char machineName[MAX_MACHINES][256];
 extern char userName[MAX_MACHINES][256];
 extern char executable[MAX_MACHINES][1024];
 extern char remoteParamFile[MAX_MACHINES][1024];
-extern boolean remote[MAX_MACHINES];
+extern bool remote[MAX_MACHINES];
 extern char currentPath[MAXPATHLEN];
 extern char currentFramePath[MAXPATHLEN];
 extern char currentGOPPath[MAXPATHLEN];
@@ -62,12 +61,21 @@ extern int realWidth, realHeight;
 extern char ioConversion[1024];
 extern char slaveConversion[1024];
 extern FILE * bitRateFile;
-extern boolean showBitRatePerFrame;
-extern boolean computeMVHist;
 extern const double VidRateNum[9];
-extern boolean keepTempFiles;
+extern bool keepTempFiles;
+extern int outputWidth, outputHeight;
+extern bool specificsOn;
+extern char specificsFile[256];
+extern char specificsDefines[1024];
+extern bool GammaCorrection;
+extern float GammaValue;
+extern char userDataFileName[256];
 
 
+/* Defined in ppmtompeg.c; computed from command line */
+extern bool showBitRatePerFrame;
+extern bool computeMVHist;
+
 /*
  * Copyright (c) 1995 The Regents of the University of California.
  * All rights reserved.
diff --git a/converter/ppm/ppmtompeg/headers/prototypes.h b/converter/ppm/ppmtompeg/headers/prototypes.h
index b421af35..432062e3 100644
--- a/converter/ppm/ppmtompeg/headers/prototypes.h
+++ b/converter/ppm/ppmtompeg/headers/prototypes.h
@@ -30,7 +30,6 @@
  *==============*/
 
 #include "general.h"
-#include "ansi.h"
 #include "frame.h"
 
 
@@ -38,34 +37,34 @@
  * EXTERNAL PROCEDURE prototypes *
  *===============================*/
 
-int GetBQScale _ANSI_ARGS_((void));
-int GetPQScale _ANSI_ARGS_((void));
-void    ResetBFrameStats _ANSI_ARGS_((void));
-void    ResetPFrameStats _ANSI_ARGS_((void));
+int GetBQScale (void);
+int GetPQScale (void);
+void    ResetBFrameStats (void);
+void    ResetPFrameStats (void);
 void SetSearchRange (int const pixelsP,
                      int const pixelsB);
 void
 SetPixelSearch(const char * const searchType);
-void    SetPQScale _ANSI_ARGS_((int qP));
-void    SetBQScale _ANSI_ARGS_((int qB));
-float   EstimateSecondsPerPFrame _ANSI_ARGS_((void));
-float   EstimateSecondsPerBFrame _ANSI_ARGS_((void));
-void    SetGOPSize _ANSI_ARGS_((int size));
+void    SetPQScale (int qP);
+void    SetBQScale (int qB);
+float   EstimateSecondsPerPFrame (void);
+float   EstimateSecondsPerBFrame (void);
+void    SetGOPSize (int size);
 void
 SetStatFileName(const char * const fileName);
 
 
-void DCTFrame _ANSI_ARGS_((MpegFrame * mf));
+void DCTFrame (MpegFrame * mf);
 
-void PPMtoYCC _ANSI_ARGS_((MpegFrame * mf));
+void PPMtoYCC (MpegFrame * mf);
 
-void    MotionSearchPreComputation _ANSI_ARGS_((MpegFrame *frame));
+void    MotionSearchPreComputation (MpegFrame *frame);
 
-void    ComputeHalfPixelData _ANSI_ARGS_((MpegFrame *frame));
-void mp_validate_size _ANSI_ARGS_((int *x, int *y));
+void    ComputeHalfPixelData (MpegFrame *frame);
+void mp_validate_size (int *x, int *y);
 
 
 /* psearch.c */
-void    ShowPMVHistogram _ANSI_ARGS_((FILE *fpointer));
-void    ShowBBMVHistogram _ANSI_ARGS_((FILE *fpointer));
-void    ShowBFMVHistogram _ANSI_ARGS_((FILE *fpointer));
+void    ShowPMVHistogram (FILE *fpointer);
+void    ShowBBMVHistogram (FILE *fpointer);
+void    ShowBFMVHistogram (FILE *fpointer);
diff --git a/converter/ppm/ppmtompeg/headers/rate.h b/converter/ppm/ppmtompeg/headers/rate.h
index df5ca1cc..a5f5076f 100644
--- a/converter/ppm/ppmtompeg/headers/rate.h
+++ b/converter/ppm/ppmtompeg/headers/rate.h
@@ -64,11 +64,11 @@ targetRateControl(MpegFrame * const frameP);
  * MB_RateOut
  *
  *      Prints out sampling of MB rate control data.  Every "nth" block
- *	stats are printed, with "n" controled by global RC_MB_SAMPLE_RATE
+ *	stats are printed, with "n" controlled by global RC_MB_SAMPLE_RATE
  *
  * RETURNS:     nothing
  *===========================================================================*/
-extern void MB_RateOut _ANSI_ARGS_((int type));
+extern void MB_RateOut (int type);
 
 
 /*===========================================================================*
@@ -92,7 +92,7 @@ updateRateControl(int const type);
  *
  * RETURNS:     new Qscale
  *===========================================================================*/
-extern int needQScaleChange _ANSI_ARGS_((int oldQScale,  Block blk0, Block blk1, Block blk2, Block blk3));
+extern int needQScaleChange (int oldQScale,  Block blk0, Block blk1, Block blk2, Block blk3);
 
 /*===========================================================================*
  *
@@ -101,7 +101,7 @@ extern int needQScaleChange _ANSI_ARGS_((int oldQScale,  Block blk0, Block blk1,
  *
  * RETURNS:   nothing
  *===========================================================================*/
-extern void incNumBlocks _ANSI_ARGS_((int num));
+extern void incNumBlocks (int num);
 
 
 /*===========================================================================*
@@ -113,7 +113,7 @@ extern void incNumBlocks _ANSI_ARGS_((int num));
  *
  * RETURNS:   nothing
  *===========================================================================*/
-extern void incMacroBlockBits _ANSI_ARGS_((int num));
+extern void incMacroBlockBits (int num);
 
 
 /*===========================================================================*
@@ -125,7 +125,7 @@ extern void incMacroBlockBits _ANSI_ARGS_((int num));
  *
  * RETURNS:     nothing
  *===========================================================================*/
-extern void SetRateControl _ANSI_ARGS_((char *charPtr));
+extern void SetRateControl (char *charPtr);
 
 
 /*===========================================================================*
@@ -150,7 +150,7 @@ setBufferSize(const char * const charPtr);
  *
  * RETURNS:     int (or -1 if invalid)
  *===========================================================================*/
-extern int getBufferSize _ANSI_ARGS_((void));
+extern int getBufferSize (void);
 
 
 /*===========================================================================*
@@ -178,7 +178,7 @@ setBitRate(const char * const charPtr);
  *
  * RETURNS:     int (-1 if Variable mode operation)
  *===========================================================================*/
-extern int getBitRate _ANSI_ARGS_((void));
+extern int getBitRate (void);
 
 
 /*===========================================================================*
@@ -189,7 +189,7 @@ extern int getBitRate _ANSI_ARGS_((void));
  *
  * RETURNS:     integer
  *===========================================================================*/
-extern int getRateMode _ANSI_ARGS_((void));
+extern int getRateMode (void);
 
 
 /*===========================================================================*
@@ -200,5 +200,5 @@ extern int getRateMode _ANSI_ARGS_((void));
  *
  * RETURNS:   nothing
  *===========================================================================*/
-extern void incQuantOverride  _ANSI_ARGS_((int num));
+extern void incQuantOverride  (int num);
 
diff --git a/converter/ppm/ppmtompeg/headers/specifics.h b/converter/ppm/ppmtompeg/headers/specifics.h
index 7bcf4ace..4f5c7074 100644
--- a/converter/ppm/ppmtompeg/headers/specifics.h
+++ b/converter/ppm/ppmtompeg/headers/specifics.h
@@ -1,4 +1,3 @@
-#include "ansi.h"
 
 
 /*===========*
@@ -29,8 +28,8 @@ typedef struct fsl_def {
 } FrameSpecList;
 
 
-void	Specifics_Init _ANSI_ARGS_((void));
-int     SpecLookup _ANSI_ARGS_((int fn, int typ, int num, 
-				BlockMV **info, int start_qs));
-int SpecTypeLookup _ANSI_ARGS_((int fn));
+void	Specifics_Init (void);
+int     SpecLookup (int fn, int typ, int num,
+			    BlockMV **info, int start_qs);
+int SpecTypeLookup (int fn);
 
diff --git a/converter/ppm/ppmtompeg/huff.c b/converter/ppm/ppmtompeg/huff.c
index 821daca1..f2be16ef 100644
--- a/converter/ppm/ppmtompeg/huff.c
+++ b/converter/ppm/ppmtompeg/huff.c
@@ -24,8 +24,9 @@
  */
 
 /*  
- *  THIS FILE IS MACHINE GENERATED!  DO NOT EDIT!
+ *  THIS FILE WAS ORIGINALLY MACHINE GENERATED
  */
+#include "general.h"
 #include "mtypes.h"
 #include "huff.h"
 
diff --git a/converter/ppm/ppmtompeg/input.c b/converter/ppm/ppmtompeg/input.c
index 2b87afa7..4266d39b 100644
--- a/converter/ppm/ppmtompeg/input.c
+++ b/converter/ppm/ppmtompeg/input.c
@@ -104,17 +104,17 @@ GetNthInputFileName(struct inputSource * const inputSourceP,
         }
 
         if (mapNEntryP->repeat != TRUE)
-            asprintfN(fileNameP, "%s%s%s",
-                      mapNEntryP->left, &numBuffer[32-numPadding],
-                      mapNEntryP->right);
+            pm_asprintf(fileNameP, "%s%s%s",
+                        mapNEntryP->left, &numBuffer[32-numPadding],
+                        mapNEntryP->right);
         else
-            asprintfN(fileNameP, "%s", mapNEntryP->left);
+            pm_asprintf(fileNameP, "%s", mapNEntryP->left);
     } else {
         if (mapNEntryP->repeat != TRUE)
-            asprintfN(fileNameP, "%s%d%s",
-                      mapNEntryP->left, index, mapNEntryP->right);
+            pm_asprintf(fileNameP, "%s%d%s",
+                        mapNEntryP->left, index, mapNEntryP->right);
         else
-            asprintfN(fileNameP, "%s", mapNEntryP->left);
+            pm_asprintf(fileNameP, "%s", mapNEntryP->left);
     }
 
     lastN = n;
diff --git a/converter/ppm/ppmtompeg/jpeg.c b/converter/ppm/ppmtompeg/jpeg.c
index a703cf39..24c9ae2d 100644
--- a/converter/ppm/ppmtompeg/jpeg.c
+++ b/converter/ppm/ppmtompeg/jpeg.c
@@ -17,7 +17,6 @@
 #define _XOPEN_SOURCE    /* Make sure stdio.h contains fileno() */
 #include <unistd.h>
 #include <stdio.h>
-#include "all.h"
 /* With the lossless jpeg patch applied to the Jpeg library
     (ftp://ftp.wizards.dupont.com/pub/ImageMagick/delegates/ljpeg-6b.tar.gz),
     the name of min_DCT_scaled_size changes to min_codec_data_unit,
@@ -26,16 +25,17 @@
 #define min_codec_data_unit min_DCT_scaled_size
 #include <jpeglib.h>
 #undef min_codec_data_unit
-#include "mtypes.h"
-#include "frames.h"
-#include "prototypes.h"
-#include "param.h"
-#include "readframe.h"
+
+#include "netpbm/pm_config.h"
+#include "netpbm/pm_c_util.h"
+#include "netpbm/mallocvar.h"
+#include "netpbm/pm.h"
+
 #include "fsize.h"
-#include "rgbtoycc.h"
+#include "frame.h"
+
 #include "jpeg.h"
 
-#include "mallocvar.h"
 
 /* make it happier.... */
 #undef DCTSIZE2
@@ -101,7 +101,7 @@ JMovie2JPEG(const char * const infilename,
     char ofname[256];     /* output filename string */
     int Temp = 0, temp = 0;   /* dummy variables */
     int image_offset = 0;     /* counting variable */
-    /* J_Movie header infomation */
+    /* J_Movie header information */
     int ver_no;           /* version number - expected to be 2 */
     int fps;              /* frame rate - frames per second */
     int no_frames;        /* total number of frames in jmovie */
@@ -360,7 +360,7 @@ JMovie2JPEG(const char * const infilename,
  *
  *      allocate and initialize JPEG decompression object
  *      specify data source (eg, a file)
- *      jpeg_read_header();     // obtain image dimensions and other parameters
+ *      jpeg_read_header();      obtain image dimensions and other parameters
  *      set parameters for decompression
  *      jpeg_start_decompress();
  *      while (scan lines remain to be read)
@@ -385,7 +385,7 @@ ReadJPEG(MpegFrame * const mf,
     jpeg_component_info *compptr;
     int buffer_height;
     int current_row[3];
-    uint8 **orig[3];
+    uint8_t **orig[3];
     int h_samp[3],v_samp[3];
     int max_h_samp,max_v_samp;
     int temp_h, temp_v;
@@ -500,7 +500,7 @@ ReadJPEG(MpegFrame * const mf,
 
         (void) jpeg_read_raw_data(&cinfo, scanarray, buffer_height);
 
-        /* alter subsample ratio's if neccessary */
+        /* alter subsample ratio's if necessary */
         if ((h_samp[0]==2) && (h_samp[1]==1) && (h_samp[2]==1) &&
             (v_samp[0]==2) && (v_samp[1]==1) && (v_samp[2]==1)) {
             /* we are 4:1:1 as expected by the encoder*/
diff --git a/converter/ppm/ppmtompeg/jrevdct.c b/converter/ppm/ppmtompeg/jrevdct.c
index 2e99a67a..bf9196c4 100644
--- a/converter/ppm/ppmtompeg/jrevdct.c
+++ b/converter/ppm/ppmtompeg/jrevdct.c
@@ -28,7 +28,6 @@
 
 #include <memory.h>
 #include "all.h"
-#include "ansi.h"
 #include "dct.h"
 
 
@@ -162,9 +161,9 @@ ones here or successive P-frames will drift too much with Reference frame coding
 /*
   Switch on reverse_dct choices
 */
-void reference_rev_dct _ANSI_ARGS_((int16 *block));
-void mpeg_jrevdct_quick _ANSI_ARGS_((int16 *block));
-void init_idctref _ANSI_ARGS_((void));
+void reference_rev_dct (int16 *block);
+void mpeg_jrevdct_quick (int16 *block);
+void init_idctref (void);
 
 extern boolean pureDCT;
 
@@ -199,7 +198,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/converter/ppm/ppmtompeg/mfwddct.c b/converter/ppm/ppmtompeg/mfwddct.c
index 4643bf25..75c3a718 100644
--- a/converter/ppm/ppmtompeg/mfwddct.c
+++ b/converter/ppm/ppmtompeg/mfwddct.c
@@ -122,33 +122,68 @@
 #define OSIN_5_16 OCOS_3_16
 #define OCOS_5_16 OSIN_3_16
 
-/* Prototypes */
-void reference_fwd_dct _ANSI_ARGS_((Block block, Block dest));
-void mp_fwd_dct_fast _ANSI_ARGS_((Block data2d, Block dest2d));
-void init_fdct _ANSI_ARGS_((void));
 
-/*
- * --------------------------------------------------------------
- *
- * mp_fwd_dct_block2 --
- *
- * Select the appropriate mp_fwd_dct routine
- *
- * Results: None
- *
- * Side effects: None
- *
- * --------------------------------------------------------------
- */
-extern boolean pureDCT;
-void
-mp_fwd_dct_block2(data, dest)
-    Block data, dest;
+static double trans_coef[8][8]; /* transform coefficients */
+
+
+
+static void reference_fwd_dct(block, dest)
+Block block, dest;
 {
-  if (pureDCT) reference_fwd_dct(data, dest);
-  else mp_fwd_dct_fast(data, dest);
+  int i, j, k;
+  double s;
+  double tmp[64];
+
+  if (DoLaplace) {
+    LaplaceNum++;
+  }
+
+  for (i=0; i<8; i++)
+    for (j=0; j<8; j++)
+    {
+      s = 0.0;
+
+      for (k=0; k<8; k++)
+        s += trans_coef[j][k] * block[i][k];
+
+      tmp[8*i+j] = s;
+    }
+
+  for (i=0; i<8; i++)
+    for (j=0; j<8; j++)
+    {
+      s = 0.0;
+
+      for (k=0; k<8; k++)
+        s += trans_coef[i][k] * tmp[8*k+j];
+
+      if (collect_quant) {
+	fprintf(collect_quant_fp, "%d %f\n", 8*i+j, s);
+      } 
+      if (DoLaplace) {
+	L1[LaplaceCnum][i*8+j] += s*s;
+	L2[LaplaceCnum][i*8+j] += s;
+      }
+
+
+      dest[i][j] = (int)floor(s+0.499999);
+      /*
+       * reason for adding 0.499999 instead of 0.5:
+       * s is quite often x.5 (at least for i and/or j = 0 or 4)
+       * and setting the rounding threshold exactly to 0.5 leads to an
+       * extremely high arithmetic implementation dependency of the result;
+       * s being between x.5 and x.500001 (which is now incorrectly rounded
+       * downwards instead of upwards) is assumed to occur less often
+       * (if at all)
+       */
+    }
 }
 
+
+
+static void
+mp_fwd_dct_fast(data2d, dest2d)
+    Block data2d, dest2d;
 /*
  * --------------------------------------------------------------
  *
@@ -166,9 +201,6 @@ mp_fwd_dct_block2(data, dest)
  * --------------------------------------------------------------
  */
 
-void
-mp_fwd_dct_fast(data2d, dest2d)
-    Block data2d, dest2d;
 {
     int16 *data = (int16 *) data2d;	/* this algorithm wants
 					 * a 1-d array */
@@ -236,10 +268,12 @@ mp_fwd_dct_fast(data2d, dest2d)
 	    tmp13 = tmp0 - tmp3;
 
 	    outptr[0] = (int16) UNFIXH((tmp10 + tmp11) * SIN_1_4);
-	    outptr[DCTSIZE * 4] = (int16) UNFIXH((tmp10 - tmp11) * COS_1_4);
-
-	    outptr[DCTSIZE * 2] = (int16) UNFIXH(tmp13 * COS_1_8 + tmp12 * SIN_1_8);
-	    outptr[DCTSIZE * 6] = (int16) UNFIXH(tmp13 * SIN_1_8 - tmp12 * COS_1_8);
+	    outptr[DCTSIZE * 4] =
+            (int16) UNFIXH((tmp10 - tmp11) * COS_1_4);
+	    outptr[DCTSIZE * 2] =
+            (int16) UNFIXH(tmp13 * COS_1_8 + tmp12 * SIN_1_8);
+	    outptr[DCTSIZE * 6] =
+            (int16) UNFIXH(tmp13 * SIN_1_8 - tmp12 * COS_1_8);
 
 	    tmp16 = UNFIXO((tmp6 + tmp5) * SIN_1_4);
 	    tmp15 = UNFIXO((tmp6 - tmp5) * COS_1_4);
@@ -257,10 +291,14 @@ mp_fwd_dct_fast(data2d, dest2d)
 	    tmp26 = tmp7 - tmp16;
 	    tmp17 = tmp7 + tmp16;
 
-	    outptr[DCTSIZE] = (int16) UNFIXH(tmp17 * OCOS_1_16 + tmp14 * OSIN_1_16);
-	    outptr[DCTSIZE * 7] = (int16) UNFIXH(tmp17 * OCOS_7_16 - tmp14 * OSIN_7_16);
-	    outptr[DCTSIZE * 5] = (int16) UNFIXH(tmp26 * OCOS_5_16 + tmp25 * OSIN_5_16);
-	    outptr[DCTSIZE * 3] = (int16) UNFIXH(tmp26 * OCOS_3_16 - tmp25 * OSIN_3_16);
+	    outptr[DCTSIZE] =
+            (int16) UNFIXH(tmp17 * OCOS_1_16 + tmp14 * OSIN_1_16);
+	    outptr[DCTSIZE * 7] =
+            (int16) UNFIXH(tmp17 * OCOS_7_16 - tmp14 * OSIN_7_16);
+	    outptr[DCTSIZE * 5] =
+            (int16) UNFIXH(tmp26 * OCOS_5_16 + tmp25 * OSIN_5_16);
+	    outptr[DCTSIZE * 3] =
+            (int16) UNFIXH(tmp26 * OCOS_3_16 - tmp25 * OSIN_3_16);
 
 	    inptr += DCTSIZE;	/* advance inptr to next row */
 	    outptr++;		/* advance outptr to next column */
@@ -285,6 +323,28 @@ mp_fwd_dct_fast(data2d, dest2d)
 }
 
 
+extern boolean pureDCT;
+void
+mp_fwd_dct_block2(data, dest)
+    DCTBLOCK_2D data, dest;
+/*
+ * --------------------------------------------------------------
+ *
+ * mp_fwd_dct_block2 --
+ *
+ * Select the appropriate mp_fwd_dct routine
+ *
+ * Results: None
+ *
+ * Side effects: None
+ *
+ * --------------------------------------------------------------
+ */
+{
+  if (pureDCT) reference_fwd_dct(data, dest);
+  else mp_fwd_dct_fast(data, dest);
+}
+
 /* Modifies from the MPEG2 verification coder */
 /* fdctref.c, forward discrete cosine transform, double precision           */
 
@@ -323,9 +383,6 @@ mp_fwd_dct_fast(data2d, dest2d)
 #endif
 #endif
 
-/* private data */
-static double trans_coef[8][8]; /* transform coefficients */
-
 void init_fdct()
 {
   int i, j;
@@ -340,54 +397,5 @@ void init_fdct()
   }
 }
 
-void reference_fwd_dct(block, dest)
-Block block, dest;
-{
-  int i, j, k;
-  double s;
-  double tmp[64];
-
-  if (DoLaplace) {
-    LaplaceNum++;
-  }
-
-  for (i=0; i<8; i++)
-    for (j=0; j<8; j++)
-    {
-      s = 0.0;
-
-      for (k=0; k<8; k++)
-        s += trans_coef[j][k] * block[i][k];
 
-      tmp[8*i+j] = s;
-    }
 
-  for (i=0; i<8; i++)
-    for (j=0; j<8; j++)
-    {
-      s = 0.0;
-
-      for (k=0; k<8; k++)
-        s += trans_coef[i][k] * tmp[8*k+j];
-
-      if (collect_quant) {
-	fprintf(collect_quant_fp, "%d %f\n", 8*i+j, s);
-      } 
-      if (DoLaplace) {
-	L1[LaplaceCnum][i*8+j] += s*s;
-	L2[LaplaceCnum][i*8+j] += s;
-      }
-
-
-      dest[i][j] = (int)floor(s+0.499999);
-      /*
-       * reason for adding 0.499999 instead of 0.5:
-       * s is quite often x.5 (at least for i and/or j = 0 or 4)
-       * and setting the rounding threshold exactly to 0.5 leads to an
-       * extremely high arithmetic implementation dependency of the result;
-       * s being between x.5 and x.500001 (which is now incorrectly rounded
-       * downwards instead of upwards) is assumed to occur less often
-       * (if at all)
-       */
-    }
-}
diff --git a/converter/ppm/ppmtompeg/mpeg.c b/converter/ppm/ppmtompeg/mpeg.c
index 6557f377..24d337ed 100644
--- a/converter/ppm/ppmtompeg/mpeg.c
+++ b/converter/ppm/ppmtompeg/mpeg.c
@@ -30,6 +30,7 @@
  * HEADER FILES *
  *==============*/
 
+#define _XOPEN_SOURCE 500  /* Make sure strdup() is in string.h */
 #define _BSD_SOURCE   /* Make sure strdup() is in string.h */
 
 #include "all.h"
@@ -125,9 +126,9 @@ int32 bit_rate, buf_size;
  * INTERNAL PROCEDURE prototypes *
  *===============================*/
 
-static void ComputeDHMSTime _ANSI_ARGS_((int32 someTime, char *timeText));
-static void OpenBitRateFile _ANSI_ARGS_((void));
-static void CloseBitRateFile _ANSI_ARGS_((void));
+static void ComputeDHMSTime (int32 someTime, char *timeText);
+static void OpenBitRateFile (void);
+static void CloseBitRateFile (void);
 
 
 static void
@@ -413,11 +414,11 @@ bitioNew(const char * const outputFileName,
     else {
         const char * fileName;
 
-        asprintfN(&fileName, "%s.frame.%d", outputFileName, frameNumber);
+        pm_asprintf(&fileName, "%s.frame.%d", outputFileName, frameNumber);
 
         bbP = Bitio_New_Filename(fileName);
 
-        strfree(fileName);
+        pm_strfree(fileName);
     }
     return bbP;
 }
@@ -771,12 +772,12 @@ doFirstFrameStuff(enum frameContext const context,
             time_t now;
                     
             time(&now);
-            asprintfN(&userDataString,"MPEG stream encoded by UCB Encoder "
-                      "(mpeg_encode) v%s on %s.",
-                      VERSION, ctime(&now));
+            pm_asprintf(&userDataString,"MPEG stream encoded by UCB Encoder "
+                        "(mpeg_encode) v%s on %s.",
+                        VERSION, ctime(&now));
             userData = strdup(userDataString);
             userDataSize = strlen(userData);
-            strfree(userDataString);
+            pm_strfree(userDataString);
         }
         Mhead_GenSequenceHeader(bbP, Fsize_x, Fsize_y,
                                 /* pratio */ aspectRatio,
@@ -1322,12 +1323,12 @@ PrintStartStats(time_t               const startTime,
             GetNthInputFileName(inputSourceP, 0, &inputFileName);
             fprintf(fpointer, "FIRST FILE:  %s/%s\n", 
                     currentPath, inputFileName);
-            strfree(inputFileName);
+            pm_strfree(inputFileName);
             GetNthInputFileName(inputSourceP, inputSourceP->numInputFiles-1, 
                                 &inputFileName);
             fprintf(fpointer, "LAST FILE:  %s/%s\n", 
                     currentPath, inputFileName);
-            strfree(inputFileName);
+            pm_strfree(inputFileName);
         }    
         fprintf(fpointer, "OUTPUT:  %s\n", outputFileName);
 
@@ -1680,7 +1681,7 @@ ReadDecodedRefFrame(MpegFrame *  const frameP,
     }
 
     if ((fpointer = fopen(fileName, "rb")) == NULL) {
-        sleepN(1000);
+        pm_sleep(1000);
         if ((fpointer = fopen(fileName, "rb")) == NULL) {
             fprintf(stderr, "Cannot open %s\n", fileName);
             exit(1);
diff --git a/converter/ppm/ppmtompeg/opts.c b/converter/ppm/ppmtompeg/opts.c
index c4d0c0b3..841efdab 100644
--- a/converter/ppm/ppmtompeg/opts.c
+++ b/converter/ppm/ppmtompeg/opts.c
@@ -40,6 +40,7 @@
 #include <stdlib.h>
 #include <math.h>
 #include "opts.h"
+#include "dct.h"
 
 /*==============*
  * EXTERNALS    *
@@ -51,8 +52,7 @@ extern int32   qtable[], niqtable[];
 extern int     ZAG[];
 extern boolean printSNR, decodeRefFrames;
 
-void init_idctref _ANSI_ARGS_((void));
-void init_fdct _ANSI_ARGS_((void));
+void init_idctref (void);
 
 
 /*===================*
@@ -255,7 +255,7 @@ SetupLocalDCT(const char * const charPtr)
  *
  * SetupLaplace
  *
- *     Setup encoder to find distrubution for I-frames, and use for -snr
+ *     Setup encoder to find distribution for I-frames, and use for -snr
  *
  * RETURNS:	nothing
  *
diff --git a/converter/ppm/ppmtompeg/parallel.c b/converter/ppm/ppmtompeg/parallel.c
index e13bf221..2835c67c 100644
--- a/converter/ppm/ppmtompeg/parallel.c
+++ b/converter/ppm/ppmtompeg/parallel.c
@@ -156,7 +156,7 @@ machineDebug(const char format[], ...) {
     if (debugMachines) {
         const char * const hostname = GetHostName();
         fprintf(stderr, "%s: ---", hostname);
-        strfree(hostname);
+        pm_strfree(hostname);
         vfprintf(stderr, format, args);
         fputc('\n', stderr);
     }
@@ -175,7 +175,7 @@ errorExit(const char format[], ...) {
     va_start(args, format);
 
     fprintf(stderr, "%s: FATAL ERROR.  ", hostname);
-    strfree(hostname);
+    pm_strfree(hostname);
     vfprintf(stderr, format, args);
     fputc('\n', stderr);
 
@@ -767,13 +767,13 @@ routeFromSocketToDisk(int              const otherSock,
     ReadBytes(otherSock, bigBuffer, numBytes);
     
     /* open file to output this stuff to */
-    asprintfN(&fileName, "%s.frame.%d", outputFileName, frameNumber);
+    pm_asprintf(&fileName, "%s.frame.%d", outputFileName, frameNumber);
     filePtr = fopen(fileName, "wb");
 
     if (filePtr == NULL)
         errorExit("I/O SERVER: Could not open output file(3):  %s", fileName);
 
-    strfree(fileName);
+    pm_strfree(fileName);
 
     /* now write the bytes here */
     fwrite(bigBuffer, sizeof(char), numBytes, filePtr);
@@ -968,7 +968,7 @@ IoServer(struct inputSource * const inputSourceP,
 -----------------------------------------------------------------------------*/
     int       ioPortNum;
     int       serverSocket;
-    boolean   done;
+    bool   done;
     unsigned char   *bigBuffer;
         /* A work buffer that we keep around permanently.  We increase
            its size as needed, but never shrink it.
@@ -1104,8 +1104,8 @@ GetRemoteFrame(MpegFrame * const frameP,
 
                 if (numBytes > sizeof(buffer))
                     errorExit("Invalid message received: numBytes = %d, "
-                              "which is greater than %d\n", 
-                              numBytes, sizeof(numBytes));
+                              "which is greater than %u", 
+                              numBytes, (unsigned)sizeof(numBytes));
                 ReadBytes(clientSocket, buffer, numBytes);
 
                 fwrite(buffer, 1, numBytes, filePtr);
@@ -1209,7 +1209,7 @@ openInputFile(const char * const fileName,
             pm_message("ERROR  Couldn't read frame file '%s' errno = %d (%s)"
                        "attempt %d", 
                        fileName, errno, strerror(errno), attempts);
-            sleepN(1000);
+            pm_sleep(1000);
         }
         ++attempts;
     }
@@ -1246,11 +1246,11 @@ waitForOutputFile(void *        const inputHandle,
         }
         machineDebug("COMBINE SERVER: Wait for frame %u over", frameNumber);
 
-        asprintfN(&fileName, "%s.frame.%u", outputFileName, frameNumber);
+        pm_asprintf(&fileName, "%s.frame.%u", outputFileName, frameNumber);
 
         openInputFile(fileName, ifPP);
 
-        strfree(fileName);
+        pm_strfree(fileName);
     }
 }
 
@@ -1263,11 +1263,11 @@ unlinkFile(void *       const inputHandle,
     if (!keepTempFiles) {
         const char * fileName;
 
-        asprintfN(&fileName, "%s.frame.%u", outputFileName, frameNumber);
+        pm_asprintf(&fileName, "%s.frame.%u", outputFileName, frameNumber);
 
         unlink(fileName);
 
-        strfree(fileName);
+        pm_strfree(fileName);
     }
 }
 
@@ -1340,13 +1340,13 @@ startCombineServer(const char * const encoderName,
     int          otherSock;
     const char * error;
 
-    snprintf(command, sizeof(command), 
-             "%s %s -max_machines %d -output_server %s %d %d %s",
-             encoderName, 
-             debugMachines ? "-debug_machines" : "",
-             numMachines, masterHostName, masterPortNum, 
-             numInputFiles, paramFileName);
-
+    pm_snprintf(command, sizeof(command), 
+                "%s %s -max_machines %d -output_server %s %d %d %s",
+                encoderName, 
+                debugMachines ? "-debug_machines" : "",
+                numMachines, masterHostName, masterPortNum, 
+                numInputFiles, paramFileName);
+    
     machineDebug("MASTER: Starting combine server with shell command '%s'",
                  command);
 
@@ -1382,12 +1382,12 @@ startDecodeServer(const char * const encoderName,
     int          otherSock;
     const char * error;
 
-    snprintf(command, sizeof(command), 
-             "%s %s -max_machines %d -decode_server %s %d %d %s",
-             encoder_name, 
-             debugMachines ? "-debug_machines" : "",
-             numMachines, masterHostName, masterPortNum,
-             numInputFiles, paramFileName);
+    pm_snprintf(command, sizeof(command), 
+                "%s %s -max_machines %d -decode_server %s %d %d %s",
+                encoder_name, 
+                debugMachines ? "-debug_machines" : "",
+                numMachines, masterHostName, masterPortNum,
+                numInputFiles, paramFileName);
 
     machineDebug("MASTER: Starting decode server with shell command '%s'",
                  command);
@@ -1680,23 +1680,23 @@ startChildren(struct scheduler *   const schedulerP,
                 }
                 --childrenLeftCurrentIoServer;
             } 
-            snprintf(command, sizeof(command),
-                     "%s %s -l %s %s "
-                     "%s %s -child %s %d %d %d %d %d %d "
-                     "-frames %d %d %s",
-                     rsh,
-                     machineName[childNum], userName[childNum],
-                     beNice ? "nice" : "",
-                     executable[childNum],
-                     debugMachines ? "-debug_machines" : "",
-                     masterHostName, masterPortNum, 
-                     remote[childNum] ? ioPortNum[numIoServers-1] : 0,
-                     combinePortNum, decodePortNum, childNum,
-                     remote[childNum] ? 1 : 0,
-                     startFrame, startFrame + nFrames - 1,
-                     remote[childNum] ? 
-                         remoteParamFile[childNum] : paramFileName
-            );
+            pm_snprintf(command, sizeof(command),
+                        "%s %s -l %s %s "
+                        "%s %s -child %s %d %d %d %d %d %d "
+                        "-frames %d %d %s",
+                        rsh,
+                        machineName[childNum], userName[childNum],
+                        beNice ? "nice" : "",
+                        executable[childNum],
+                        debugMachines ? "-debug_machines" : "",
+                        masterHostName, masterPortNum, 
+                        remote[childNum] ? ioPortNum[numIoServers-1] : 0,
+                        combinePortNum, decodePortNum, childNum,
+                        remote[childNum] ? 1 : 0,
+                        startFrame, startFrame + nFrames - 1,
+                        remote[childNum] ? 
+                          remoteParamFile[childNum] : paramFileName
+                );
         
             machineDebug("MASTER: Starting child server "
                          "with shell command '%s'", command);
@@ -2070,7 +2070,7 @@ MasterServer(struct inputSource * const inputSourceP,
         fclose(statFile);
 
     free(childState);
-    strfree(hostName);
+    pm_strfree(hostName);
 }
 
 
diff --git a/converter/ppm/ppmtompeg/param.c b/converter/ppm/ppmtompeg/param.c
index a145d33c..45605981 100644
--- a/converter/ppm/ppmtompeg/param.c
+++ b/converter/ppm/ppmtompeg/param.c
@@ -73,14 +73,14 @@
 #define LAST_OPTION           15
 
 /* put any non-required options after LAST_OPTION */
-#define OPTION_RESIZE	      16
+#define OPTION_RESIZE         16
 #define OPTION_IO_CONVERT     17
 #define OPTION_SLAVE_CONVERT  18
-#define OPTION_IQTABLE	      19
-#define OPTION_NIQTABLE	      20
+#define OPTION_IQTABLE        19
+#define OPTION_NIQTABLE       20
 #define OPTION_FRAME_RATE     21
 #define OPTION_ASPECT_RATIO   22
-#define OPTION_YUV_SIZE	      23
+#define OPTION_YUV_SIZE       23
 #define OPTION_SPECIFICS      24
 #define OPTION_DEFS_SPECIFICS 25
 #define OPTION_BUFFER_SIZE    26
@@ -98,48 +98,49 @@
  * GLOBAL VARIABLES *
  *==================*/
 
-extern char currentPath[MAXPATHLEN];
-char	outputFileName[256];
-int	outputWidth, outputHeight;
+char outputFileName[256];
+int outputWidth, outputHeight;
 char inputConversion[1024];
 char ioConversion[1024];
 char slaveConversion[1024];
 char yuvConversion[256];
 char specificsFile[256],specificsDefines[1024]="";
-boolean GammaCorrection=FALSE;
-float   GammaValue;
+bool GammaCorrection=FALSE;
+float GammaValue;
 char userDataFileName[256]={0};
-boolean specificsOn = FALSE;
+bool specificsOn = FALSE;
 char currentGOPPath[MAXPATHLEN];
 char currentFramePath[MAXPATHLEN];
-boolean keepTempFiles;
+bool keepTempFiles;
+int numMachines;
+char machineName[MAX_MACHINES][256];
+char userName[MAX_MACHINES][256];
+char executable[MAX_MACHINES][1024];
+char remoteParamFile[MAX_MACHINES][1024];
+bool remote[MAX_MACHINES];
+int mult_seq_headers = 0;  /* 0 for none, N for header/N GOPs */
+
+
+extern char currentPath[MAXPATHLEN];
 
 static const char * const optionText[LAST_OPTION+1] = { 
     "GOP_SIZE", "PATTERN", "PIXEL", "PQSCALE",
     "OUTPUT", "RANGE", "PSEARCH_ALG", "IQSCALE", "INPUT_DIR",
     "INPUT_CONVERT", "INPUT", "BQSCALE", "BASE_FILE_FORMAT",
     "SLICES_PER_FRAME", "BSEARCH_ALG", "REFERENCE_FRAME"};
-static boolean optionSeen[NUM_OPTIONS+1];
+static bool optionSeen[NUM_OPTIONS+1];
     /* optionSeen[x] means we have seen option x in the parameter file we've
        been reading.
     */
 
-int numMachines;
-char	machineName[MAX_MACHINES][256];
-char	userName[MAX_MACHINES][256];
-char	executable[MAX_MACHINES][1024];
-char	remoteParamFile[MAX_MACHINES][1024];
-boolean	remote[MAX_MACHINES];
-int mult_seq_headers = 0;  /* 0 for none, N for header/N GOPs */
-
 
 /*===========================================================================*
  *
  * SkipSpacesTabs
  *
- *	skip all spaces and tabs
+ *  skip all spaces and tabs
  *
- * RETURNS:	point to next character not a space or tab
+ * RETURNS: point to next character not a space or tab
  *
  * SIDE EFFECTS:    none
  *
@@ -172,13 +173,13 @@ static int
 GetAspectRatio(const char * const p)
 {
   float   ratio;
-  int	  ttRatio;
+  int     ttRatio;
   int     retval;
 
   sscanf(p, "%f", &ratio);
   ttRatio = (int)(0.5+ratio*10000.0);
 
-  if ( ttRatio == 10000 )	      retval = 1;
+  if ( ttRatio == 10000 )         retval = 1;
   else if ( ttRatio ==  6735 )    retval = 2;
   else if ( ttRatio ==  7031 )    retval = 3;
   else if ( ttRatio ==  7615 )    retval = 4;
@@ -205,9 +206,9 @@ GetAspectRatio(const char * const p)
  *
  * ReadMachineNames
  *
- *	read a list of machine names for parallel execution
+ *  read a list of machine names for parallel execution
  *
- * RETURNS:	nothing
+ * RETURNS: nothing
  *
  * SIDE EFFECTS:    machine info updated
  *
@@ -219,7 +220,7 @@ ReadMachineNames(FILE * const fpointer)
   const char *charPtr;
 
   while ( (fgets(input, 256, fpointer) != NULL) &&
-	 (strncmp(input, "END_PARALLEL", 12) != 0) ) {
+     (strncmp(input, "END_PARALLEL", 12) != 0) ) {
     if ( input[0] == '#' || input[0] == '\n') {
       continue;
     }
@@ -229,13 +230,13 @@ ReadMachineNames(FILE * const fpointer)
       remote[numMachines] = TRUE;
 
       sscanf(charPtr, "%s %s %s %s", machineName[numMachines],
-	     userName[numMachines], executable[numMachines],
-	     remoteParamFile[numMachines]);
+         userName[numMachines], executable[numMachines],
+         remoteParamFile[numMachines]);
     } else {
       remote[numMachines] = FALSE;
 
       sscanf(input, "%s %s %s", machineName[numMachines],
-	     userName[numMachines], executable[numMachines]);
+         userName[numMachines], executable[numMachines]);
     }
 
     numMachines++;
@@ -259,13 +260,13 @@ static int
 GetFrameRate(const char * const p)
 {
   float   rate;
-  int	  thouRate;
+  int     thouRate;
   int     retval;
 
   sscanf(p, "%f", &rate);
   thouRate = (int)(0.5+1000.0*rate);
 
-  if ( thouRate == 23976 )	       retval = 1;
+  if ( thouRate == 23976 )         retval = 1;
   else if ( thouRate == 24000 )    retval = 2;
   else if ( thouRate == 25000 )    retval = 3;
   else if ( thouRate == 29970 )    retval = 4;
@@ -988,7 +989,7 @@ ReadParamFile(const char *         const fileName,
                            paramP);
               /* May read additional lines from file */
 
-      strfree(input);
+      pm_strfree(input);
   }
 
   fclose(fpointer);
diff --git a/converter/ppm/ppmtompeg/ppmtompeg.c b/converter/ppm/ppmtompeg/ppmtompeg.c
index f53ffea9..cd94db39 100644
--- a/converter/ppm/ppmtompeg/ppmtompeg.c
+++ b/converter/ppm/ppmtompeg/ppmtompeg.c
@@ -30,12 +30,14 @@
  * HEADER FILES *
  *==============*/
 
+#define _XOPEN_SOURCE 500  /* Make sure strdup() is in string.h */
 #define _BSD_SOURCE   /* Make sure strdup() is in string.h */
 
 #include <assert.h>
 
 #include "all.h"
 #include "mtypes.h"
+#include "dct.h"
 #include "mpeg.h"
 #include "motion_search.h"
 #include "prototypes.h"
@@ -57,14 +59,15 @@
 
 #include <time.h>
 
-int main _ANSI_ARGS_((int argc, char **argv));
+int main (int argc, char **argv);
 
 
 /*==================*
  * GLOBAL VARIABLES *
  *==================*/
 
-boolean showBitRatePerFrame;
+bool showBitRatePerFrame;
+bool computeMVHist = FALSE;
 boolean frameSummary;
 
 extern time_t IOtime;
@@ -78,9 +81,7 @@ boolean noFrameSummaryOption = FALSE;
 boolean debugSockets = FALSE;
 boolean debugMachines = FALSE;
 boolean bitRateInfoOption = FALSE;
-boolean computeMVHist = FALSE;
 int     baseFormat;
-extern  boolean specificsOn;
 extern  FrameSpecList *fsl;
 boolean pureDCT=FALSE;
 char    encoder_name[1024];
@@ -91,8 +92,7 @@ const char * hostname;
  * External PROCEDURE prototypes  *
  *================================*/
 
-void init_idctref _ANSI_ARGS_((void));
-void init_fdct _ANSI_ARGS_((void));
+void init_idctref (void);
 
 
 struct cmdlineInfo {
@@ -335,9 +335,9 @@ announceJob(enum frameContext const context,
         const char * combineDest;
 
         if (context == CONTEXT_JUSTFRAMES)
-            asprintfN(&outputDest, "to individual frame files");
+            pm_asprintf(&outputDest, "to individual frame files");
         else
-            asprintfN(&outputDest, "to file '%s'", outputFileName);
+            pm_asprintf(&outputDest, "to file '%s'", outputFileName);
 
         if (childProcess)
             combineDest = strdup("for delivery to combine server");
@@ -347,8 +347,8 @@ announceJob(enum frameContext const context,
         pm_message("%s:  ENCODING FRAMES %u-%u to %s %s",
                    hostname, frameStart, frameEnd, outputDest, combineDest);
 
-        strfree(combineDest);
-        strfree(outputDest);
+        pm_strfree(combineDest);
+        pm_strfree(outputDest);
     }
 }
 
@@ -540,15 +540,15 @@ getUserFrameFile(void *       const handle,
 
         GetNthInputFileName(inputSourceP, frameNumber, &inputFileName);
         
-        asprintfN(&fileName, "%s/%s", currentFramePath, inputFileName);
+        pm_asprintf(&fileName, "%s/%s", currentFramePath, inputFileName);
         
         *ifPP = fopen(fileName, "rb");
         if (*ifPP == NULL)
             pm_error("Unable to open file '%s'.  Errno = %d (%s)",
                      fileName, errno, strerror(errno));
         
-        strfree(inputFileName);
-        strfree(fileName);
+        pm_strfree(inputFileName);
+        pm_strfree(fileName);
     }
 }
 
@@ -702,7 +702,7 @@ main(int argc, char **argv) {
     } 
     Frame_Exit();
         
-    strfree(hostname);
+    pm_strfree(hostname);
 
     return 0;
 }
diff --git a/converter/ppm/ppmtompeg/psearch.c b/converter/ppm/ppmtompeg/psearch.c
index 83c62d04..3cca1241 100644
--- a/converter/ppm/ppmtompeg/psearch.c
+++ b/converter/ppm/ppmtompeg/psearch.c
@@ -962,7 +962,7 @@ ShowBFMVHistogram(fpointer)
  * Changed copyrights
  *
  * Revision 1.8  1994/12/07  00:40:36  smoot
- * Added seperate P and B search ranges
+ * Added separate P and B search ranges
  *
  * Revision 1.7  1994/11/12  02:09:45  eyhung
  * full pixel bug
diff --git a/converter/ppm/ppmtompeg/psocket.c b/converter/ppm/ppmtompeg/psocket.c
index 707f1d84..6a50dc27 100644
--- a/converter/ppm/ppmtompeg/psocket.c
+++ b/converter/ppm/ppmtompeg/psocket.c
@@ -91,7 +91,7 @@ errorExit(const char format[], ...) {
     va_start(args, format);
 
     fprintf(stderr, "%s: FATAL ERROR.  ", hostname);
-    strfree(hostname);
+    pm_strfree(hostname);
     vfprintf(stderr, format, args);
     fputc('\n', stderr);
 
@@ -272,13 +272,13 @@ ConnectToSocket(const char *      const machineName,
     if ((*hostEnt) == NULL) {
         (*hostEnt) = gethostbyname(machineName);
         if ((*hostEnt) == NULL)
-            asprintfN(errorP, "Couldn't get host by name (%s)", machineName);
+            pm_asprintf(errorP, "Couldn't get host by name (%s)", machineName);
     }
     if (!*errorP) {
         rc = socket(AF_INET, SOCK_STREAM, 0);
         if (rc < 0)
-            asprintfN(errorP, "socket() failed with errno %d (%s)", 
-                      errno, strerror(errno));
+            pm_asprintf(errorP, "socket() failed with errno %d (%s)", 
+                        errno, strerror(errno));
         else {
             int const socketFd = rc;
             
@@ -298,10 +298,10 @@ ConnectToSocket(const char *      const machineName,
                          sizeof(struct sockaddr));
             
             if (rc != 0)
-                asprintfN(errorP, 
-                          "connect() to host '%s', port %d failed with "
-                          "errno %d (%s)",
-                          machineName, portNum, errno, strerror(errno));
+                pm_asprintf(errorP, 
+                            "connect() to host '%s', port %d failed with "
+                            "errno %d (%s)",
+                            machineName, portNum, errno, strerror(errno));
             else {
                 *errorP = NULL;
                 *socketFdP = socketFd;
@@ -364,14 +364,14 @@ bindToUnusedPort(int              const socketFd,
             foundPort = TRUE;
             *portNumP = trialPortNum;
         } else if (!portInUseErrno(errno))
-            asprintfN(errorP, "bind() of TCP port number %hu failed "
-                      "with errno %d (%s)", 
-                      trialPortNum, errno, strerror(errno));
+            pm_asprintf(errorP, "bind() of TCP port number %hu failed "
+                        "with errno %d (%s)", 
+                        trialPortNum, errno, strerror(errno));
     }
     
     if (!*errorP && !foundPort)
-        asprintfN(errorP, "Unable to find a free port.  Every TCP port "
-                  "in the range 2048-16383 is in use");
+        pm_asprintf(errorP, "Unable to find a free port.  Every TCP port "
+                    "in the range 2048-16383 is in use");
 }
 
 
@@ -392,10 +392,10 @@ CreateListeningSocket(int *         const socketP,
     
     rc = socket(AF_INET, SOCK_STREAM, 0);
     if (rc < 0)
-        asprintfN(errorP,
-                  "Unable to create socket.  "
-                  "socket() failed with errno %d (%s)",
-                  errno, strerror(errno));
+        pm_asprintf(errorP,
+                    "Unable to create socket.  "
+                    "socket() failed with errno %d (%s)",
+                    errno, strerror(errno));
     else {
         int const socketFd = rc;
 
@@ -414,9 +414,9 @@ CreateListeningSocket(int *         const socketP,
             */
             rc = listen(socketFd, SOMAXCONN);
             if (rc != 0)
-                asprintfN(errorP, "Unable to listen on TCP socket.  "
-                          "listen() fails with errno %d (%s)", 
-                          errno, strerror(errno));
+                pm_asprintf(errorP, "Unable to listen on TCP socket.  "
+                            "listen() fails with errno %d (%s)", 
+                            errno, strerror(errno));
         }
         if (*errorP)
             close(socketFd);
@@ -443,8 +443,8 @@ AcceptConnection(int           const listenSocketFd,
     rc = accept(listenSocketFd, &otherSocket, &otherSize);
 
     if (rc < 0)
-        asprintfN(errorP, "accept() failed with errno %d (%s).  ",
-                  errno, strerror(errno));
+        pm_asprintf(errorP, "accept() failed with errno %d (%s).  ",
+                    errno, strerror(errno));
     else {
         *connectSocketFdP = rc;
         *errorP = NULL;
diff --git a/converter/ppm/ppmtompeg/rate.c b/converter/ppm/ppmtompeg/rate.c
index 1a44cb95..c775e055 100644
--- a/converter/ppm/ppmtompeg/rate.c
+++ b/converter/ppm/ppmtompeg/rate.c
@@ -204,13 +204,13 @@ extern int framePatternLen;
  * INTERNAL PROCEDURE prototypes *
  *===============================*/
 
-int initGOPRateControl _ANSI_ARGS_((void));
-int determineMBCount _ANSI_ARGS_((void));
-void checkBufferFullness _ANSI_ARGS_((int count));
-void checkSpatialActivity _ANSI_ARGS_((Block blk0, Block blk1, Block blk2, Block blk3));
-void incNumBlocks _ANSI_ARGS_((int num));
-void calculateVBVDelay _ANSI_ARGS_((int num));
-int BlockExperiments  _ANSI_ARGS_((int16 *OrigBlock, int16 *NewBlock, int control));
+int initGOPRateControl (void);
+int determineMBCount (void);
+void checkBufferFullness (int count);
+void checkSpatialActivity (Block blk0, Block blk1, Block blk2, Block blk3);
+void incNumBlocks (int num);
+void calculateVBVDelay (int num);
+int BlockExperiments  (int16 *OrigBlock, int16 *NewBlock, int control);
      
      
 
@@ -236,7 +236,7 @@ analyzePattern(const char *  const framePattern,
         case 'p': ++*gop_pP; break;
         case 'b': ++*gop_bP; break;
         default:
-            asprintfN(errorP, "Bad pattern - not composed of i, p, and b");
+            pm_asprintf(errorP, "Bad pattern - not composed of i, p, and b");
         }
     }
     assert(*gop_xP == *gop_iP + *gop_pP + *gop_bP);
@@ -285,7 +285,7 @@ initRateControl(bool const wantUnderflowWarning,
     if (error) {
         pm_message("Unable to set up rate control.  Switching to variable.  "
                    "%s", error);
-        strfree(error);
+        pm_strfree(error);
         RateControlMode = VARIABLE_RATE;
         return -1;
     }
@@ -595,7 +595,7 @@ updateRateControl(int const type) {
  * MB_RateOut
  *
  *      Prints out sampling of MB rate control data.  Every "nth" block
- *	stats are printed, with "n" controled by global RC_MB_SAMPLE_RATE
+ *	stats are printed, with "n" controlled by global RC_MB_SAMPLE_RATE
  *	(NB. "skipped" blocks do not go through this function and thus do not
  *		show up in the sample )
  *
diff --git a/converter/ppm/ppmtompeg/readframe.c b/converter/ppm/ppmtompeg/readframe.c
index d1423c1f..23752706 100644
--- a/converter/ppm/ppmtompeg/readframe.c
+++ b/converter/ppm/ppmtompeg/readframe.c
@@ -67,9 +67,6 @@ struct YuvLine {
  * Global VARIABLES *
  *==================*/
 
-extern boolean GammaCorrection;
-extern float GammaValue;
-extern int outputWidth,outputHeight;
 boolean resizeFrame;
 const char *CurrFile;
 
@@ -77,19 +74,19 @@ const char *CurrFile;
  * INTERNAL PROCEDURE prototypes *
  *===============================*/
 
-static void ReadEYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer,
-                 int width, int height));
-static void ReadAYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer,
-                 int width, int height));
-static void SeparateLine _ANSI_ARGS_((FILE *fpointer, struct YuvLine *lineptr,
-                     int width));
-static void ReadY _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer,
-                 int width, int height));
-static void ReadSub4 _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer,
-                  int width, int height));
-static void DoGamma  _ANSI_ARGS_((MpegFrame *mf, int width, int height));
+static void ReadEYUV (MpegFrame * mf, FILE *fpointer,
+                 int width, int height);
+static void ReadAYUV (MpegFrame * mf, FILE *fpointer,
+                 int width, int height);
+static void SeparateLine (FILE *fpointer, struct YuvLine *lineptr,
+                     int width);
+static void ReadY (MpegFrame * mf, FILE *fpointer,
+                 int width, int height);
+static void ReadSub4 (MpegFrame * mf, FILE *fpointer,
+                  int width, int height);
+static void DoGamma  (MpegFrame *mf, int width, int height);
 
-static void DoKillDim _ANSI_ARGS_((MpegFrame *mf, int w, int h));
+static void DoKillDim (MpegFrame *mf, int w, int h);
 
 #define safe_fread(ptr,sz,len,fileptr)                           \
     if ((safe_read_count=fread(ptr,sz,len,fileptr))!=sz*len) {   \
@@ -155,7 +152,7 @@ openFile(struct inputSource * const inputSourceP,
         
         GetNthInputFileName(inputSourceP, frameNumber, &fileName);
         
-        asprintfN(&fullFileName, "%s/%s", currentPath, fileName);
+        pm_asprintf(&fullFileName, "%s/%s", currentPath, fileName);
         
         CurrFile = fullFileName;
         
@@ -207,8 +204,8 @@ openFile(struct inputSource * const inputSourceP,
             if (baseFormat == JMOVIE_FILE_TYPE)
                 unlink(fullFileName);
         }
-        strfree(fullFileName);
-        strfree(fileName);
+        pm_strfree(fullFileName);
+        pm_strfree(fileName);
     }
 }
 
@@ -377,10 +374,10 @@ ReadFrame(MpegFrame *          const frameP,
 void
 SetFileType(const char * const conversion)
 {
-    if ( strcmp(conversion, "*") == 0 ) {
-    fileType = BASE_FILE_TYPE;
+    if (streq(conversion, "*")) {
+        fileType = BASE_FILE_TYPE;
     } else {
-    fileType = ANY_FILE_TYPE;
+        fileType = ANY_FILE_TYPE;
     }
 }
 
@@ -399,23 +396,23 @@ SetFileType(const char * const conversion)
 void
 SetFileFormat(const char * const format)
 {
-    if ( strcmp(format, "PPM") == 0 ) {
-    baseFormat = PNM_FILE_TYPE;
-    } else if ( strcmp(format, "YUV") == 0 ) {
-    baseFormat = YUV_FILE_TYPE;
-    } else if ( strcmp(format, "Y") == 0 ) {
-    baseFormat = Y_FILE_TYPE;
-    } else if ( strcmp(format, "PNM") == 0 ) {
-    baseFormat = PNM_FILE_TYPE;
-    } else if (( strcmp(format, "JPEG") == 0 ) || ( strcmp(format, "JPG") == 0 )) {
-    baseFormat = JPEG_FILE_TYPE;
-    } else if ( strcmp(format, "JMOVIE") == 0 ) {
-    baseFormat = JMOVIE_FILE_TYPE;
-    } else if ( strcmp(format, "SUB4") == 0 ) {
-    baseFormat = SUB4_FILE_TYPE;
+    if (streq(format, "PPM")) {
+        baseFormat = PNM_FILE_TYPE;
+    } else if (streq(format, "YUV")) {
+        baseFormat = YUV_FILE_TYPE;
+    } else if (streq(format, "Y")) {
+        baseFormat = Y_FILE_TYPE;
+    } else if (streq(format, "PNM")) {
+        baseFormat = PNM_FILE_TYPE;
+    } else if (streq(format, "JPEG") || streq(format, "JPG")) {
+        baseFormat = JPEG_FILE_TYPE;
+    } else if (streq(format, "JMOVIE")) {
+        baseFormat = JMOVIE_FILE_TYPE;
+    } else if (streq(format, "SUB4")) {
+        baseFormat = SUB4_FILE_TYPE;
     } else {
-    fprintf(stderr, "ERROR:  Invalid file format:  %s\n", format);
-    exit(1);
+        fprintf(stderr, "ERROR:  Invalid file format:  %s\n", format);
+        exit(1);
     }
 }
 
@@ -435,9 +432,9 @@ ReadIOConvert(struct inputSource * const inputSourceP,
 
     GetNthInputFileName(inputSourceP, frameNumber, &fileName);
 
-    asprintfN(&fullFileName, "%s/%s", currentPath, fileName);
+    pm_asprintf(&fullFileName, "%s/%s", currentPath, fileName);
 
-    if ( strcmp(ioConversion, "*") == 0 ) {
+    if (streq(ioConversion, "*")) {
         char buff[1024];
         ifp = fopen(fullFileName, "rb");
         sprintf(buff,"fopen \"%s\"",fullFileName);
@@ -483,8 +480,8 @@ ReadIOConvert(struct inputSource * const inputSourceP,
         exit(1);
     }
 
-    strfree(fullFileName);
-    strfree(fileName);
+    pm_strfree(fullFileName);
+    pm_strfree(fileName);
 
     return ifp;
 }
@@ -828,7 +825,7 @@ MpegFrame *mf;
 int w,h;
 {
   static int GammaVal[256];
-  static boolean init_done=FALSE;
+  static bool init_done=FALSE;
   int i,j;
 
   if (!init_done) {
@@ -882,7 +879,7 @@ DoKillDim(mf, w, h)
 MpegFrame *mf;
 int w,h;
 {
-  static boolean init_done=FALSE;
+  static bool init_done=FALSE;
   static unsigned char mapper[256];
   register int i,j;
   double slope, intercept;
diff --git a/converter/ppm/ppmtompeg/rgbtoycc.c b/converter/ppm/ppmtompeg/rgbtoycc.c
index 766b8902..2dd1899a 100644
--- a/converter/ppm/ppmtompeg/rgbtoycc.c
+++ b/converter/ppm/ppmtompeg/rgbtoycc.c
@@ -84,11 +84,11 @@ compute_mult_tables(const pixval maxval) {
         if (mult299 == NULL || mult587 == NULL || mult114 == NULL ||
             mult16874 == NULL || mult33126 == NULL || mult5 == NULL ||
             mult41869 == NULL || mult08131 == NULL) 
-            pm_error("Unable to allocate storage for arithmetic tables.\n"
+            pm_error("Unable to allocate storage for arithmetic tables.  "
                      "We need %d bytes, which is the maxval of the input "
-                     "image, plus 1,\n"
+                     "image, plus 1, "
                      "times the storage size of a floating point value.", 
-                     8 * (table_maxval+1)*sizeof(float));
+                     (unsigned)(8 * (table_maxval+1)*sizeof(float)));
 
         {
             int index;
diff --git a/converter/ppm/ppmtompeg/specifics.c b/converter/ppm/ppmtompeg/specifics.c
index 38e8fc43..fb5e3649 100644
--- a/converter/ppm/ppmtompeg/specifics.c
+++ b/converter/ppm/ppmtompeg/specifics.c
@@ -46,28 +46,26 @@
 #include <stdio.h>
 #include <string.h>
 #include "prototypes.h"
+#include "param.h"
 
 /*==================*
  * GLOBAL VARIABLES *
  *==================*/
 
-extern boolean specificsOn;
-extern char specificsFile[];
-extern char specificsDefines[];
 FrameSpecList *fsl;
 
 /*=====================*
  * Internal procedures *
  *=====================*/
 
-void Parse_Specifics_File _ANSI_ARGS_((FILE *fp));
-void Parse_Specifics_File_v1 _ANSI_ARGS_((FILE *fp));
-void Parse_Specifics_File_v2 _ANSI_ARGS_((FILE *fp));
-FrameSpecList *MakeFslEntry _ANSI_ARGS_((void));
-void AddSlc _ANSI_ARGS_((FrameSpecList *c,int snum, int qs));
-Block_Specifics *AddBs _ANSI_ARGS_((FrameSpecList *c,int bnum, 
-				    boolean rel, int qs));
-FrameSpecList *MakeFslEntry _ANSI_ARGS_((void));
+void Parse_Specifics_File (FILE *fp);
+void Parse_Specifics_File_v1 (FILE *fp);
+void Parse_Specifics_File_v2 (FILE *fp);
+FrameSpecList *MakeFslEntry (void);
+void AddSlc (FrameSpecList *c,int snum, int qs);
+Block_Specifics *AddBs (FrameSpecList *c,int bnum, 
+				    boolean rel, int qs);
+FrameSpecList *MakeFslEntry (void);
 #define my_upper(c) (((c>='a') && (c<='z')) ? (c-'a'+'A') : c)
 #define CvtType(x) ReallyCvt(my_upper(x))
 #define ReallyCvt(x) (x=='I' ? 1 : (x=='P')?2: ((x=='B')?3:-1))
@@ -91,7 +89,7 @@ version N
   Specify the version of the specifics file format (this is 1)
 frame N T M
   Sets frame number N to type T and Qscale M
-  (type T is I,B,P,other, other means unspec.  I recomend - )
+  (type T is I,B,P,other, other means unspec.  I recommend - )
 slice M Q
   Sets slice M (in frame N as defined by a previous frame command)
   to qscale Q
@@ -559,7 +557,7 @@ int start_qs;
       } else {
 	/* if not next, check from the start.
 	   (this allows people to put frames out of order,even
-	   though the spec doesnt allow it.) */
+	   though the spec doesn't allow it.) */
 	tmp = fsl;
 	found_it = FALSE;
 	while (tmp != (FrameSpecList *) NULL) {
diff --git a/converter/ppm/ppmtopcx.c b/converter/ppm/ppmtopcx.c
index edc44149..fa68edc5 100644
--- a/converter/ppm/ppmtopcx.c
+++ b/converter/ppm/ppmtopcx.c
@@ -12,6 +12,10 @@
 **
 ** 11/Dec/94: first version
 ** 12/Dec/94: added handling of "packed" format (16 colors or less)
+** 
+** ZSoft PCX File Format Technical Reference Manual
+** http://bespin.org/~qz/pc-gpe/pcx.txt
+** http://web.archive.org/web/20100206055706/http://www.qzx.com/pc-gpe/pcx.txt
 */
 #include <assert.h>
 
@@ -79,7 +83,7 @@ parseCommandLine(int argc, char ** argv,
    was passed to us as the argv array.  We also trash *argv.
 -----------------------------------------------------------------------------*/
     optEntry *option_def;
-        /* Instructions to optParseOptions3 on how to parse our options.
+        /* Instructions to pm_optParseOptions3 on how to parse our options.
          */
     optStruct3 opt;
 
@@ -111,7 +115,7 @@ parseCommandLine(int argc, char ** argv,
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
 
-    optParseOptions3( &argc, argv, opt, sizeof(opt), 0 );
+    pm_optParseOptions3( &argc, argv, opt, sizeof(opt), 0 );
         /* Uses and sets argc, argv, and some of *cmdline_p and others. */
 
     if (!xposSpec)
@@ -158,6 +162,8 @@ parseCommandLine(int argc, char ** argv,
         pm_error("Program takes at most one argument "
                  "(input file specification).  You specified %d",
                  argc-1);
+
+    free(option_def);
 }
 
 
@@ -632,6 +638,16 @@ generateStandardPalette(struct pcxCmapEntry ** const pcxcmapP,
         putPcxColorInHash(cht, pcxColor, colorIndex, maxval);
     }
 
+    /* Set remaining slots in palette to black.  The values are not
+       meaningful, but this suppresses a Valgrind warning about our writing
+       undefined values to the file and makes our output constant with input.
+    */
+    for ( ; colorIndex < MAXCOLORS; ++colorIndex) {
+        pcxcmap[colorIndex].r = 0;
+        pcxcmap[colorIndex].g = 0;
+        pcxcmap[colorIndex].b = 0;
+    }
+
     *chtP = cht;
     *colorsP = stdPaletteSize;
 }
diff --git a/converter/ppm/ppmtopict.c b/converter/ppm/ppmtopict.c
index 1b9f2d5c..36464b6c 100644
--- a/converter/ppm/ppmtopict.c
+++ b/converter/ppm/ppmtopict.c
@@ -11,464 +11,462 @@
 ** implied warranty.
 */
 
+#include <assert.h>
+#include "pm_c_util.h"
+#include "pm.h"
 #include "ppm.h"
 
-#define HEADER_SIZE		512
+#define HEADER_SIZE     512
 
-#define	RUN_THRESH		3
-#define	MAX_RUN			128		/* 0xff = 2, 0xfe = 3, etc */
-#define	MAX_COUNT		128		/* 0x00 = 1, 0x01 = 2, etc */
+#define RUN_THRESH      3
+#define MAX_RUN         128     /* 0xff = 2, 0xfe = 3, etc */
+#define MAX_COUNT       128     /* 0x00 = 1, 0x01 = 2, etc */
 
 /* Opcodes */
-#define PICT_NOP		0x00
-#define PICT_clipRgn		0x01
-#define PICT_bkPat		0x02
-#define PICT_txFont		0x03
-#define PICT_txFace		0x04
-#define PICT_txMode		0x05
-#define PICT_spExtra		0x06
-#define PICT_pnSize		0x07
-#define PICT_pnMode		0x08
-#define PICT_pnPat		0x09
-#define PICT_thePat		0x0A
-#define PICT_ovSize		0x0B
-#define PICT_origin		0x0C
-#define PICT_txSize		0x0D
-#define PICT_fgColor		0x0E
-#define PICT_bkColor		0x0F
-#define PICT_txRatio		0x10
-#define PICT_picVersion		0x11
-#define	PICT_blPixPat		0x12
-#define	PICT_pnPixPat		0x13
-#define	PICT_fillPixPat		0x14
-#define	PICT_pnLocHFrac		0x15
-#define	PICT_chExtra		0x16
-#define	PICT_rgbFgCol		0x1A
-#define	PICT_rgbBkCol		0x1B
-#define	PICT_hiliteMode		0x1C
-#define	PICT_hiliteColor	0x1D
-#define	PICT_defHilite		0x1E
-#define	PICT_opColor		0x1F
-#define PICT_line		0x20
-#define PICT_line_from		0x21
-#define PICT_short_line		0x22
-#define PICT_short_line_from	0x23
-#define PICT_long_text		0x28
-#define PICT_DH_text		0x29
-#define PICT_DV_text		0x2A
-#define PICT_DHDV_text		0x2B
-#define PICT_frameRect		0x30
-#define PICT_paintRect		0x31
-#define PICT_eraseRect		0x32
-#define PICT_invertRect		0x33
-#define PICT_fillRect		0x34
-#define PICT_frameSameRect	0x38
-#define PICT_paintSameRect	0x39
-#define PICT_eraseSameRect	0x3A
-#define PICT_invertSameRect	0x3B
-#define PICT_fillSameRect	0x3C
-#define PICT_frameRRect		0x40
-#define PICT_paintRRect		0x41
-#define PICT_eraseRRect		0x42
-#define PICT_invertRRect	0x43
-#define PICT_fillRRect		0x44
-#define PICT_frameSameRRect	0x48
-#define PICT_paintSameRRect	0x49
-#define PICT_eraseSameRRect	0x4A
-#define PICT_invertSameRRect	0x4B
-#define PICT_fillSameRRect	0x4C
-#define PICT_frameOval		0x50
-#define PICT_paintOval		0x51
-#define PICT_eraseOval		0x52
-#define PICT_invertOval		0x53
-#define PICT_fillOval		0x54
-#define PICT_frameSameOval	0x58
-#define PICT_paintSameOval	0x59
-#define PICT_eraseSameOval	0x5A
-#define PICT_invertSameOval	0x5B
-#define PICT_fillSameOval	0x5C
-#define PICT_frameArc		0x60
-#define PICT_paintArc		0x61
-#define PICT_eraseArc		0x62
-#define PICT_invertArc		0x63
-#define PICT_fillArc		0x64
-#define PICT_frameSameArc	0x68
-#define PICT_paintSameArc	0x69
-#define PICT_eraseSameArc	0x6A
-#define PICT_invertSameArc	0x6B
-#define PICT_fillSameArc	0x6C
-#define PICT_framePoly		0x70
-#define PICT_paintPoly		0x71
-#define PICT_erasePoly		0x72
-#define PICT_invertPoly		0x73
-#define PICT_fillPoly		0x74
-#define PICT_frameSamePoly	0x78
-#define PICT_paintSamePoly	0x79
-#define PICT_eraseSamePoly	0x7A
-#define PICT_invertSamePoly	0x7B
-#define PICT_fillSamePoly	0x7C
-#define PICT_frameRgn		0x80
-#define PICT_paintRgn		0x81
-#define PICT_eraseRgn		0x82
-#define PICT_invertRgn		0x83
-#define PICT_fillRgn		0x84
-#define PICT_frameSameRgn	0x88
-#define PICT_paintSameRgn	0x89
-#define PICT_eraseSameRgn	0x8A
-#define PICT_invertSameRgn	0x8B
-#define PICT_fillSameRgn	0x8C
-#define PICT_BitsRect		0x90
-#define PICT_BitsRgn		0x91
-#define PICT_PackBitsRect	0x98
-#define PICT_PackBitsRgn	0x99
-#define PICT_shortComment	0xA0
-#define PICT_longComment	0xA1
-#define PICT_EndOfPicture	0xFF
-#define	PICT_headerOp		0x0C00
-
-static void putFill ARGS(( FILE *fd, int n ));
-static void putShort ARGS(( FILE *fd, int i ));
-static void putLong ARGS(( FILE *fd, long i ));
-static void putFixed ARGS(( FILE *fd, int in, int frac ));
-static void putRect ARGS(( FILE *fd, int x1, int x2, int y1, int y2 ));
-static int putRow ARGS(( FILE *fd, int row, int cols, pixel *rowpixels, char *packed ));
+#define PICT_NOP        0x00
+#define PICT_clipRgn        0x01
+#define PICT_bkPat      0x02
+#define PICT_txFont     0x03
+#define PICT_txFace     0x04
+#define PICT_txMode     0x05
+#define PICT_spExtra        0x06
+#define PICT_pnSize     0x07
+#define PICT_pnMode     0x08
+#define PICT_pnPat      0x09
+#define PICT_thePat     0x0A
+#define PICT_ovSize     0x0B
+#define PICT_origin     0x0C
+#define PICT_txSize     0x0D
+#define PICT_fgColor        0x0E
+#define PICT_bkColor        0x0F
+#define PICT_txRatio        0x10
+#define PICT_picVersion     0x11
+#define PICT_blPixPat       0x12
+#define PICT_pnPixPat       0x13
+#define PICT_fillPixPat     0x14
+#define PICT_pnLocHFrac     0x15
+#define PICT_chExtra        0x16
+#define PICT_rgbFgCol       0x1A
+#define PICT_rgbBkCol       0x1B
+#define PICT_hiliteMode     0x1C
+#define PICT_hiliteColor    0x1D
+#define PICT_defHilite      0x1E
+#define PICT_opColor        0x1F
+#define PICT_line       0x20
+#define PICT_line_from      0x21
+#define PICT_short_line     0x22
+#define PICT_short_line_from    0x23
+#define PICT_long_text      0x28
+#define PICT_DH_text        0x29
+#define PICT_DV_text        0x2A
+#define PICT_DHDV_text      0x2B
+#define PICT_frameRect      0x30
+#define PICT_paintRect      0x31
+#define PICT_eraseRect      0x32
+#define PICT_invertRect     0x33
+#define PICT_fillRect       0x34
+#define PICT_frameSameRect  0x38
+#define PICT_paintSameRect  0x39
+#define PICT_eraseSameRect  0x3A
+#define PICT_invertSameRect 0x3B
+#define PICT_fillSameRect   0x3C
+#define PICT_frameRRect     0x40
+#define PICT_paintRRect     0x41
+#define PICT_eraseRRect     0x42
+#define PICT_invertRRect    0x43
+#define PICT_fillRRect      0x44
+#define PICT_frameSameRRect 0x48
+#define PICT_paintSameRRect 0x49
+#define PICT_eraseSameRRect 0x4A
+#define PICT_invertSameRRect    0x4B
+#define PICT_fillSameRRect  0x4C
+#define PICT_frameOval      0x50
+#define PICT_paintOval      0x51
+#define PICT_eraseOval      0x52
+#define PICT_invertOval     0x53
+#define PICT_fillOval       0x54
+#define PICT_frameSameOval  0x58
+#define PICT_paintSameOval  0x59
+#define PICT_eraseSameOval  0x5A
+#define PICT_invertSameOval 0x5B
+#define PICT_fillSameOval   0x5C
+#define PICT_frameArc       0x60
+#define PICT_paintArc       0x61
+#define PICT_eraseArc       0x62
+#define PICT_invertArc      0x63
+#define PICT_fillArc        0x64
+#define PICT_frameSameArc   0x68
+#define PICT_paintSameArc   0x69
+#define PICT_eraseSameArc   0x6A
+#define PICT_invertSameArc  0x6B
+#define PICT_fillSameArc    0x6C
+#define PICT_framePoly      0x70
+#define PICT_paintPoly      0x71
+#define PICT_erasePoly      0x72
+#define PICT_invertPoly     0x73
+#define PICT_fillPoly       0x74
+#define PICT_frameSamePoly  0x78
+#define PICT_paintSamePoly  0x79
+#define PICT_eraseSamePoly  0x7A
+#define PICT_invertSamePoly 0x7B
+#define PICT_fillSamePoly   0x7C
+#define PICT_frameRgn       0x80
+#define PICT_paintRgn       0x81
+#define PICT_eraseRgn       0x82
+#define PICT_invertRgn      0x83
+#define PICT_fillRgn        0x84
+#define PICT_frameSameRgn   0x88
+#define PICT_paintSameRgn   0x89
+#define PICT_eraseSameRgn   0x8A
+#define PICT_invertSameRgn  0x8B
+#define PICT_fillSameRgn    0x8C
+#define PICT_BitsRect       0x90
+#define PICT_BitsRgn        0x91
+#define PICT_PackBitsRect   0x98
+#define PICT_PackBitsRgn    0x99
+#define PICT_shortComment   0xA0
+#define PICT_longComment    0xA1
+#define PICT_EndOfPicture   0xFF
+#define PICT_headerOp       0x0C00
 
 #define MAXCOLORS 256
 static colorhash_table cht;
 
-int
-main(argc, argv)
-int argc;
-char *argv[];
-{
-	FILE *ifp;
-	int argn, rows, cols, colors, i, row, oc;
-	register pixel **pixels;
-	char *packed;
-	pixval maxval;
-	long lmaxval, rval, gval, bval;
-	colorhist_vector chv;
-
-
-	ppm_init( &argc, argv );
-
-	argn = 1;
-	if (argn < argc)
-	{
-		ifp = pm_openr(argv[1]);
-		argn++;
-	}
-	else
-		ifp = stdin;
-	if (argn != argc)
-		pm_usage("[ppmfile]");
-
-	pixels = ppm_readppm(ifp, &cols, &rows, &maxval);
-	if (cols < 8)
-		pm_error("ppm input too narrow, must be >= 8 pixels wide" );
-	lmaxval = (long)maxval;
-	pm_close(ifp);
-
-	/* Figure out the colormap. */
-	pm_message("computing colormap..." );
-	chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &colors);
-	if (chv == (colorhist_vector) 0)
-		pm_error("too many colors - try doing a 'pnmquant %d'", MAXCOLORS);
-	pm_message("%d colors found", colors );
-
-	/* Make a hash table for fast color lookup. */
-	cht = ppm_colorhisttocolorhash(chv, colors);
-
-	/* write the header */
-	putFill(stdout, HEADER_SIZE);
-
-	/* write picSize and picFrame */
-	putShort(stdout, 0);
-	putRect(stdout, 0, 0, rows, cols);
-
-	/* write version op and version */
-	putShort(stdout, PICT_picVersion);
-	putShort(stdout, 0x02FF);
-	putShort(stdout, PICT_headerOp);
-	putLong(stdout, -1L);
-	putFixed(stdout, 0, 0);
-	putFixed(stdout, 0, 0);
-	putFixed(stdout, cols, 0);
-	putFixed(stdout, rows, 0);
-	putFill(stdout, 4);
-
-	/* seems to be needed by many PICT2 programs */
-	putShort(stdout, PICT_clipRgn);
-	putShort(stdout, 10);
-	putRect(stdout, 0, 0, rows, cols);
-
-	/* write picture */
-	putShort(stdout, PICT_PackBitsRect);
-	putShort(stdout, cols | 0x8000);
-	putRect(stdout, 0, 0, rows, cols);
-	putShort(stdout, 0);	/* pmVersion */
-	putShort(stdout, 0);	/* packType */
-	putLong(stdout, 0L);	/* packSize */
-	putFixed(stdout, 72, 0);	/* hRes */
-	putFixed(stdout, 72, 0);	/* vRes */
-	putShort(stdout, 0);	/* pixelType */
-	putShort(stdout, 8);	/* pixelSize */
-	putShort(stdout, 1);	/* cmpCount */
-	putShort(stdout, 8);	/* cmpSize */
-	putLong(stdout, 0L);	/* planeBytes */
-	putLong(stdout, 0L);	/* pmTable */
-	putLong(stdout, 0L);	/* pmReserved */
-	putLong(stdout, 0L);	/* ctSeed */
-	putShort(stdout, 0);	/* ctFlags */
-	putShort(stdout, colors-1);	/* ctSize */
-
-	/* Write out the colormap. */
-	for (i = 0; i < colors; i++)
-	{
-		putShort(stdout, i);
-		rval = PPM_GETR(chv[i].color);
-		gval = PPM_GETG(chv[i].color);
-		bval = PPM_GETB(chv[i].color);
-		if (lmaxval != 65535L)
-		{
-			rval = rval * 65535L / lmaxval;
-			gval = gval * 65535L / lmaxval;
-			bval = bval * 65535L / lmaxval;
-		}
-		putShort(stdout, (short)rval);
-		putShort(stdout, (short)gval);
-		putShort(stdout, (short)bval);
-	}
-
-	putRect(stdout, 0, 0, rows, cols);	/* srcRect */
-	putRect(stdout, 0, 0, rows, cols);	/* dstRect */
-	putShort(stdout, 0);			/* mode */
-
-	/* Finally, write out the data. */
-	packed = (char*) malloc((unsigned)(cols+cols/MAX_COUNT+1));
-	oc = 0;
-	for (row = 0; row < rows; row++)
-		oc += putRow(stdout, row, cols, pixels[row], packed);
-
-	/* if we wrote an odd number of pixdata bytes, pad */
-	if (oc & 1)
-		(void) putc(0, stdout);
-	putShort(stdout, PICT_EndOfPicture);
-
-	lmaxval = ftell(stdout) - HEADER_SIZE;
-	if (fseek(stdout, (long)HEADER_SIZE, 0) >= 0)
-		putShort(stdout, (short)(lmaxval & 0xffff));
-
-	exit(0);
-}
+
 
 static void
-putFill(fd, n)
-FILE *fd;
-int n;
-{
-	register int i;
-
-	for (i = 0; i < n; i++)
-		(void) putc(0, fd);
+putFill(FILE *       const ifP,
+        unsigned int const n) {
+
+    unsigned int i;
+
+    for (i = 0; i < n; ++i)
+        putc(0, ifP);
 }
 
+
+
 static void
-putShort(fd, i)
-FILE *fd;
-int i;
-{
-	(void) putc((i >> 8) & 0xff, fd);
-	(void) putc(i & 0xff, fd);
+putShort(FILE * const ifP,
+         int    const i) {
+    putc((i >> 8) & 0xff, ifP);
+    putc(i & 0xff, ifP);
 }
 
+
+
 static void
-putLong( FILE *fd, long i )
-{
-	(void) putc((int)((i >> 24) & 0xff), fd);
-	(void) putc(((int)(i >> 16) & 0xff), fd);
-	(void) putc(((int)(i >> 8) & 0xff), fd);
-	(void) putc((int)(i & 0xff), fd);
+putLong(FILE * const ifP,
+        long   const i) {
+    putc((int)((i >> 24) & 0xff), ifP);
+    putc(((int)(i >> 16) & 0xff), ifP);
+    putc(((int)(i >> 8) & 0xff), ifP);
+    putc((int)(i & 0xff), ifP);
 }
 
+
+
 static void
-putFixed(fd, in, frac)
-FILE *fd;
-int in, frac;
-{
-	putShort(fd, in);
-	putShort(fd, frac);
+putFixed(FILE * const ifP,
+         int    const in,
+         int    const frac) {
+    putShort(ifP, in);
+    putShort(ifP, frac);
 }
 
+
+
 static void
-putRect(fd, x1, x2, y1, y2)
-FILE *fd;
-int x1, x2, y1, y2;
-{
-	putShort(fd, x1);
-	putShort(fd, x2);
-	putShort(fd, y1);
-	putShort(fd, y2);
+putRect(FILE * const ifP,
+        int    const x1,
+        int    const x2,
+        int    const y1,
+        int    const y2) {
+    putShort(ifP, x1);
+    putShort(ifP, x2);
+    putShort(ifP, y1);
+    putShort(ifP, y2);
 }
 
-#define	RUNLENGTH
-#ifdef	RUNLENGTH
-
-#define		runtochar(c)	(257-(c))
-#define		counttochar(c)	((c)-1)
-
-static int
-putRow(fd, row, cols, rowpixels, packed)
-FILE *fd;
-int row, cols;
-pixel *rowpixels;
-char *packed;
-{
-	register int i;
-	int packcols, count, run, rep, oc;
-	register pixel *pP;
-	pixel lastp;
-	register char *p;
-
-	run = count = 0;
-	for (cols--, i = cols, pP = rowpixels + cols, p = packed, lastp = *pP;
-		i >= 0; i--, lastp = *pP, pP--)
-	{
-		if (PPM_EQUAL(lastp, *pP))
-			run++;
-		else if (run < RUN_THRESH)
-		{
-			while (run > 0)
-			{
-				*p++ = ppm_lookupcolor(cht, &lastp);
-				run--;
-				count++;
-				if (count == MAX_COUNT)
-				{
-					*p++ = counttochar(MAX_COUNT);
-					count -= MAX_COUNT;
-				}
-			}
-			run = 1;
-		}
-		else
-		{
-			if (count > 0)
-				*p++ = counttochar(count);
-			count = 0;
-			while (run > 0)
-			{
-				rep = run > MAX_RUN ? MAX_RUN : run;
-				*p++ = ppm_lookupcolor(cht, &lastp);
-				*p++ = runtochar(rep);
-				run -= rep;
-			}
-			run = 1;
-		}
-	}
-	if (run < RUN_THRESH)
-	{
-		while (run > 0)
-		{
-			*p++ = ppm_lookupcolor(cht, &lastp);
-			run--;
-			count++;
-			if (count == MAX_COUNT)
-			{
-				*p++ = counttochar(MAX_COUNT);
-				count -= MAX_COUNT;
-			}
-		}
-	}
-	else
-	{
-		if (count > 0)
-			*p++ = counttochar(count);
-		count = 0;
-		while (run > 0)
-		{
-			rep = run > MAX_RUN ? MAX_RUN : run;
-			*p++ = ppm_lookupcolor(cht, &lastp);
-			*p++ = runtochar(rep);
-				run -= rep;
-		}
-		run = 1;
-	}
-	if (count > 0)
-		*p++ = counttochar(count);
-
-	packcols = p - packed;		/* how many did we write? */
-	if (cols > 200)
-	{
-		putShort(fd, packcols);
-		oc = packcols + 2;
-	}
-	else
-	{
-		(void) putc(packcols, fd);
-		oc = packcols + 1;
-	}
-
-	/* now write out the packed row */
-	while(p != packed)
-	{
-		--p;
-		(void) putc(*p, fd);
-	}
-
-	return (oc);
+
+
+#define     runtochar(c)    (257-(c))
+#define     counttochar(c)  ((c)-1)
+
+static void
+putRow(FILE *         const ofP,
+       unsigned int   const row,
+       unsigned int   const cols,
+       pixel *        const rowpixels,
+       char *         const outBuf,
+       unsigned int * const outCountP) {
+/*----------------------------------------------------------------------------
+   Write the row rowpixels[], which is 'cols' pixels wide and is row 'row' of
+   the image, to file *ofP in PICT format.
+
+   Return as *outCountP the number of bytes we write to *ofP.
+
+   Use buffer 'outBuf'.
+-----------------------------------------------------------------------------*/
+    unsigned int i;
+    unsigned int count;
+    unsigned int run;
+    unsigned int rep;
+    unsigned int outCount;
+    pixel lastpix;
+    char * p;
+
+    run = 0;
+    count = 0;
+    lastpix = rowpixels[cols-1];
+
+    for (i = 0, p = &outBuf[0]; i < cols; ++i) {
+
+        pixel const pix = rowpixels[cols - 1 - i];
+
+        if (PPM_EQUAL(lastpix, pix))
+            ++run;
+        else if (run < RUN_THRESH) {
+            while (run > 0) {
+                *p++ = ppm_lookupcolor(cht, &lastpix);
+                --run;
+                ++count;
+                if (count == MAX_COUNT) {
+                    *p++ = counttochar(MAX_COUNT);
+                    count -= MAX_COUNT;
+                }
+            }
+            run = 1;
+        } else {
+            if (count > 0)
+                *p++ = counttochar(count);
+            count = 0;
+            while (run > 0) {
+                rep = MIN(run, MAX_RUN);
+                *p++ = ppm_lookupcolor(cht, &lastpix);
+                *p++ = runtochar(rep);
+                assert(run >= rep);
+                run -= rep;
+            }
+            run = 1;
+        }
+        lastpix = pix;
+    }
+    if (run < RUN_THRESH) {
+        while (run > 0) {
+            *p++ = ppm_lookupcolor(cht, &lastpix);
+            --run;
+            ++count;
+            if (count == MAX_COUNT) {
+                *p++ = counttochar(MAX_COUNT);
+                count -= MAX_COUNT;
+            }
+        }
+    } else {
+        if (count > 0)
+            *p++ = counttochar(count);
+        count = 0;
+        while (run > 0) {
+            rep = MIN(run, MAX_RUN);
+            *p++ = ppm_lookupcolor(cht, &lastpix);
+            *p++ = runtochar(rep);
+            assert(run >= rep);
+            run -= rep;
+        }
+        run = 1;
+    }
+    if (count > 0)
+        *p++ = counttochar(count);
+
+    {
+        unsigned int const packcols = p - outBuf;
+            /* How many we wrote */
+        if (cols-1 > 200) {
+            putShort(ofP, packcols);
+            outCount = packcols + 2;
+        } else {
+            putc(packcols, ofP);
+            outCount = packcols + 1;
+        }
+    }
+    /* now write out the packed row */
+    while (p != outBuf) {
+        --p;
+        putc(*p, ofP);
+    }
+    *outCountP = outCount;
 }
 
-#else	/* RUNLENGTH */
+
+
+# if 0
 
 /* real dumb putRow with no compression */
-static int
-putRow(fd, row, cols, rowpixels, packed)
-FILE *fd;
-int row, cols;
-pixel *rowpixels;
-char *packed;
-{
-	register int i, j, bc, oc;
-	register pixel *pP;
-
-#if notdef
-	bzero(aux, cols); /* aux?? */
-#endif /*notdef*/
-	bc = cols + (cols + MAX_COUNT - 1) / MAX_COUNT;
-	if (bc > 200)
-	{
-		putShort(fd, bc);
-		oc = bc + 2;
-	}
-	else
-	{
-		(void) putc(bc, fd);
-		oc = bc + 1;
-	}
-	for (i = 0, pP = rowpixels; i < cols;)
-	{
-		if (cols - i > MAX_COUNT)
-		{
-			(void) putc(MAX_COUNT - 1, fd);
-			for (j = 0; j < MAX_COUNT; j++)
-			{
-				(void) putc(ppm_lookupcolor(cht, pP), fd);
-				pP++;
-			}
-			i += MAX_COUNT;
-		}
-		else
-		{
-			(void) putc(cols - i - 1, fd);
-			for (j = 0; j < cols - i; j++)
-			{
-				(void) putc(ppm_lookupcolor(cht, pP), fd);
-				pP++;
-			}
-			i = cols;
-		}
-	}
-	return (oc);
+static void
+putRow(FILE *         const ifP,
+       unsigned int   const row,
+       unsigned int   const cols,
+       pixel *        const rowpixels,
+       char *         const outBuf,
+       unsigned int * const outCountP) {
+
+    unsigned int const bc = cols + (cols + MAX_COUNT - 1) / MAX_COUNT;
+
+    unsigned int i;
+
+    if (bc > 200) {
+        putShort(ifP, bc);
+        *outCountP = bc + 2;
+    }  else {
+        putc(bc, ifP);
+        *outCountP = bc + 1;
+    }
+    for (col = 0; col < cols;) {
+        if (cols - col > MAX_COUNT) {
+            unsigned int j;
+            putc(MAX_COUNT - 1, ifP);
+            for (j = 0; j < MAX_COUNT; ++j) {
+                putc(ppm_lookupcolor(cht, &rowPixels[col]), ifP);
+                ++col
+            }
+            col += MAX_COUNT;
+        } else {
+            unsigned int j;
+            putc(cols - col - 1, ifP);
+            for (j = 0; j < cols - col; ++j) {
+                putc(ppm_lookupcolor(cht, &rowPixels[col]), ifP);
+                ++pP;
+            }
+            col = cols;
+        }
+    }
+}
+#endif  /* 0 */
+
+
+
+int
+main(int argc, const char ** argv) {
+
+    FILE * ifP;
+    int nColors;
+    unsigned int oc;
+    unsigned int i;
+    int rows, cols;
+    unsigned int row;
+    pixel ** pixels;
+    char * outBuf;
+    pixval maxval;
+    long lmaxval, rval, gval, bval;
+    colorhist_vector chv;
+
+    pm_proginit(&argc, argv);
+
+    if (argc-1 > 0)
+        ifP = pm_openr(argv[1]);
+    else
+        ifP = stdin;
+    if (argc-1 > 1)
+        pm_error("Too many arguments.  The only argument is the "
+                 "input file name");
+
+    pixels = ppm_readppm(ifP, &cols, &rows, &maxval);
+    if (cols < 8)
+        pm_error("ppm input too narrow, must be >= 8 pixels wide" );
+    lmaxval = (long)maxval;
+    pm_close(ifP);
+
+    /* Figure out the colormap. */
+    pm_message("computing colormap..." );
+    chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &nColors);
+    if (chv == NULL)
+        pm_error("too many colors - try doing a 'pnmquant %u'", MAXCOLORS);
+    pm_message("%u colors found", nColors);
+
+    /* Make a hash table for fast color lookup. */
+    cht = ppm_colorhisttocolorhash(chv, nColors);
+
+    /* write the header */
+    putFill(stdout, HEADER_SIZE);
+
+    /* write picSize and picFrame */
+    putShort(stdout, 0);
+    putRect(stdout, 0, 0, rows, cols);
+
+    /* write version op and version */
+    putShort(stdout, PICT_picVersion);
+    putShort(stdout, 0x02FF);
+    putShort(stdout, PICT_headerOp);
+    putLong(stdout, -1L);
+    putFixed(stdout, 0, 0);
+    putFixed(stdout, 0, 0);
+    putFixed(stdout, cols, 0);
+    putFixed(stdout, rows, 0);
+    putFill(stdout, 4);
+
+    /* seems to be needed by many PICT2 programs */
+    putShort(stdout, PICT_clipRgn);
+    putShort(stdout, 10);
+    putRect(stdout, 0, 0, rows, cols);
+
+    /* write picture */
+    putShort(stdout, PICT_PackBitsRect);
+    putShort(stdout, cols | 0x8000);
+    putRect(stdout, 0, 0, rows, cols);
+    putShort(stdout, 0);    /* pmVersion */
+    putShort(stdout, 0);    /* packType */
+    putLong(stdout, 0L);    /* packSize */
+    putFixed(stdout, 72, 0);    /* hRes */
+    putFixed(stdout, 72, 0);    /* vRes */
+    putShort(stdout, 0);    /* pixelType */
+    putShort(stdout, 8);    /* pixelSize */
+    putShort(stdout, 1);    /* cmpCount */
+    putShort(stdout, 8);    /* cmpSize */
+    putLong(stdout, 0L);    /* planeBytes */
+    putLong(stdout, 0L);    /* pmTable */
+    putLong(stdout, 0L);    /* pmReserved */
+    putLong(stdout, 0L);    /* ctSeed */
+    putShort(stdout, 0);    /* ctFlags */
+    putShort(stdout, nColors-1); /* ctSize */
+
+    /* Write out the colormap. */
+    for (i = 0; i < nColors; ++i) {
+        putShort(stdout, i);
+        rval = PPM_GETR(chv[i].color);
+        gval = PPM_GETG(chv[i].color);
+        bval = PPM_GETB(chv[i].color);
+        if (lmaxval != 65535L) {
+            rval = rval * 65535L / lmaxval;
+            gval = gval * 65535L / lmaxval;
+            bval = bval * 65535L / lmaxval;
+        }
+        putShort(stdout, (short)rval);
+        putShort(stdout, (short)gval);
+        putShort(stdout, (short)bval);
+    }
+
+    putRect(stdout, 0, 0, rows, cols);  /* srcRect */
+    putRect(stdout, 0, 0, rows, cols);  /* dstRect */
+    putShort(stdout, 0);            /* mode */
+
+    /* Finally, write out the data. */
+    outBuf = malloc((unsigned)(cols+cols/MAX_COUNT+1));
+    for (row = 0, oc = 0; row < rows; ++row) {
+        unsigned int rowSize;
+        putRow(stdout, row, cols, pixels[row], outBuf, &rowSize);
+        oc += rowSize;
+    }
+    /* if we wrote an odd number of pixdata bytes, pad */
+    if (oc & 0x1)
+        putc(0, stdout);
+    putShort(stdout, PICT_EndOfPicture);
+
+    lmaxval = ftell(stdout) - HEADER_SIZE;
+    if (fseek(stdout, (long)HEADER_SIZE, 0) >= 0)
+        putShort(stdout, (short)(lmaxval & 0xffff));
+
+    return 0;
 }
-#endif	/* RUNLENGTH */
+
+
+
diff --git a/converter/ppm/ppmtopjxl.c b/converter/ppm/ppmtopjxl.c
index 91cd1a45..90bcef0f 100644
--- a/converter/ppm/ppmtopjxl.c
+++ b/converter/ppm/ppmtopjxl.c
@@ -12,6 +12,7 @@
  *
  */
 
+#include <assert.h>
 #include <stdio.h>
 #include <math.h>
 #include <string.h>
@@ -19,6 +20,7 @@
 #include "pm_c_util.h"
 #include "nstring.h"
 #include "ppm.h"
+#include "runlength.h"
 
 #define MAXCOLORS 1024
 
@@ -33,7 +35,7 @@ const char * const usage="[-nopack] [-gamma <n>] [-presentation] [-dark]\n\
 #define PCL_MAXHEIGHT 32767
 #define PCL_MAXVAL 255
 
-static int nopack = 0;
+static bool nopack = false;
 static int dark = 0;
 static int diffuse = 0;
 static int dither = 0;
@@ -73,16 +75,28 @@ static const struct options {
    {"-nopack",       BOOL, &nopack },
 };
 
-#define putword(w) (putchar(((w)>>8) & 255), putchar((w) & 255))
 
-static int 
-bitsperpixel(int v) {
-   int bpp = 0;
-   while (v > 0) {  /* calculate # bits for value */
-      ++bpp;
-      v>>=1;
-   }
-   return (bpp);
+
+static void
+putword(unsigned short const w) {
+    putchar((w >> 8) & 0xff);
+    putchar((w >> 0) & 0xff);
+}
+
+
+
+static unsigned int
+bitsperpixel(unsigned int v) {
+
+    unsigned int bpp;
+
+    /* calculate # bits for value */
+    
+    for (bpp = 0; v > 0; ) {
+        ++bpp;
+        v >>= 1;
+    }
+    return bpp;
 }
 
 
@@ -94,101 +108,77 @@ static char *outrow = NULL;
 static signed char *runcnt = NULL;
 
 static void 
-putbits(b, n) {
-    /* put #n bits in b out, packing into bytes; n=0 flushes bits */
-    /* n should never be > 8 */
-
-   static int out = 0;
-   static int cnt = 0;
-   static int num = 0;
-   static int pack = 0;
-   if (n) {
-      int xo = 0;
-      int xc = 0;
-      if (cnt+n > 8) {  /* overflowing current byte? */
-     xc = cnt + n - 8;
-     xo = (b & ~(-1 << xc)) << (8-xc);
-     n -= xc;
-     b >>= xc;
-      }
-      cnt += n;
-      out |= (b & ~(-1 << n)) << (8-cnt);
-      if (cnt >= 8) {
-     inrow[num++] = out;
-     out = xo;
-     cnt = xc;
-      }
-   } else { /* flush row */
-      int i;
-      if (cnt) {
-     inrow[num++] = out;
-     out = cnt = 0;
-      }
-      for (; num > 0 && inrow[num-1] == 0; num--); /* remove trailing zeros */
-      printf("\033*b"); 
-      if (num && !nopack) {            /* TIFF 4.0 packbits encoding */
-     int start = 0;
-     int next;
-     runcnt[start] = 0;
-     for (i = 1; i < num; i++) {
-        if (inrow[i] == inrow[i-1]) {
-           if (runcnt[start] <= 0 && runcnt[start] > -127)
-          runcnt[start]--;
-           else
-          runcnt[start = i] = 0;
-        } else {
-           if (runcnt[start] >= 0 && runcnt[start] < 127)
-          runcnt[start]++;
-           else
-          runcnt[start = i] = 0;
+putbits(int const bArg,
+        int const nArg) {
+/*----------------------------------------------------------------------------
+  Put 'n' bits in 'b' out, packing into bytes; n=0 flushes bits.
+
+  n should never be > 8 
+-----------------------------------------------------------------------------*/
+    static int out = 0;
+    static int cnt = 0;
+    static int num = 0;
+    static bool pack = false;
+
+    int b;
+    int n;
+
+    b = bArg;
+    n = nArg;
+
+    if (n) {
+        int xo = 0;
+        int xc = 0;
+
+        assert(n <= 8);
+
+        if (cnt + n > 8) {  /* overflowing current byte? */
+            xc = cnt + n - 8;
+            xo = (b & ~(-1 << xc)) << (8-xc);
+            n -= xc;
+            b >>= xc;
         }
-     }
-     start = 0;
-     for (i = 0; i < num; i = next) {
-        int count = runcnt[i];
-        int from = i;
-        if (count >= 0) { /* merge two-byte runs */
-           for (;;) {
-          next = i+1+runcnt[i];
-          if(next >= num || runcnt[next] < 0 ||
-             count+runcnt[next]+1 > 127)
-             break;
-          count += runcnt[next]+1;
-          i = next;
-           }
+        cnt += n;
+        out |= (b & ~(-1 << n)) << (8-cnt);
+        if (cnt >= 8) {
+            inrow[num++] = out;
+            out = xo;
+            cnt = xc;
         }
-        next =  i + 1 + ((runcnt[i] < 0) ? -runcnt[i] : runcnt[i]);
-        if (next < num && count > 0 &&
-        runcnt[next] < 0 && runcnt[next] > -127) {
-           count--;
-           next--;
-           runcnt[next] = runcnt[next+1]-1;
+    } else { /* flush row */
+        if (cnt) {
+            inrow[num++] = out;
+            out = cnt = 0;
         }
-        outrow[start++] = count;
-        if (count >= 0) {
-           while (count-- >= 0)
-          outrow[start++] = inrow[from++];
-        } else
-           outrow[start++] = inrow[from];
-     }
-     if (start < num) {
-        num = start;
-        if (!pack) {
-           printf("2m");
-           pack = 1;
+        for (; num > 0 && inrow[num-1] == 0; --num);
+            /* remove trailing zeros */
+        printf("\033*b"); 
+        if (num && !nopack) {            /* TIFF 4.0 packbits encoding */
+            size_t outSize;
+            pm_rlenc_compressbyte(
+                (unsigned char *)inrow, (unsigned char *)outrow,
+                PM_RLE_PACKBITS, num, &outSize); 
+            if (outSize < num) {
+                num = outSize;
+                if (!pack) {
+                    printf("2m");
+                    pack = true;
+                }
+            } else {
+                if (pack) {
+                    printf("0m");
+                    pack = false;
+                }
+            }
         }
-     } else {
-        if (pack) {
-           printf("0m");
-           pack = 0;
+        printf("%dW", num);
+        {
+            unsigned int i;
+            for (i = 0; i < num; ++i)
+                putchar(pack ? outrow[i] : inrow[i]);
         }
-     }
-      }
-      printf("%dW", num);
-      for (i = 0; i < num; i++)
-     putchar(pack ? outrow[i] : inrow[i]);
-      num = 0; /* new row */
-   }
+        num = 0; /* new row */
+    }
 }
 
 
diff --git a/converter/ppm/ppmtorgb3.c b/converter/ppm/ppmtorgb3.c
index b1ac8087..3d2f1c21 100644
--- a/converter/ppm/ppmtorgb3.c
+++ b/converter/ppm/ppmtorgb3.c
@@ -51,11 +51,11 @@ openComponentOut(const char * const suffix,
 
     const char * fileName;
 
-    asprintfN(&fileName, "%s.%s", baseName, suffix);
+    pm_asprintf(&fileName, "%s.%s", baseName, suffix);
 
     *fpP = pm_openw(fileName);
 
-    strfree(fileName);
+    pm_strfree(fileName);
 }
 
 
@@ -90,7 +90,7 @@ main(int argc, const char ** argv) {
     ifP = pm_openr(cmdline.inputFileName);
 
     if (streq(cmdline.inputFileName, "-"))
-        asprintfN(&baseFileName, "noname");
+        baseFileName = strdup("noname");
     else
         baseFileName = strippedOfExtension(cmdline.inputFileName);
 
@@ -131,7 +131,7 @@ main(int argc, const char ** argv) {
 
     pgm_freerow(grayrow);
     ppm_freerow(pixelrow);
-    strfree(baseFileName);
+    pm_strfree(baseFileName);
     pm_close(ifP);
     pm_close(blufP);
     pm_close(grnfP);
diff --git a/converter/ppm/ppmtospu.c b/converter/ppm/ppmtospu.c
new file mode 100644
index 00000000..b558c1fe
--- /dev/null
+++ b/converter/ppm/ppmtospu.c
@@ -0,0 +1,593 @@
+/*
+ *  ppmtpspu.c - Read a raw PPM file on stdin and write an uncompressed
+ *  Spectrum file on stdout.
+ *
+ *  Copyright (C) 1990, Steve Belczyk
+ */
+
+#include <assert.h>
+#include <stdio.h>
+
+#include "pm_c_util.h"
+#include "mallocvar.h"
+#include "shhopt.h"
+#include "pam.h"
+
+#define SPU_WIDTH 320
+#define SPU_HEIGHT 200
+
+
+struct CmdlineInfo {
+    /* All the information the user supplied in the command line,
+       in a form easy for the program to use.
+    */
+    const char * inputFileName;  /* Name of input file */
+    unsigned int dithflag;
+        /* dithering flag */
+};
+
+
+static void
+parseCommandLine(int argc, const char ** argv,
+                 struct CmdlineInfo * const cmdlineP) {
+/*----------------------------------------------------------------------------
+   Parse the program arguments (given by argc and argv) into a form
+   the program can deal with more easily -- a cmdline_info structure.
+   If the syntax is invalid, issue a message and exit the program via
+   pm_error().
+
+   Note that the file spec array we return is stored in the storage that
+   was passed to us as the argv array.
+-----------------------------------------------------------------------------*/
+    optEntry * option_def;  /* malloc'ed */
+    optStruct3 opt;  /* set by OPTENT3 */
+    unsigned int option_def_index;
+
+    unsigned int d0Spec, d2Spec, d4Spec;
+
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    option_def_index = 0;   /* incremented by OPTENT3 */
+    OPTENT3(0,   "d0",       OPT_FLAG,   
+            NULL,                       &d0Spec, 0);
+    OPTENT3(0,   "d2",       OPT_FLAG,   
+            NULL,                       &d2Spec, 0);
+    OPTENT3(0,   "d4",       OPT_FLAG,   
+            NULL,                       &d4Spec, 0);
+
+    opt.opt_table = option_def;
+    opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
+    opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
+
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
+
+
+    if (d4Spec)
+        cmdlineP->dithflag = 4;
+    else if (d2Spec)
+        cmdlineP->dithflag = 2;
+    else if (d0Spec)
+        cmdlineP->dithflag = 0;
+    else
+        cmdlineP->dithflag = 2;
+
+    if (argc-1 < 1) 
+        cmdlineP->inputFileName = "-";
+    else {
+        cmdlineP->inputFileName = argv[1];
+
+        if (argc-1 > 1)
+            pm_error("Program takes zero or one argument (filename).  You "
+                     "specified %u", argc-1);
+    }
+}
+
+
+
+/* This is the stuff to remember about each pixel */
+struct PixelType {
+    unsigned int index4;      /* 4-bit color, used in bitmap */
+    unsigned int x;           /* Pixel's original x-position */
+    unsigned int popularity;  /* Popularity of this pixel's color */
+    unsigned int color9;      /* 9-bit color this pixel actually got */
+};
+
+
+typedef struct {
+    int index[SPU_WIDTH][16];   /* Indices into the 48 color entries */
+} Index48;
+
+typedef struct {
+/* These are the palettes, 3 16-color palettes per each of 200 scan lines */
+    int pal[SPU_HEIGHT][48];  /* -1 means free */
+} Pal;
+
+
+
+static void
+initializePalette(Pal * const palP) {
+/*----------------------------------------------------------------------------
+   Set palettes to zero
+-----------------------------------------------------------------------------*/
+    unsigned int row;
+
+    for (row = 0; row < SPU_HEIGHT; ++row) {
+        unsigned int j;
+        for (j = 0; j < 48; ++j)
+            palP->pal[row][j] = 0;
+    }
+}
+
+
+
+static int
+findIndex(unsigned int const col,
+          unsigned int const index) {
+/*----------------------------------------------------------------------------
+   Given an x-coordinate and a color index, return the corresponding
+   Spectrum palette index.
+-----------------------------------------------------------------------------*/
+    int r, x1;
+    
+    x1 = 10 * index;  /* initial value */
+    if (index & 0x1)
+        x1 -= 5;
+    else
+        ++x1;
+
+    r = index;  /* initial value */
+
+    if ((col >= x1) && (col < (x1+160)))
+        r += 16;
+
+    if (col >= (x1+160))
+        r += 32;
+    
+    return r;
+}
+
+
+
+static void
+setup48(Index48 * const index48P) {
+/*----------------------------------------------------------------------------
+  For each pixel position, set up the indices into the 48-color
+  palette
+-----------------------------------------------------------------------------*/
+    unsigned int col;
+
+    for (col = 0; col < SPU_WIDTH; ++col) {
+        unsigned int i;
+        for (i = 0; i < 16; ++i)
+            index48P->index[col][i] = findIndex(col, i);
+    }
+}
+
+
+
+static void
+dither(unsigned int       const row,
+       tuple *            const tuplerow,
+       unsigned int       const dithflag,
+       struct PixelType * const pixelType) {
+
+    static int const dith4[4][4] = {
+        { 0,  8,  2, 10 },
+        { 12, 4, 14,  6 },
+        { 3, 11,  1,  9 },
+        { 15, 7, 13,  5 }
+    };
+
+    static int const dith2[2][2] = {
+        { 0, 2 },
+        { 3, 1 }
+    };
+    
+    unsigned int c[3];  /* An element for each plane */
+    unsigned int col;
+
+    for (col = 0; col < SPU_WIDTH; ++col) {
+        unsigned int plane;
+
+        for (plane = 0; plane < 3; ++plane) {
+            unsigned int t;
+
+            c[plane] = ((tuplerow[col][plane] & 0xe0) >> 5) & 0x7;
+                /* initial value */
+
+            switch (dithflag) {
+            case 0:
+                break;
+
+            case 2:
+                t = (tuplerow[col][plane] & 0x18 ) >> 3;
+                if (t > dith2[col%2][row%2])
+                    ++c[plane];
+                break;
+
+            case 4:
+                t = (tuplerow[col][plane] & 0x1e) >> 1;
+                if (t > dith4[col%4][row%4])
+                    ++c[plane];
+                break;
+            }
+            c[plane] = MIN(7, c[plane]);
+        }
+        pixelType[col].color9 = (c[0] << 6) | (c[1] << 3) | c[2];
+        pixelType[col].x = col;
+    }
+}
+
+
+
+static void
+swapPixelType(struct PixelType *  const pixelType,
+              unsigned int        const i,
+              unsigned int        const j) {
+
+    struct PixelType const w = pixelType[i];
+
+    pixelType[i] = pixelType[j];
+    pixelType[j] = w;
+}
+
+
+
+static void
+sort(struct PixelType * const pixelType,
+     unsigned int       const left,
+     unsigned int       const right) {
+/*----------------------------------------------------------------------------
+  Sort pixelType[] from element 'left' to (not including) element 'right' in
+  increasing popularity.
+
+  Good ol' Quicksort.
+-----------------------------------------------------------------------------*/
+    unsigned int const pivot = pixelType[(left+right-1)/2].popularity;
+
+    unsigned int i, j;
+
+    /* Rearrange so that everything less than 'pivot' is on the left side of
+       the subject array slice and everything greater than is on the right
+       side and elements equal could be on either side (we won't know until
+       we're done where the dividing line between the sides is), then sort
+       those two sides.
+    */
+
+    assert(left < right);
+
+    for (i = left, j = right; i < j; ) {
+        while (pixelType[i].popularity < pivot)
+            ++i;
+        while (pixelType[j-1].popularity > pivot)
+            --j;
+        
+        if (i < j) {
+            /* An element not less popular than pivot is to the left of a
+               pixel not more popular than pivot, so swap them.  Note that we
+               could be swapping equal (pivot-valued) elements.  Though the
+               swap isn't necessary, moving 'i' and 'j' is.
+            */
+            swapPixelType(pixelType, i, j-1);
+            ++i;
+            --j;
+        }
+    }
+    
+    if (j - left > 1)
+        sort(pixelType, left, j);
+    if (right - i > 1)
+        sort(pixelType, i, right);
+}
+
+
+
+static void
+computePalette(struct PixelType * const pixelType) {
+
+    unsigned int hist[512];      /* Count for each color */
+    unsigned int col;
+    unsigned int i;
+
+    /* Uses popularity algorithm */
+
+    /* Count the occurences of each color */
+
+    for (i = 0; i < 512; ++i)
+        hist[i] = 0;
+
+    for (col = 0; col < SPU_WIDTH; ++col)
+        ++hist[pixelType[col].color9];
+
+    /* Set the popularity of each pixel's color */
+    for (col = 0; col < SPU_WIDTH; ++col)
+        pixelType[col].popularity = hist[pixelType[col].color9];
+
+    /* Sort to find the most popular colors */
+    sort(pixelType, 0, SPU_WIDTH);
+}
+
+
+
+static int
+dist9(unsigned int const x,
+      unsigned int const y) {
+/*----------------------------------------------------------------------------
+    Return the distance between two 9-bit colors.
+-----------------------------------------------------------------------------*/
+    unsigned int i;
+    unsigned int d;
+    int x0[3], y0[3];
+
+    x0[0] = (x & 0x007);
+    x0[1] = (x & 0x038) >> 3;
+    x0[2] = (x & 0x1c0) >> 6;
+
+    y0[0] = (y & 0x007);
+    y0[1] = (y & 0x038) >> 3;
+    y0[2] = (y & 0x1c0) >> 6;
+
+    for (i = 0, d = 0; i < 3; ++i) {
+        unsigned int const t = x0[i] - y0[i];
+        d += t * t;
+    }
+
+    return d;
+}
+
+
+
+static void
+convertPixel(unsigned int       const col,
+             unsigned int       const row,
+             struct PixelType * const pixelType,
+             Pal *              const palP,
+             const Index48 *    const index48P) {
+
+    int ifree;
+
+    unsigned int const x = pixelType[col].x;
+    unsigned int const c = pixelType[col].color9;
+
+    ifree = -1;       /* Set if free slot found */
+
+    /* Handle each possible case, from easiest to hardest, in the hopes the
+       easy ones are more frequent.
+    */
+
+    /* If it wants black, it gets it */
+    if (c == 0)
+        pixelType[col].index4 = 0;
+    else {
+        /* If another pixel is using this color, it gets it */
+        unsigned int i;
+        for (i = 1; i < 15; ++i) {
+            /* Check for free slots while we're here */
+            if ((ifree < 0) &&
+                (palP->pal[row][index48P->index[x][i]] == -1))
+                ifree = i;
+            else if (c == palP->pal[row][index48P->index[x][i]]) {
+                pixelType[col].index4 = i;
+                return;
+            }
+        }
+
+        /* If there are no free slots, we must use the closest entry in use so
+           far
+        */
+        if (ifree < 0) {
+            unsigned int i;
+            unsigned int d;
+            unsigned int b;
+
+            for (i = 1, d = 1000; i < 15; ++i) {
+                unsigned int const t =
+                    dist9(c, palP->pal[row][index48P->index[x][i]]);
+                if (t < d) {
+                    d = t;
+                    b = i;
+                }
+            }
+
+            /* See if it would be better off with black */
+            if (d > dist9(c, 0))
+                b = 0;
+
+            pixelType[col].index4 = b;
+        } else {
+            /* Use up a slot and give it what it wants */
+            palP->pal[row][index48P->index[x][ifree]] = c;
+            pixelType[col].index4 = ifree;
+        }
+    }
+}
+
+
+
+static void
+setPixel(unsigned int const col,
+         unsigned int const row,
+         unsigned int const c,
+         short *      const screen) {
+
+    unsigned int index, bit, plane;
+
+    /* In the next few statements, the bit operations are a little
+       quicker, but the arithmetic versions are easier to read and
+       maybe more portable.  Please try swapping them if you have
+       trouble on your machine.
+    */
+
+    /*  index = (80 * row) + 4 * (col / 16);    */
+    index = (row << 6) + (row << 4) + ((col >> 4) << 2);
+
+    /*  bit = 0x8000 >> (col % 16);   */
+    bit = 0x8000 >> (col & 0x0f);
+
+    for (plane=0; plane<4; ++plane) {
+        if (c & (1 << plane))
+            screen[index + plane] |= bit;
+    }
+}
+
+
+
+static void
+convertRow(unsigned int       const row,
+           struct PixelType * const pixelType,
+           Pal *              const palP,
+           const Index48 *    const index48P,
+           short *            const screen) {
+
+    unsigned int i;
+
+    /* Mark palette entries as all free */
+    for (i = 0; i < 48; ++i)
+        palP->pal[row][i] = -1;
+    
+    /* Mark reserved palette entries */
+    palP->pal[row][0]  = palP->pal[row][15] = palP->pal[row][16] = 0;
+    palP->pal[row][31] = palP->pal[row][32] = palP->pal[row][47] = 0;
+
+    /* Convert each pixel */
+
+    {
+        /* Process the pixels in order of the popularity of the desired
+           color
+        */
+        int col;
+        for (col = SPU_WIDTH-1; col >= 0; --col) {
+            convertPixel(col, row, pixelType, palP, index48P);
+            setPixel(pixelType[col].x, row, pixelType[col].index4, screen);
+        }
+    }
+}
+
+
+
+static void
+doRow(unsigned int    const row,
+      tuple *         const tuplerow,
+      unsigned int    const dithflag,
+      const Index48 * const index48P,
+      Pal *           const palP,
+      short *         const screen) {
+
+    struct PixelType pixelType[SPU_WIDTH];
+
+    /* Dither and reduce to 9 bits */
+    dither(row, tuplerow, dithflag, pixelType);
+
+    /* Compute the best colors for this row */
+    computePalette(pixelType);
+
+    /* Convert this row */
+    convertRow(row, pixelType, palP, index48P, screen);
+}
+
+
+
+static void
+writeScreen(const short * const screen) {
+
+    /* Write the bitmap */
+
+    unsigned int i;
+    
+    for (i = 0; i < 16000; ++i) {
+        char const c0 = 0xff & (screen[i] >> 8);
+        char const c1 = 0xff & screen[i];
+        putchar(c0);
+        putchar(c1);
+    }
+}
+
+
+
+static void
+writePalettes(const Pal * const palP) {
+
+    unsigned int row;
+
+    for (row = 1; row < SPU_HEIGHT; ++row) {
+        unsigned int i;
+        for (i = 0; i < 48; ++i) {
+            int const p = palP->pal[row][i];
+            unsigned int const q =
+                ((p & 0x1c0) << 2) +
+                ((p & 0x038) << 1) +
+                ((p & 0x007) << 0);
+
+            putchar((q >> 8) & 0xff);
+            putchar((q >> 0) & 0xff);
+        }
+    }
+}
+
+
+
+static void
+writeSpu(const short * const screen,
+         const Pal *   const palP ) {
+
+    writeScreen(screen);
+
+    writePalettes(palP);
+}
+
+
+
+int
+main (int argc, const char ** argv) {
+
+    struct pam pam;
+    struct CmdlineInfo cmdline;
+    FILE * ifP;
+    tuple ** tuples;
+    Pal pal;
+    Index48 index48;
+    short screen[16000];  /* This is the ST's video RAM */
+
+    pm_proginit(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+
+    ifP = pm_openr(cmdline.inputFileName);
+
+    tuples = pnm_readpam(ifP, &pam, PAM_STRUCT_SIZE(tuple_type));
+
+    if (pam.depth < 3)
+        pm_error("Image must be RGB, so at least 3 deep.  This image is "
+                 "only %u deep", pam.depth);
+
+    if ((pam.width != SPU_WIDTH) || (pam.height != SPU_HEIGHT))
+        pm_error("Image size must be %ux%u.  This one is %u x %u",
+                 SPU_WIDTH, SPU_HEIGHT, pam.width, pam.height);
+
+    {
+        unsigned int i;
+        for (i = 0; i < 16000; screen[i++] = 0);
+    }
+    setup48(&index48);
+
+    initializePalette(&pal);
+
+    {
+        /* Set first row of screen data to black */
+        unsigned int i;
+        for (i = 0; i < 80; ++i)
+            screen[i] = 0;
+    }
+    {
+        unsigned int row;
+        for (row = 0; row < SPU_HEIGHT; ++row)
+            doRow(row, tuples[row], cmdline.dithflag, &index48, &pal, screen);
+    }
+    writeSpu(screen, &pal);
+
+    return 0;
+}
+
+
+
diff --git a/converter/ppm/ppmtoterm.c b/converter/ppm/ppmtoterm.c
index 81df614e..d388f77d 100644
--- a/converter/ppm/ppmtoterm.c
+++ b/converter/ppm/ppmtoterm.c
@@ -19,32 +19,37 @@
 **
 */
 
+#include <assert.h>
 #include <string.h>
 
 #include "pm_c_util.h"
-#include "ppm.h"
+#include "mallocvar.h"
 #include "shhopt.h"
+#include "ppm.h"
 
 
 struct cmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
-    const char *inputFilespec;  /* Filespec of input file */
+    const char * inputFileName;  /* Name of input file */
     unsigned int verbose;
 };
 
 
 
 static void
-parseCommandLine(int argc, char **argv,
-                 struct cmdlineInfo *cmdlineP) {
-    optEntry *option_def = malloc(100*sizeof(optEntry));
+parseCommandLine(int argc, const char ** argv,
+                 struct cmdlineInfo * const cmdlineP) {
+
+    optEntry * option_def;
         /* Instructions to OptParseOptions3 on how to parse our options */
     optStruct3 opt;
 
     unsigned int option_def_index;
 
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
     option_def_index = 0;   /* incremented by OPTENTRY */
     OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0);
 
@@ -52,123 +57,176 @@ parseCommandLine(int argc, char **argv,
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
 
-    optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
-    switch (argc-1) {
-    case 0:
-        cmdlineP->inputFilespec = "-";
-        break;
-    case 1:
-        cmdlineP->inputFilespec = argv[1];
-        break;
-    case 2:
-        break;
+    if (argc-1 < 1)
+        cmdlineP->inputFileName = "-";
+    else {
+        cmdlineP->inputFileName = argv[1];
+
+        if (argc-1 > 1)
+            pm_error("Too many arguments: %u.  The only possible argument "
+                     "is the input file name", argc-1);
     }
 }
 
 
-#define ESC         "\x1B\x5B"
-#define NUM_COLORS      128
-#define MAX_ANSI_STR_LEN    16
 
+#define ESC "\x1B\x5B"
+#define ANSI_BRIGHT_CMD_PAT ESC "%dm"
+#define ANSI_FGCOLOR_CMD_PAT ESC "3%dm"
+#define ANSI_BGCOLOR_CMD_PAT ESC "4%dm"
+#define MAX_ANSI_STR_LEN 16
+#define NUM_COLORS 128
+    /* 1 bit each RGB = 8 colors.
+       8 BG colors * 8 FG colors * 2 brightnesses
+    */
 
-static int __inline__ sqr(const int x) {
-    return x*x;
-}
 
-/*
-    Generates some sort of color palette mixing the available
-    colors as different values of background, foreground & brightness.
-*/
-static int 
-generate_palette(unsigned char rgb[NUM_COLORS][3], 
-                 char ansi_code[NUM_COLORS][MAX_ANSI_STR_LEN]) {
-    int code, col=0, cd2=0;
-    
-    memset((void *)rgb, 0, NUM_COLORS*3);
-    memset((void *)ansi_code, 0, NUM_COLORS*MAX_ANSI_STR_LEN);
-
-    for(col=cd2=0; cd2<8; cd2++) {
-        unsigned int b;
-        for(b=0;b<2;b++) {
-            for(code=0; code<8; code++) {
-                unsigned int c;
-                for(c=0;c<3;c++) {
-                    if(code&(1<<c)) {
-                        rgb[col][c]=(192|(b?63:0));
-                    }
-                    if(cd2&(1<<c)) {
-                        rgb[col][c]|=(128);
+
+static void
+generatePalette(unsigned char        rgb[NUM_COLORS][3], 
+                char                 ansiCode[NUM_COLORS][MAX_ANSI_STR_LEN],
+                unsigned int * const paletteSizeP) {
+/*----------------------------------------------------------------------------
+  Generate some sort of color palette mixing the available colors as different
+  values of background, foreground & brightness.
+
+  We return as rgb[I] the RGB triple for the color with palette index I.
+  Component intensities are in the range 0..255.  rgb[I][0] is red;
+  rgb[I][1] is green; rgb[I][2] is blue.
+
+  We return as ansiCode[I] the sequence you send to a terminal to generate
+  the color with palette index I.
+-----------------------------------------------------------------------------*/
+    unsigned int idx;
+        /* palette index of the color being considered */
+    unsigned int bgColorCode;
+        /* This is the ANSI color code for the background.  An ANSI color code
+           is a 3 bit code in which LSB means red; middle bit means green, and
+           MSB means blue.
+        */
+
+    /* We develop the palette backwards: consider every permutation of the
+       three terminal controls -- background, foreground, and brightness --
+       and for each figure out what RGB color it represents and fill in
+       that element of RGB[][]
+    */
+
+    for (bgColorCode = 0, idx = 0; bgColorCode < 8; ++bgColorCode) {
+        unsigned int brightness;  /* 0 = dim; 1 = bright */
+        for (brightness = 0; brightness < 2; ++brightness) {
+            unsigned int fgColorCode;
+                /* ANSI color code for the foreground.  See bgColorCode. */
+            for (fgColorCode = 0; fgColorCode < 8; ++fgColorCode) {
+                unsigned int rgbComp;
+                    /* 0 = red; 1 = green; 2 = blue */
+                for (rgbComp = 0; rgbComp < 3; ++rgbComp) {
+                    assert (idx < NUM_COLORS);
+                    rgb[idx][rgbComp] = 0x00;  /* initial value */
+                    if ((fgColorCode & (0x1 << rgbComp)) != 0) {
+                        rgb[idx][rgbComp] |= 0xC0;
+                        if (brightness == 1)
+                            rgb[idx][rgbComp] |= 0x3F;
                     }
+                    if ((bgColorCode & (0x1 << rgbComp)) != 0)
+                        rgb[idx][rgbComp] |= 0x80;
                 }
-                sprintf(ansi_code[col],
-                        ESC"%dm"ESC"3%dm"ESC"4%dm",
-                        b, code, cd2);
-                col++;
+                sprintf(ansiCode[idx],
+                        ANSI_BRIGHT_CMD_PAT
+                        ANSI_FGCOLOR_CMD_PAT
+                        ANSI_BGCOLOR_CMD_PAT,
+                        brightness, fgColorCode, bgColorCode);
+                ++idx;
             }
         }
     }
-    return col;
+    *paletteSizeP = idx;
+}
+
+
+
+static void
+lookupInPalette(pixel          const pixel,
+                pixval         const maxval,
+                unsigned char        rgb[NUM_COLORS][3], 
+                unsigned int   const palLen,
+                unsigned int * const paletteIdxP) {
+/*----------------------------------------------------------------------------
+   Look up the color 'pixel' (which has maxval 'maxval') in the palette
+   palette[], which has 'palLen' elements and uses maxval 255.  Return the
+   index into palette[] of the color that is closes to 'pixel' as
+   *paletteIdxP.
+-----------------------------------------------------------------------------*/
+    pixval const r = PPM_GETR(pixel) * 255 / maxval;
+    pixval const g = PPM_GETG(pixel) * 255 / maxval;
+    pixval const b = PPM_GETB(pixel) * 255 / maxval;
+
+    unsigned int paletteIdxSoFar;
+    unsigned int dist;
+    unsigned int i;
+            
+    /* The following loop calculates the index that corresponds to the
+       minimum color distance between the given RGB values and the
+       values available in the palette.
+    */
+    for (i = 0, dist = SQR(255)*3, paletteIdxSoFar = 0; i < palLen; ++i) {
+        pixval const pr=rgb[i][0];
+        pixval const pg=rgb[i][1];
+        pixval const pb=rgb[i][2];
+        unsigned int const j = SQR(r-pr) + SQR(b-pb) + SQR(g-pg);
+
+        if (j  < dist) {
+            dist = j;
+            paletteIdxSoFar = i;
+        }
+    }
+    *paletteIdxP = paletteIdxSoFar;
 }
 
 
 
-int main(int argc, char **argv)
-{
-    FILE            *ifp;
-    pixel           **pixels;
-    int             rows, row, cols, col,
-                    pal_len, i;
+int
+main(int argc, const char ** argv) {
+
+    FILE *          ifP;
+    pixel **        pixels;
+    int             rows, cols;
+    unsigned int    row;
+    unsigned int    palLen;
     pixval          maxval;
-    struct cmdlineInfo
-                    cmdline;
+    struct cmdlineInfo cmdline;
     unsigned char   rgb[NUM_COLORS][3];
-    char            ansi_code[NUM_COLORS][MAX_ANSI_STR_LEN];
+    char            ansiCode[NUM_COLORS][MAX_ANSI_STR_LEN];
 
-    
-    ppm_init(&argc, argv);    
+    pm_proginit(&argc, argv);    
 
     parseCommandLine(argc, argv, &cmdline);
 
-    ifp = pm_openr(cmdline.inputFilespec);
+    ifP = pm_openr(cmdline.inputFileName);
     
-    pixels = ppm_readppm(ifp, &cols, &rows, &maxval);
+    pixels = ppm_readppm(ifP, &cols, &rows, &maxval);
 
-    pm_close(ifp);
+    pm_close(ifP);
         
-    pal_len=generate_palette(rgb, ansi_code);
+    generatePalette(rgb, ansiCode, &palLen);
     
     for (row = 0; row < rows; ++row) {
-        for (col = 0; col < cols; col++) {
-            pixval const r=(int)PPM_GETR(pixels[row][col])*255/maxval;
-            pixval const g=(int)PPM_GETG(pixels[row][col])*255/maxval;
-            pixval const b=(int)PPM_GETB(pixels[row][col])*255/maxval;
-            int val, dist;
-            
-            /*
-            The following loop calculates the index that
-            corresponds to the minimum color distance
-            between the given RGB values and the values
-            available in the palette.
-            */
-            for(i=0, dist=sqr(255)*3, val=0; i<pal_len; i++) {
-                pixval const pr=rgb[i][0];
-                pixval const pg=rgb[i][1];
-                pixval const pb=rgb[i][2];
-                unsigned int j;
-                if( (j=sqr(r-pr)+sqr(b-pb)+sqr(g-pg))<dist ) {
-                    dist=j;
-                    val=i;
-                }
-            }
-            printf("%s%c", ansi_code[val],0xB1);
+        unsigned int col;
+        for (col = 0; col < cols; ++col) {
+            unsigned int paletteIdx;
+
+            lookupInPalette(pixels[row][col], maxval, rgb, palLen,
+                            &paletteIdx);
+
+            printf("%s\xB1", ansiCode[paletteIdx]);
         }
-        printf(ESC"\x30m\n");
+        printf(ESC "\x30m\n");
     }
-    printf(ESC"\x30m");
+    printf(ESC "\x30m");
 
     ppm_freearray(pixels, rows);
     
-    exit(0);
+    return 0;
 }
diff --git a/converter/ppm/ppmtowinicon.c b/converter/ppm/ppmtowinicon.c
index a96840a1..c673798f 100644
--- a/converter/ppm/ppmtowinicon.c
+++ b/converter/ppm/ppmtowinicon.c
@@ -58,7 +58,7 @@ parseCommandLine(int                 argc,
    was passed to us as the argv array.  We also trash *argv.
 -----------------------------------------------------------------------------*/
     optEntry *option_def;
-        /* Instructions to optParseOptions3 on how to parse our options.
+        /* Instructions to pm_optParseOptions3 on how to parse our options.
          */
     optStruct3 opt;
 
@@ -82,7 +82,7 @@ parseCommandLine(int                 argc,
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
 
-    optParseOptions3( &argc, argv, opt, sizeof(opt), 0);
+    pm_optParseOptions3( &argc, argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
     if (!outputSpec)
@@ -524,9 +524,9 @@ makePalette(pixel **          const xorPPMarray,
     xorChv = ppm_computecolorhist(xorPPMarray, xorCols, xorRows, MAXCOLORS, 
                                   &colors);
     if (xorChv == NULL)
-        asprintfN(errorP,
-                  "image has too many colors - try doing a 'pnmquant %d'",
-                  MAXCOLORS);
+        pm_asprintf(errorP,
+                    "image has too many colors - try doing a 'pnmquant %d'",
+                    MAXCOLORS);
     else {
         *errorP = NULL;
 
@@ -584,10 +584,10 @@ getOrFakeAndMap(const char *      const andPgmFname,
         pm_close(andfile);
 
         if ((andCols != xorCols) || (andRows != xorRows)) {
-            asprintfN(errorP,
-                      "And mask and image have different dimensions "
-                     "(%d x %d vs %d x %d).  Aborting.",
-                     andCols, xorCols, andRows, xorRows);
+            pm_asprintf(errorP,
+                        "And mask and image have different dimensions "
+                        "(%d x %d vs %d x %d).  Aborting.",
+                        andCols, xorCols, andRows, xorRows);
         } else
             *errorP = NULL;
     }
@@ -670,7 +670,7 @@ addEntryToIcon(MS_Ico       const MSIconData,
     * All the icons I found seemed to pad the palette to the max entries
     * for that bitdepth.
     * 
-    * The spec indicates this isn't neccessary, but I'll follow this behaviour
+    * The spec indicates this isn't necessary, but I'll follow this behaviour
     * just in case.
     */
     if (colors < 3) {
diff --git a/converter/ppm/ppmtoxpm.c b/converter/ppm/ppmtoxpm.c
index fc8ba9d7..38d99972 100644
--- a/converter/ppm/ppmtoxpm.c
+++ b/converter/ppm/ppmtoxpm.c
@@ -126,7 +126,7 @@ parseCommandLine(int argc, char ** argv,
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = FALSE;  /* We may have parms that are negative numbers */
 
-    optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
+    pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
     if (argc-1 == 0) 
@@ -317,7 +317,7 @@ genCmap(colorhist_vector const chv,
     MALLOCARRAY(cmap, cmapSize);
     if (cmapP == NULL)
         pm_error("Out of memory allocating %u bytes for a color map.",
-                 sizeof(cixel_map) * (ncolors+1));
+                 (unsigned)sizeof(cixel_map) * (ncolors+1));
 
     xpmMaxval = xpmMaxvalFromMaxval(maxval);
 
@@ -363,13 +363,13 @@ genCmap(colorhist_vector const chv,
 
             PPM_DEPTH(scaledColor, color, maxval, xpmMaxval);
 
-            asprintfN(&hexString, xpmMaxval == 0x000F ? "#%X%X%X" :
-                      xpmMaxval == 0x00FF ? "#%02X%02X%02X" :
-                      xpmMaxval == 0x0FFF ? "#%03X%03X%03X" :
-                      "#%04X%04X%04X", 
-                      PPM_GETR(scaledColor),
-                      PPM_GETG(scaledColor),
-                      PPM_GETB(scaledColor)
+            pm_asprintf(&hexString, xpmMaxval == 0x000F ? "#%X%X%X" :
+                        xpmMaxval == 0x00FF ? "#%02X%02X%02X" :
+                        xpmMaxval == 0x0FFF ? "#%03X%03X%03X" :
+                        "#%04X%04X%04X", 
+                        PPM_GETR(scaledColor),
+                        PPM_GETG(scaledColor),
+                        PPM_GETB(scaledColor)
                 );
 
             if (hexString == NULL)
@@ -399,7 +399,7 @@ destroyCmap(cixel_map *  const cmap,
     int i;
     /* Free the real color entries */
     for (i = 0; i < cmapSize; i++) {
-        strfree(cmap[i].rgbname);
+        pm_strfree(cmap[i].rgbname);
         free(cmap[i].cixel);
     }
     free(cmap);
diff --git a/converter/ppm/ppmtoyuv.c b/converter/ppm/ppmtoyuv.c
index 7d843cc0..75f79c1e 100644
--- a/converter/ppm/ppmtoyuv.c
+++ b/converter/ppm/ppmtoyuv.c
@@ -19,79 +19,102 @@
 
 #include "ppm.h"
 
-int
-main(argc, argv)
-char **argv;
-{
-	FILE *ifp;
-	pixel          *pixelrow;
-	register pixel *pP;
-	int             rows, cols, format, row;
-	register int    col;
-	pixval          maxval;
-	unsigned long   y1, y2=0, u=0, v=0, u0=0, u1, u2, v0=0, v1, v2;
-	unsigned char  *yuvbuf;
-
-
-	ppm_init(&argc, argv);
 
-	if (argc > 2) pm_usage("[ppmfile]");
 
-	if (argc == 2) ifp = pm_openr(argv[1]);
-	else ifp = stdin;
-
-	ppm_readppminit(ifp, &cols, &rows, &maxval, &format);
+static void
+convertRow(const pixel *   const pixelrow,
+           unsigned int    const cols,
+           unsigned char * const yuvBuf,
+           unsigned long * const uP,
+           unsigned long * const vP,
+           unsigned long * const u0P,
+           unsigned long * const v0P,
+           unsigned long * const y2CarryP) {
+
+    unsigned int col;
+    unsigned char * yuvptr;
+
+    for (col = 0, yuvptr = &yuvBuf[0]; col < cols; col += 2) {
+        unsigned long y1, y2, u1, u2, v1, v2;
+
+        {
+            /* first pixel gives Y and 0.5 of chroma */
+            pixval const r = PPM_GETR(pixelrow[col]);
+            pixval const g = PPM_GETG(pixelrow[col]);
+            pixval const b = PPM_GETB(pixelrow[col]);
+            
+            y1 = 16829 * r + 33039 * g +  6416 * b + (*y2CarryP & 0xffff);
+            u1 = -4853 * r -  9530 * g + 14383 * b;
+            v1 = 14386 * r - 12046 * g -  2340 * b;
+        }
+        {
+            /* second pixel gives Y and 0.25 of chroma */
+            pixval const r = PPM_GETR(pixelrow[col + 1]);
+            pixval const g = PPM_GETG(pixelrow[col + 1]);
+            pixval const b = PPM_GETB(pixelrow[col + 1]);
+
+            y2 = 16829 * r + 33039 * g + 6416 * b + (y1 & 0xffff);
+            u2 = -2426 * r -  4765 * g + 7191 * b;
+            v2 =  7193 * r -  6023 * g - 1170 * b;
+        }
+        /* filter the chroma */
+        *uP = *u0P + u1 + u2 + (*uP & 0xffff);
+        *vP = *v0P + v1 + v2 + (*vP & 0xffff);
+
+        *u0P = u2;
+        *v0P = v2;
+
+        *yuvptr++ = (*uP >> 16) + 128;
+        *yuvptr++ = (y1  >> 16) +  16;
+        *yuvptr++ = (*vP >> 16) + 128;
+        *yuvptr++ = (y2  >> 16) +  16;
+
+        *y2CarryP = y2;
+    }
+}
 
-    if (cols % 2 != 0)
-        pm_error("Image must have even number of columns.\n"
-                 "This image is %d columns wide.  Try Pnmcut.", cols);
 
-	pixelrow = ((pixel*) pm_allocrow( cols, sizeof(pixel) ));
-	yuvbuf = (unsigned char *) pm_allocrow( cols, 2 );
 
-	for (row = 0; row < rows; ++row) {
-		unsigned char *yuvptr;
+int
+main(int argc, const char **argv) {
 
-		ppm_readppmrow(ifp, pixelrow, cols, maxval, format);
+    FILE * ifP;
+    pixel * pixelrow;
+    int rows, cols, format;
+    pixval maxval;
+    unsigned int row;
+    unsigned char  * yuvBuf;
+    unsigned long u, v, u0, v0, y2Carry;
 
-		for (col = 0, pP = pixelrow, yuvptr=yuvbuf; col < cols; col += 2, ++pP) {
-			pixval r, g, b;
+    pm_proginit(&argc, argv);
 
-			/* first pixel gives Y and 0.5 of chroma */
-			r = PPM_GETR(*pP);
-			g = PPM_GETG(*pP);
-			b = PPM_GETB(*pP);
+    if (argc-1 > 1)
+        pm_error("Too many arguments: %u.  The only possible argument "
+                 "is the name of the input file", argc-1);
 
-			y1 = 16829 * r + 33039 * g + 6416 * b + (0xffff & y2);
-			u1 = -4853 * r - 9530 * g + 14383 * b;
-			v1 = 14386 * r - 12046 * g - 2340 * b;
+    if (argc-1 == 1)
+        ifP = pm_openr(argv[1]);
+    else
+        ifP = stdin;
 
-			pP++;
-			/* second pixel just yields a Y and 0.25 U, 0.25 V */
-			r = PPM_GETR(*pP);
-			g = PPM_GETG(*pP);
-			b = PPM_GETB(*pP);
+    ppm_readppminit(ifP, &cols, &rows, &maxval, &format);
 
-			y2 = 16829 * r + 33039 * g + 6416 * b + (0xffff & y1);
-			u2 = -2426 * r - 4765 * g + 7191 * b;
-			v2 = 7193 * r - 6023 * g - 1170 * b;
+    if (cols % 2 != 0)
+        pm_error("Image must have even number of columns.\n"
+                 "This image is %u columns wide.  Try Pamcut.", cols);
 
-			/* filter the chroma */
-			u = u0 + u1 + u2 + (0xffff & u);
-			v = v0 + v1 + v2 + (0xffff & v);
+    pixelrow = ppm_allocrow(cols);
+    yuvBuf = (unsigned char *) pm_allocrow(cols, 2);
 
-			u0 = u2;
-			v0 = v2;
+    for (row = 0, u = v = u0 = v0 = y2Carry = 0; row < rows; ++row) {
+        ppm_readppmrow(ifP, pixelrow, cols, maxval, format);
 
-			*yuvptr++ = (u >> 16) + 128;
-			*yuvptr++ = (y1 >> 16) + 16;
-			*yuvptr++ = (v >> 16) + 128;
-			*yuvptr++ = (y2 >> 16) + 16;
-		}
-		fwrite(yuvbuf, cols*2, 1, stdout);
-	}
+        convertRow(pixelrow, cols, yuvBuf, &u, &v, &u0, &v0, &y2Carry);
+        
+        fwrite(yuvBuf, cols*2, 1, stdout);
+    }
 
-	pm_close(ifp);
+    pm_close(ifP);
 
-	exit(0);
+    return 0;
 }
diff --git a/converter/ppm/ppmtoyuvsplit.c b/converter/ppm/ppmtoyuvsplit.c
index b5809d0b..eb89ad29 100644
--- a/converter/ppm/ppmtoyuvsplit.c
+++ b/converter/ppm/ppmtoyuvsplit.c
@@ -46,9 +46,9 @@ static void
 makeOutputFileName(const char *         const baseName,
                    struct FileNameSet * const fnameP) {
 
-    asprintfN(&fnameP->u, "%s.U", baseName);
-    asprintfN(&fnameP->v, "%s.V", baseName);
-    asprintfN(&fnameP->y, "%s.Y", baseName);
+    pm_asprintf(&fnameP->u, "%s.U", baseName);
+    pm_asprintf(&fnameP->v, "%s.V", baseName);
+    pm_asprintf(&fnameP->y, "%s.Y", baseName);
 }
 
 
@@ -56,9 +56,9 @@ makeOutputFileName(const char *         const baseName,
 static void
 termFileNameSet(struct FileNameSet const fname) {
 
-    strfree(fname.u);
-    strfree(fname.v);
-    strfree(fname.y);
+    pm_strfree(fname.u);
+    pm_strfree(fname.v);
+    pm_strfree(fname.y);
 }
 
 
diff --git a/converter/ppm/sldtoppm.c b/converter/ppm/sldtoppm.c
index ab9f3447..550eed5b 100644
--- a/converter/ppm/sldtoppm.c
+++ b/converter/ppm/sldtoppm.c
@@ -26,23 +26,20 @@
 #include <string.h>
 #include <math.h>
 
+#include "pm_c_util.h"
 #include "ppm.h"
 #include "ppmdraw.h"
 #include "nstring.h"
-#ifdef DEBUG
 #include <assert.h>
-#else
-#define assert(x)
-#endif
+
+#include "autocad.h"                  /* AutoCAD standard color assignments */
+
 
 /*  Define a variable type accepting numbers -127 <= n <= 127.  But note
     that we still expect it to act UNSIGNED. */
 
 #define smallint unsigned char        /* Small integers */
 
-#define TRUE     1
-#define FALSE    0
-
 #define EOS     '\0'
 
 /* Screen point */
@@ -70,18 +67,17 @@ typedef void (slvecfn)(struct svector * vec, int color);
 typedef void (slfloodfn)(struct spolygon * poly, int color);
 
 
+static unsigned long const pixmaxval = 255;  /* Largest pixel value */
+
 static int ixdots, iydots;        /* Screen size in dots */
-static FILE *slfile;              /* Slide file descriptor */
-static int blither = FALSE;       /* Dump slide file information ? */
-static int info = FALSE;          /* Print header information */
+static FILE * slfile;             /* Slide file descriptor */
+static bool blither;              /* Dump slide file information ? */
+static bool info;                 /* Print header information */
 static pixel **pixels;            /* Pixel map */
-static int pixcols, pixrows;          /* Pixel map size */
-#define pixmaxval 255             /* Largest pixel value */
+static int pixcols, pixrows;      /* Pixel map size */
 static double uscale = -1;        /* Uniform scale factor */
 static int sxsize = -1, sysize = -1;  /* Scale to X, Y size ? */
 
-#include "autocad.h"                  /* AutoCAD standard color assignments */
-
 /*  Local variables  */
 
 struct slhead {
@@ -94,11 +90,11 @@ struct slhead {
     char spad;                /* Pad to even byte length */
 };
 
-static int adjust = FALSE;        /* Adjust to correct aspect ratio ? */
-static struct slhead slfrof;          /* Slide file header */
-static long xfac, yfac;           /* Aspect ratio scale factors */
+static bool adjust;           /* Adjust to correct aspect ratio ? */
+static struct slhead slfrof;  /* Slide file header */
+static long xfac, yfac;       /* Aspect ratio scale factors */
 
-static int sdrawkcab;
+static bool sdrawkcab;
     /* Slide drawing kinematic conversion of ass-backwards data flag */
 
 
@@ -108,7 +104,7 @@ static int sdrawkcab;
 */
 
 static int
-extend(smallint ch) {
+extend(unsigned char const ch) {
     return ((int) ((ch & 0x80) ? (ch | ~0xFF) : ch));
 }
 
@@ -136,9 +132,9 @@ sli(void) {
 
 static int 
 slib(void) {
-    smallint ch = 0;
+    unsigned char ch;
 
-    if (fread(&ch, sizeof ch, 1, slfile) != 1) {
+    if (fread(&ch, sizeof(ch), 1, slfile) != 1) {
         pm_error("error reading slide file");
     }
     return extend(ch);
@@ -171,22 +167,28 @@ slidefind(const char * const sname,
     char uname[32];
     unsigned char libent[36];
     long pos;
+    bool found;
+    bool eof;
 
     if (dironly)
         pm_message("Slides in library:");
     else {
-        int i;
+        unsigned int i;
         const char * ip;
         
         ip = sname; /* initial value */
         
-        for (i = 0; i < 31; i++) {
-            char ch = *ip++;
+        for (i = 0; i < 31; ++i) {
+            char const ch = *ip++;
             if (ch == EOS)
                 break;
-            if (ucasen && ISLOWER(ch))
-                ch = TOUPPER(ch);
-            uname[i] = ch;
+
+            {
+                char const upperCh =
+                    ucasen && islower(ch) ? toupper(ch) : ch;
+                
+                uname[i] = upperCh;
+            }
         }
         uname[i] = EOS;
     }
@@ -199,31 +201,38 @@ slidefind(const char * const sname,
     }
     pos = 32;
     
-    /* Search for a slide with the requested name. */
+    /* Search for a slide with the requested name or list the directory */
     
-    while (TRUE) {
-        if ((fread(libent, 36, 1, slfile) != 1) ||
-            (strnlen((char *)libent, 32) == 0)) {
+    for (found = false, eof = false; !found && !eof; ) {
+        size_t readCt;
+        readCt = fread(libent, 36, 1, slfile);
+        if (readCt != 1)
+            eof = true;
+        else if (strnlen((char *)libent, 32) == 0)
+            eof = true;
+
+        if (!eof) {
+            pos += 36;
             if (dironly) {
-                return;
-            }
-            pm_error("slide %s not in library.", sname);
-        }
-        pos += 36;
-        if (dironly) {
-            pm_message("  %s", libent);
-        } else if (strneq((char *)libent, uname, 32)) {
-            long dpos = (((((libent[35] << 8) | libent[34]) << 8) |
-                          libent[33]) << 8) | libent[32];
-            if ((slfile == stdin) || (fseek(slfile, dpos, 0) == -1)) {
-                dpos -= pos;
+                pm_message("  %s", libent);
+            } else if (strneq((char *)libent, uname, 32)) {
+                long dpos;
+
+                dpos = (((((libent[35] << 8) | libent[34]) << 8) |
+                         libent[33]) << 8) | libent[32];
         
-                while (dpos-- > 0)
-                    getc(slfile);
+                if ((slfile == stdin) || (fseek(slfile, dpos, 0) == -1)) {
+                    dpos -= pos;
+
+                    while (dpos-- > 0)
+                        getc(slfile);
+                }
+                found = true;
             }
-            break;
         }
     }
+    if (!found && !dironly)
+        pm_error("slide '%s' not in library.", sname);
 }
 
 
@@ -329,7 +338,7 @@ slider(slvecfn   slvec,
     
     /* Process the header of the slide file.  */
     
-    sdrawkcab = FALSE;            /* Initially guess byte order is OK */
+    sdrawkcab = false;            /* Initially guess byte order is OK */
     fread(slfrof.slh, 17, 1, slfile);
     fread(&slfrof.sntype, sizeof(char), 1, slfile);
     fread(&slfrof.slevel, sizeof(char), 1, slfile);
@@ -364,12 +373,12 @@ slider(slvecfn   slvec,
     */
 
     if (btest != rtest) {
-        sdrawkcab = TRUE;
-#define rshort(x) x = ((x >> 8) & 0xFF) | (x << 8)
+        sdrawkcab = true;
+        #define rshort(x) x = ((x >> 8) & 0xFF) | (x << 8)
         rshort(slfrof.sxdots);
         rshort(slfrof.sydots);
         rshort(slfrof.shwfill);
-#undef rshort
+        #undef rshort
     }
     
     /* Dump the header if we're blithering. */
@@ -413,7 +422,7 @@ slider(slvecfn   slvec,
         ixdots = slfrof.sxdots;
         iydots = slfrof.sydots;
         dsar = slfrof.sdsar;
-        adjust = FALSE;           /* Mark no adjustment needed */
+        adjust = false;           /* Mark no adjustment needed */
     }
 
     /* If there's a uniform scale factor specified, apply it. */
@@ -571,32 +580,42 @@ slider(slvecfn   slvec,
 /*  Main program. */
 
 int
-main(int    argc,
-     char * argv[]) {
+main(int          argc,
+     const char * argv[]) {
 
     int argn;
     const char * const usage = "[-verbose] [-info] [-adjust] [-scale <s>]\n\
 [-dir] [-lib|-Lib <name>]\n\
 [-xsize|-width <x>] [-ysize|-height <y>] [sldfile]";
-    int scalespec = FALSE, widspec = FALSE, hgtspec = FALSE, dironly = FALSE,
-        ucasen;
+    bool dironly;
+    bool hgtspec;
+    bool widspec;
+    bool scalespec;
+    bool ucasen;
     const char * slobber;       /* Slide library item */
 
+    pm_proginit(&argc, argv);
+    argn = 1;
 
     slobber = NULL;
-
-    ppm_init(&argc, argv);
-    argn = 1;
+    dironly = false;
+    hgtspec = false;
+    widspec = false;
+    scalespec = false;
+    ucasen = false;
+    blither = false;
+    info = false;
+    adjust = false;
 
     while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') {
         if (pm_keymatch(argv[argn], "-verbose", 2)) {
-            blither = TRUE;
+            blither = true;
         } else if (pm_keymatch(argv[argn], "-adjust", 2)) {
-            adjust = TRUE;
+            adjust = true;
         } else if (pm_keymatch(argv[argn], "-dir", 2)) {
-            dironly = TRUE;
+            dironly = true;
         } else if (pm_keymatch(argv[argn], "-info", 2)) {
-            info = TRUE;
+            info = true;
         } else if (pm_keymatch(argv[argn], "-lib", 2)) {
             if (slobber)
                 pm_error("already specified a library item");
@@ -616,7 +635,7 @@ main(int    argc,
             if (uscale <= 0.0) {
                 pm_error("scale factor must be greater than 0");
             }
-            scalespec = TRUE;
+            scalespec = true;
         } else if (pm_keymatch(argv[argn], "-xsize", 2) ||
                    pm_keymatch(argv[argn], "-width", 2)) {
             if (widspec) {
@@ -625,7 +644,7 @@ main(int    argc,
             argn++;
             if ((argn == argc) || (sscanf(argv[argn], "%d", &sxsize) != 1))
                 pm_usage(usage);
-            widspec = TRUE;
+            widspec = true;
         } else if (pm_keymatch(argv[argn], "-ysize", 2) ||
                    pm_keymatch(argv[argn], "-height", 2)) {
             if (hgtspec) {
@@ -634,7 +653,7 @@ main(int    argc,
             argn++;
             if ((argn == argc) || (sscanf(argv[argn], "%d", &sysize) != 1))
                 pm_usage(usage);
-            hgtspec = TRUE;
+            hgtspec = true;
         } else {
             pm_usage(usage);
         }
@@ -665,7 +684,7 @@ main(int    argc,
  
     if (!dironly) {
         slider(draw, flood);
-        ppm_writeppm(stdout, pixels, pixcols, pixrows, pixmaxval, FALSE);
+        ppm_writeppm(stdout, pixels, pixcols, pixrows, pixmaxval, 0);
     }
     pm_close(slfile);
     pm_close(stdout);
diff --git a/converter/ppm/sputoppm.c b/converter/ppm/sputoppm.c
index 2671bffa..acf61c1b 100644
--- a/converter/ppm/sputoppm.c
+++ b/converter/ppm/sputoppm.c
@@ -1,4 +1,4 @@
-/* sputoppm.c - read an uncompressed Spectrum file and produce a portable pixmap
+/* sputoppm.c - read an uncompressed Spectrum file and produce a PPM
 **
 ** Copyright (C) 1991 by Steve Belczyk and Jef Poskanzer
 **
@@ -16,93 +16,114 @@
 #define COLS 320
 #define MAXVAL 7
 
-static pixel pal[ROWS][48];                /* Spectrum palettes, three per row */
-static short screen[ROWS*COLS/4];          /* simulates the Atari's video RAM */
 
-int
-main( argc, argv )
-    int argc;
-    char* argv[];
+typedef struct {
+    pixel pal[ROWS][48];  /* Spectrum palettes, three per row */
+} Pal;
+
+
+
+static void
+readPalettes(FILE * const ifP,
+             Pal *  const palP) {
+
+    unsigned int row;
+
+    /* Clear the first palette line. */
     {
-    FILE* ifp;
-    int i, j;
-    pixel* pixelrow;
-    register pixel* pP;
-    int row, col;
+        unsigned int j;
+        for (j = 0; j < 48; ++j)
+            PPM_ASSIGN(palP->pal[0][j], 0, 0, 0);
+    }
+    /* Read the palettes. */
+    for (row = 1; row < ROWS; ++row) {
+        unsigned int j;
+        for (j = 0; j < 48; ++j) {
+            short k;
+            pm_readbigshort(ifP, &k);
+            PPM_ASSIGN(palP->pal[row][j],
+                       (k & 0x700) >> 8,
+                       (k & 0x070) >> 4,
+                       (k & 0x007) >> 0);
+        }
+    }
+}
+
+
+
+int
+main(int argc, const char ** argv) {
 
+    FILE * ifP;
+    unsigned int i;
+    pixel * pixelrow;
+    unsigned int row;
+    Pal pal;
+    short screen[ROWS*COLS/4];      /* simulates the Atari's video RAM */
 
-    ppm_init( &argc, argv );
+    pm_proginit(&argc, argv);
 
     /* Check args. */
     if ( argc > 2 )
         pm_usage( "[spufile]" );
 
     if ( argc == 2 )
-        ifp = pm_openr( argv[1] );
+        ifP = pm_openr( argv[1] );
     else
-        ifp = stdin;
+        ifP = stdin;
 
     /* Read the SPU file */
 
     /* Read the screen data. */
-    for ( i = 0; i < ROWS*COLS/4; ++i )
-        (void) pm_readbigshort( ifp, &screen[i] );
-
-    /* Clear the first palette line. */
-    for ( j = 0; j < 48; ++j )
-        PPM_ASSIGN( pal[0][j], 0, 0, 0 );
+    for (i = 0; i < ROWS*COLS/4; ++i)
+        pm_readbigshort(ifP, &screen[i]);
 
-    /* Read the palettes. */
-    for ( i = 1; i < ROWS; ++i )
-        for ( j = 0; j < 48; ++j )
-            {
-            short k;
-            (void) pm_readbigshort( ifp, &k );
-            PPM_ASSIGN( pal[i][j],
-                ( k & 0x700 ) >> 8,
-                ( k & 0x070 ) >> 4,
-                ( k & 0x007 ) );
-            }
+    readPalettes(ifP, &pal);
 
-    pm_close( ifp );
+    pm_close(ifP);
 
     /* Ok, get set for writing PPM. */
-    ppm_writeppminit( stdout, COLS, ROWS, (pixval) MAXVAL, 0 );
-    pixelrow = ppm_allocrow( COLS );
+    ppm_writeppminit(stdout, COLS, ROWS, MAXVAL, 0);
+    pixelrow = ppm_allocrow(COLS);
 
     /* Now do the conversion. */
-    for ( row = 0; row < ROWS; ++row )
-        {
-        for ( col = 0, pP = pixelrow; col < COLS; ++col, ++pP )
-            {
-            int c, ind, b, plane, x1;
-
+    for (row = 0; row < ROWS; ++row) {
+        unsigned int col;
+        for (col = 0; col < COLS; ++col) {
             /* Compute pixel value. */
-            ind = 80 * row + ( ( col >> 4 ) << 2 );
-            b = 0x8000 >> (col & 0xf);
-            c = 0;
-            for ( plane = 0; plane < 4; ++plane )
-                if ( b & screen[ind+plane] )
+            unsigned int const ind = 80 * row + ((col >> 4) << 2);
+            unsigned int const b = 0x8000 >> (col & 0xf);
+            unsigned int c;
+            unsigned int plane;
+            unsigned int x1;
+
+            c = 0;  /* initial value */
+            for (plane = 0; plane < 4; ++plane) {
+                if (b & screen[ind + plane])
                     c |= (1 << plane);
-
+            }
             /* Compute palette index. */
             x1 = 10 * c;
-            if ( c & 1 )
+            if ((c & 1) != 0)
                 x1 -= 5;
             else
                 ++x1;
-            if ( ( col >= x1 ) && ( col < ( x1 + 160 ) ) )
+            if ((col >= x1 ) && (col < (x1 + 160)))
                 c += 16;
-            if ( col >= ( x1 + 160 ) )
+            if (col >= (x1 + 160))
                 c += 32;
 
-            /* Store the proper color. */
-            *pP = pal[row][c];
-            }
-        ppm_writeppmrow( stdout, pixelrow, COLS, (pixval) MAXVAL, 0 );
+            /* Set the proper color. */
+            pixelrow[col] = pal.pal[row][c];
         }
+        ppm_writeppmrow(stdout, pixelrow, COLS, MAXVAL, 0);
+    }
+
+    ppm_freerow(pixelrow);
+    pm_close(stdout);
+
+    return 0;
+}
+
 
-    pm_close( stdout );
 
-    exit( 0 );
-    }
diff --git a/converter/ppm/tgatoppm.c b/converter/ppm/tgatoppm.c
index f8538214..95893089 100644
--- a/converter/ppm/tgatoppm.c
+++ b/converter/ppm/tgatoppm.c
@@ -71,7 +71,7 @@ parseCommandLine(int argc, char ** argv,
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
 
-    optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
+    pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
     if (argc - 1 == 0)
diff --git a/converter/ppm/winicontoppm.c b/converter/ppm/winicontoppm.c
index ad859c94..6b1376b2 100644
--- a/converter/ppm/winicontoppm.c
+++ b/converter/ppm/winicontoppm.c
@@ -31,10 +31,9 @@
 #define MAJVERSION 0
 #define MINVERSION 4
 
-static int file_offset = 0;    /* not actually used, but useful for debug */
+static int fileOffset = 0;    /* not actually used, but useful for debug */
 static const char     er_read[] = "%s: read error";
 static const char *   infname;
-static FILE *   ifp;
 
 struct cmdlineInfo {
     /* All the information the user supplied in the command line,
@@ -53,8 +52,8 @@ struct cmdlineInfo {
 
 
 static void
-parseCommandLine ( int argc, char ** argv,
-                   struct cmdlineInfo *cmdlineP ) {
+parseCommandLine (int argc, const 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.  
@@ -65,13 +64,15 @@ 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));
-        /* Instructions to optParseOptions3 on how to parse our options.
+    optEntry * option_def;
+        /* Instructions to pm_optParseOptions3 on how to parse our options.
          */
     optStruct3 opt;
 
     unsigned int option_def_index;
 
+    MALLOCARRAY(option_def, 100);
+
     option_def_index = 0;   /* incremented by OPTENT3 */
     OPTENT3(0, "allicons",     OPT_FLAG,   NULL,                  
             &cmdlineP->allicons,       0 );
@@ -88,10 +89,9 @@ parseCommandLine ( int argc, char ** argv,
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
 
-    optParseOptions3( &argc, argv, opt, sizeof(opt), 0);
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
-
     if (argc-1 < 1) 
         cmdlineP->inputFilespec = "-";
     else
@@ -116,37 +116,37 @@ parseCommandLine ( int argc, char ** argv,
 
 
 static int 
-GetByte(void) {
+GetByte(FILE * const ifP) {
+
     int v;
    
-    if ((v = getc(ifp)) == EOF)
-    {
+    v = getc(ifP);
+    if (v == EOF)
         pm_error(er_read, infname);
-    }
    
     return v;
 }
+
+
    
 static short 
-GetShort(void) {
+GetShort(FILE * const ifP) {
+
     short v;
    
-    if (pm_readlittleshort(ifp, &v) == -1)
-    {
-        pm_error(er_read, infname);
-    }
-   
+    pm_readlittleshort(ifP, &v);
+
     return v;
 }
+
+
    
 static long 
-GetLong(void) {
+GetLong(FILE * const ifP) {
+
     long v;
    
-    if (pm_readlittlelong(ifp, &v) == -1)
-    {
-        pm_error(er_read, infname);
-    }
+    pm_readlittlelong(ifP, &v);
    
     return v;
 }
@@ -158,14 +158,18 @@ GetLong(void) {
  * functions.
  */
 static u1 
-readU1 (void) {
-    file_offset++;
-    return GetByte();
+readU1(FILE * const ifP) {
+
+    ++fileOffset;
+
+    return GetByte(ifP);
 }
 
+
+
 static u1 * 
-readU1String (int length)
-{
+readU1String (FILE *       const ifP,
+              unsigned int const length) {
    
     u1 * string;
     
@@ -173,150 +177,173 @@ readU1String (int length)
     if (string == NULL)
         pm_error("out of memory");
 
-    fread(string,sizeof(u1),length,ifp);
+    fread(string, sizeof(u1), length, ifP);
     string[length] = 0;
-    file_offset += length * sizeof(u1);
+    fileOffset += length * sizeof(u1);
+
     return string;
 }
 
+
+
 static u2 
-readU2 (void) {
-    file_offset +=2;
-    return GetShort();
+readU2 (FILE * const ifP) {
+
+    fileOffset +=2;
+
+    return GetShort(ifP);
 }
 
+
+
 static u4 
-readU4 (void) {
-    file_offset += 4;
-    return GetLong();
+readU4 (FILE * const ifP) {
+
+    fileOffset += 4;
+
+    return GetLong(ifP);
 }
 
+
+
 static IC_Entry 
-readICEntry (void) 
-{
-    IC_Entry entry;
+readICEntry(FILE * const ifP) {
+
+    IC_Entry entryP;
 
-    MALLOCVAR(entry);
+    MALLOCVAR(entryP);
 
-    if (entry == NULL)
+    if (entryP == NULL)
         pm_error("Unable to allcoate memory for IC entry");
 
-    entry->width         = readU1();
-    entry->height        = readU1();
-    entry->color_count   = readU1();
-    entry->reserved      = readU1();
-    entry->planes        = readU2();
-    entry->bitcount      = readU2();
-    entry->size_in_bytes = readU4();
-    entry->file_offset   = readU4();
-    entry->colors        = NULL;
-    entry->ih            = NULL;
-    entry->xorBitmap     = NULL;
-    entry->andBitmap     = NULL;
+    entryP->width         = readU1(ifP);
+    entryP->height        = readU1(ifP);
+    entryP->color_count   = readU1(ifP);
+    entryP->reserved      = readU1(ifP);
+    entryP->planes        = readU2(ifP);
+    entryP->bitcount      = readU2(ifP);
+    entryP->size_in_bytes = readU4(ifP);
+    entryP->file_offset   = readU4(ifP);
+    entryP->colors        = NULL;
+    entryP->ih            = NULL;
+    entryP->xorBitmap     = NULL;
+    entryP->andBitmap     = NULL;
     
-    return entry;
+    return entryP;
 }
 
 
 
 static IC_InfoHeader 
-readInfoHeader (IC_Entry entry) 
-{
-    IC_InfoHeader ih;
+readInfoHeader (FILE *   const ifP,
+                IC_Entry const entryP) {
+
+    IC_InfoHeader ihP;
 
-    MALLOCVAR(ih);
+    MALLOCVAR(ihP);
     
-    if (ih == NULL)
+    if (ihP == NULL)
         pm_error("Unable to allocate memory for info header");
 
-    ih->size            = readU4();
-    ih->width           = readU4();
-    ih->height          = readU4();
-    ih->planes          = readU2();
-    ih->bitcount        = readU2();
-    ih->compression     = readU4();
-    ih->imagesize       = readU4();
-    ih->x_pixels_per_m  = readU4();
-    ih->y_pixels_per_m  = readU4();
-    ih->colors_used     = readU4();
-    ih->colors_important = readU4();
+    ihP->size             = readU4(ifP);
+    ihP->width            = readU4(ifP);
+    ihP->height           = readU4(ifP);
+    ihP->planes           = readU2(ifP);
+    ihP->bitcount         = readU2(ifP);
+    ihP->compression      = readU4(ifP);
+    ihP->imagesize        = readU4(ifP);
+    ihP->x_pixels_per_m   = readU4(ifP);
+    ihP->y_pixels_per_m   = readU4(ifP);
+    ihP->colors_used      = readU4(ifP);
+    ihP->colors_important = readU4(ifP);
     
-    if (!entry->bitcount) entry->bitcount = ih->bitcount;
-    if (entry->color_count == 0 && 
-        entry->bitcount <= 8) entry->color_count = 256;
-    if (ih->compression) {
+    if (!entryP->bitcount)
+        entryP->bitcount = ihP->bitcount;
+    
+    if (entryP->color_count == 0 && entryP->bitcount <= 8)
+        entryP->color_count = 256;
+
+    if (ihP->compression) {
         pm_error("Can't handle compressed icons");
     }
-    return ih;
+    return ihP;
 }
 
-/*
- * I don't know why this isn't the same as the spec, it just <b>isn't</b>
- * The colors honestly seem to be stored BGR.  Bizarre.
- * 
- * I've checked this in the BMP code for bmptoppm and the gimp.  Guess the
- * spec I have is just plain wrong.
- */
+
+
 static IC_Color 
-readICColor (void) 
-{
-    IC_Color col;
+readICColor(FILE * const ifP)  {
+
+    IC_Color colorP;
 
-    MALLOCVAR(col);
+    MALLOCVAR(colorP);
 
-    if (col == NULL)
+    if (colorP == NULL)
         pm_error("Unable to allocate memory for color");
 
-    col->blue     = readU1();
-    col->green    = readU1();
-    col->red      = readU1();
-    col->reserved = readU1();
-    return col;
+    /* I don't know why this isn't the same as the spec, it just isn't.
+       The colors honestly seem to be stored BGR.  Bizarre.
+      
+       I've checked this in the BMP code for bmptoppm and the gimp.  Guess the
+       spec I have is just plain wrong.
+    */
+
+    colorP->blue     = readU1(ifP);
+    colorP->green    = readU1(ifP);
+    colorP->red      = readU1(ifP);
+    colorP->reserved = readU1(ifP);
+
+    return colorP;
 }
    
 
 
-/*
- * Depending on if the image is stored as 1bpp, 4bpp or 8bpp, the 
- * encoding mechanism is different.
- * 
- * 8bpp => 1 byte/palette index.
- * 4bpp => High Nibble, Low Nibble
- * 1bpp => 1 palette value per bit, high bit 1st.
- */
 static u1 * 
-read1Bitmap (int width, int height) 
-{
-    int tmp;
-    int xBytes;
+read1Bitmap (FILE *       const ifP,
+             unsigned int const width,
+             unsigned int const height) {
+
+    unsigned int row;
+    unsigned int xByteCt;
     u1 * bitmap;
-    int wt = width;
+    unsigned int wt;
 
     MALLOCARRAY(bitmap, width * height);
     if (bitmap == NULL)
         pm_error("out of memory");
 
-    wt >>= 3;
-    if (wt & 3) {
-        wt = (wt & ~3) + 4;
+    /* Depending on if the image is stored as 1bpp, 4bpp or 8bpp, the 
+       encoding mechanism is different.
+  
+       8bpp => 1 byte/palette index.
+       4bpp => High Nibble, Low Nibble
+       1bpp => 1 palette value per bit, high bit 1st.
+    */
+
+    wt = width >> 3;
+
+    if ((wt & 0x3) != 0) {
+        wt = (wt & ~0x3) + 4;
     }
-    xBytes = wt;
-    for (tmp = 0; tmp<height; tmp++ ) {
-        int x;
-        int rowByte = 0;
-        int xOrVal = 128;
-        u1 * row = readU1String(xBytes);
-        for (x = 0; x< width; x++) {
-            *(bitmap+((height-tmp-1)*width) + (x)) = 
-                (row[rowByte] & xOrVal) / xOrVal;
-            if (xOrVal == 1) {
-                xOrVal = 128;
-                rowByte++;
-            } else {
+    xByteCt = wt;
+
+    for (row = 0; row < height; ++row) {
+        u1 * const imgRow = readU1String(ifP, xByteCt);
+
+        unsigned int col;
+        unsigned int rowByte;
+        unsigned int xOrVal;
+        
+        for (col = 0, rowByte = 0, xOrVal = 0x80; col < width; ++col) {
+            *(bitmap+((height - row - 1) * width) + col) = 
+                (imgRow[rowByte] & xOrVal) / xOrVal;
+            if (xOrVal == 0x01) {
+                xOrVal = 0x80;
+                ++rowByte;
+            } else
                 xOrVal >>= 1;
-            }
         }
-        free(row);
+        free(imgRow);
     }
     return bitmap;
 }
@@ -324,43 +351,46 @@ read1Bitmap (int width, int height)
 
    
 static u1 * 
-read4Bitmap (int width, int height) 
-{
-    int tmp;
+read4Bitmap (FILE *       const ifP,
+             unsigned int const width,
+             unsigned int const height) {
+
+    unsigned int row;
     u1 * bitmap;
 
-    int wt = width;
-    int xBytes;
+    unsigned int wt;
+    unsigned int xByteCt;
 
     MALLOCARRAY(bitmap, width * height);
     if (bitmap == NULL)
         pm_error("out of memory");
 
+    wt = width >> 1;
 
-    wt >>= 1;
-    if (wt & 3) {
-        wt = (wt & ~3) + 4;
+    if (wt & 0x3) {
+        wt = (wt & ~0x3) + 4;
     }
-    xBytes = wt;
-    for (tmp = 0; tmp<height ; tmp++ ) {
-        int rowByte = 0;
-        int bottom = 1;
-        int x;
-        u1 * row = readU1String(xBytes);
-        for (x = 0; x< width; x++) {
-            /*
-             * 2 nibbles, 2 values.
-             */
+    xByteCt = wt;
+
+    for (row = 0; row < height; ++row) {
+        u1 * const imgRow = readU1String(ifP, xByteCt);
+
+        unsigned int rowByte;
+        bool bottom;
+        unsigned int col;
+        for (col = 0, rowByte = 0, bottom = true; col < width; ++col) {
+            /* 2 nibbles, 2 values */
             if (bottom) {
-                *(bitmap+((height-tmp-1)*width) + (x)) = 
-                    (row[rowByte] & 0xF0) >> 4;
+                *(bitmap + ((height - row - 1) * width) + col) = 
+                    (imgRow[rowByte] & 0xF0) >> 4;
             } else {
-                *(bitmap+((height-tmp-1)*width) + (x)) = (row[rowByte] & 0xF);
-                rowByte++;
+                *(bitmap + ((height - row -1) * width) + col) =
+                    (imgRow[rowByte] & 0xF);
+                ++rowByte;
             }
             bottom = !bottom;
         }
-    free(row);
+        free(imgRow);
     }
     return bitmap;
 }
@@ -368,52 +398,57 @@ read4Bitmap (int width, int height)
 
    
 static u1 * 
-read8Bitmap (int width, int height) 
-{
-    int tmp;
-    unsigned int xBytes;
-    unsigned int wt = width;
+read8Bitmap (FILE *       const ifP,
+             unsigned int const width,
+             unsigned int const height) {
+
+    unsigned int row;
+    unsigned int xByteCt;
+    unsigned int wt;
     u1 * bitmap;
    
     MALLOCARRAY(bitmap, width * height);
     if (bitmap == NULL)
         pm_error("out of memory");
 
-    if (wt & 3) {
-        wt = (wt & ~3) + 4;
+    wt = width;
+    if (wt & 0x3) {
+        wt = (wt & ~0x3) + 4;
     }
-    xBytes = wt;
-    for (tmp = 0; tmp<height ; tmp++ ) {
-        int rowByte = 0;
-        int x;
-        u1 * row = readU1String(xBytes);
-        for ( x = 0; x< width; x++) {
-            *(bitmap+((height-tmp-1)*width) + (x)) = row[rowByte];
-            rowByte++;
-        }
-        free(row);
+    xByteCt = wt;
+
+    for (row = 0; row < height; ++row) {
+        u1 * imgRow = readU1String(ifP, xByteCt);
+
+        unsigned int rowByte;
+        unsigned int col;
+        for (col = 0, rowByte = 0; col < width; ++col)
+            *(bitmap + ((height - row - 1) * width) + col) = imgRow[rowByte++];
+
+        free(imgRow);
     }
     return bitmap;
 }
 
 
 
-/*
- * Read a true color bitmap. (24/32 bits)
- * 
- * The output routine deplanarizes it for us, we keep it flat here.
- */
 static u1 *
-readXBitmap (int const width, 
-             int const height, 
-             int const bpp) {
-    int          const bytes  = bpp >> 3;
-    unsigned int const xBytes = width * bytes;
+readXBitmap (FILE *       const ifP,
+             unsigned int const width, 
+             unsigned int const height, 
+             unsigned int const bpp) {
+/*----------------------------------------------------------------------------
+  Read a true color bitmap. (24/32 bits)
+  
+  The output routine deplanarizes it for us, we keep it flat here.
+-----------------------------------------------------------------------------*/
+    unsigned int const byteCt = bpp >> 3;
+    unsigned int const xByteCt = width * byteCt;
 
     u1 * bitmap;
         /* remember - bmp (dib) stored upside down, so reverse */
 
-    MALLOCARRAY(bitmap, bytes * width * height);
+    MALLOCARRAY(bitmap, byteCt * width * height);
     if (bitmap == NULL)
         pm_error("out of memory allocating bitmap array");
 
@@ -421,12 +456,12 @@ readXBitmap (int const width,
         unsigned int i;
         u1 * bitcurptr;
 
-        for (i = 0, bitcurptr = &bitmap[bytes * width * (height-1)];
+        for (i = 0, bitcurptr = &bitmap[byteCt * width * (height-1)];
              i < height; 
-             ++i, bitcurptr -= xBytes) {
+             ++i, bitcurptr -= xByteCt) {
 
-            u1 * const row = readU1String(xBytes);
-            memcpy(bitcurptr, row, xBytes);
+            u1 * const row = readU1String(ifP, xByteCt);
+            memcpy(bitcurptr, row, xByteCt);
             free(row);
         }
     }
@@ -436,80 +471,70 @@ readXBitmap (int const width,
 
 
 static MS_Ico 
-readIconFile (bool const verbose) {
-    int iter,iter2;
+readIconFile(FILE * const ifP,
+             bool   const verbose) {
+
+    unsigned int i;
 
     MS_Ico MSIconData;
 
     MALLOCVAR(MSIconData);
    
-    /*
-     * reserved - should equal 0.
-     */
-    MSIconData->reserved = readU2();
-    /*
-     * Type - should equal 1
-     */
-    MSIconData->type     = readU2();
-    /*
-     * count - no of icons in file..
-     */
-    MSIconData->count    = readU2();
-    /*
-     * Allocate "count" array of entries.
-     */
+    MSIconData->reserved = readU2(ifP);  /* should be 0 */
+    MSIconData->type     = readU2(ifP);  /* should be 1 */
+    MSIconData->count    = readU2(ifP);  /* # icons in file */
+
     if (verbose) 
         pm_message("Icon file contains %d icons.", MSIconData->count);
 
     MALLOCARRAY(MSIconData->entries, MSIconData->count);
     if (MSIconData->entries == NULL)
         pm_error("out of memory");
-    /*
-     * Read in each of the entries
-     */
-    for (iter = 0;iter < MSIconData->count ; iter++ ) {
-        MSIconData->entries[iter] = readICEntry();
-    }
-    /* After that, we have to read in the infoheader, color map (if
-     * any) and the actual bit/pix maps for the icons.  
-     */
+
+    /* Read in each of the entries */
+    for (i = 0; i < MSIconData->count; ++i)
+        MSIconData->entries[i] = readICEntry(ifP);
+
+    /* Read in the infoheader, color map (if any) and the actual bit/pix maps
+       for the icons.
+    */
     if (verbose) 
-        fprintf (stderr,"#\tColors\tBPP\tWidth\tHeight\n");
-    for (iter = 0;iter < MSIconData->count ; iter++ ) {
-        int bpp;
-        MSIconData->entries[iter]->ih =
-            readInfoHeader (MSIconData->entries[iter]);
+        pm_message("#\tColors\tBPP\tWidth\tHeight\n");
+
+    for (i = 0; i < MSIconData->count; ++i) {
+        unsigned int bpp;  /* bits per pixel */
+
+        MSIconData->entries[i]->ih =
+            readInfoHeader(ifP, MSIconData->entries[i]);
        
-        /* What's the bits per pixel? */
-        bpp = MSIconData->entries[iter]->bitcount; 
+        bpp = MSIconData->entries[i]->bitcount; 
+
         /* Read the palette, if appropriate */
         switch (bpp) {
         case 24:
         case 32:
             /* 24/32 bpp icon has no palette */
             break;
-        default:
-            MALLOCARRAY(MSIconData->entries[iter]->colors, 
-                        MSIconData->entries[iter]->color_count);
-            if (MSIconData->entries[iter]->colors == NULL)
+        default: {
+            unsigned int j;
+
+            MALLOCARRAY(MSIconData->entries[i]->colors, 
+                        MSIconData->entries[i]->color_count);
+            if (MSIconData->entries[i]->colors == NULL)
                 pm_error("out of memory");
 
-            for (iter2 = 0;
-                 iter2 < MSIconData->entries[iter]->color_count ; 
-                 iter2++ ) {
-                MSIconData->entries[iter]->colors[iter2] = readICColor();
-            }
-            break;
+            for (j = 0; j < MSIconData->entries[i]->color_count; ++j)
+                MSIconData->entries[i]->colors[j] = readICColor(ifP);
+        }
         }
         if (verbose) {
-            char cols_text[10];
-            sprintf (cols_text, "%d", MSIconData->entries[iter]->color_count);
-            fprintf (stderr,
-                     "%d\t%s\t%d\t%d\t%d\n", iter,
-                     MSIconData->entries[iter]->color_count ? 
-                     cols_text : "TRUE",
-                     bpp, MSIconData->entries[iter]->width, 
-                     MSIconData->entries[iter]->height);
+            char colsText[10];
+            sprintf (colsText, "%d", MSIconData->entries[i]->color_count);
+            pm_message("%d\t%s\t%d\t%d\t%d\n", i,
+                       MSIconData->entries[i]->color_count ? 
+                       colsText : "TRUE",
+                       bpp, MSIconData->entries[i]->width, 
+                       MSIconData->entries[i]->height);
         }
         /* Pixels are stored bottom-up, left-to-right. Pixel lines are
          * padded with zeros to end on a 32bit (4byte) boundary. Every
@@ -528,35 +553,40 @@ readIconFile (bool const verbose) {
              */
             switch (bpp) {
             case 1:
-                MSIconData->entries[iter]->xorBitmap = 
-                    read1Bitmap(MSIconData->entries[iter]->width,
-                                MSIconData->entries[iter]->height);
+                MSIconData->entries[i]->xorBitmap = 
+                    read1Bitmap(ifP,
+                                MSIconData->entries[i]->width,
+                                MSIconData->entries[i]->height);
                 break;
             case 4:
-                MSIconData->entries[iter]->xorBitmap = 
-                    read4Bitmap(MSIconData->entries[iter]->width,
-                                MSIconData->entries[iter]->height);
+                MSIconData->entries[i]->xorBitmap = 
+                    read4Bitmap(ifP,
+                                MSIconData->entries[i]->width,
+                                MSIconData->entries[i]->height);
                 break;
             case 8:
-                MSIconData->entries[iter]->xorBitmap = 
-                    read8Bitmap(MSIconData->entries[iter]->width,
-                                MSIconData->entries[iter]->height);
+                MSIconData->entries[i]->xorBitmap = 
+                    read8Bitmap(ifP,
+                                MSIconData->entries[i]->width,
+                                MSIconData->entries[i]->height);
                 break;
             case 24:
             case 32:
-                MSIconData->entries[iter]->xorBitmap = 
-                    readXBitmap(MSIconData->entries[iter]->width,
-                                MSIconData->entries[iter]->height,bpp);
+                MSIconData->entries[i]->xorBitmap = 
+                    readXBitmap(ifP,
+                                MSIconData->entries[i]->width,
+                                MSIconData->entries[i]->height,bpp);
                 break;
             default:
-                pm_error("Uncatered bit depth %d",bpp);
+                pm_error("Uncatered bit depth %u", bpp);
             }
             /*
              * Read AND Bitmap
              */
-            MSIconData->entries[iter]->andBitmap = 
-                read1Bitmap(MSIconData->entries[iter]->width,
-                            MSIconData->entries[iter]->height);
+            MSIconData->entries[i]->andBitmap = 
+                read1Bitmap(ifP,
+                            MSIconData->entries[i]->width,
+                            MSIconData->entries[i]->height);
         }
       
     }
@@ -566,15 +596,14 @@ readIconFile (bool const verbose) {
 
 
 static char * 
-trimOutputName(const char inputName[])
-{
+trimmedOutputName(const char inputName[]) {
     /*
      * Just trim off the final ".ppm", if there is one, else return as is.
      * oh, for =~ ... :)
      */
-    char * outFile = strdup(inputName);
-    if (streq(outFile + (strlen (outFile) - 4), ".ppm")) {
-        *(outFile + (strlen (outFile) - 4)) = 0;
+    char * const outFile = strdup(inputName);
+    if (streq(outFile + (strlen(outFile) - 4), ".ppm")) {
+        *(outFile + (strlen(outFile) - 4)) = 0;
     }
     return outFile;
 
@@ -585,29 +614,34 @@ trimOutputName(const char inputName[])
 static int 
 getBestQualityIcon(MS_Ico MSIconData)
 {
-    int x,best,best_size,best_bpp,bpp,size;
-    IC_Entry entry;
-
-    best_size = best_bpp = 0;
-    for (x = 0; x < MSIconData->count; x++) {
-        entry =  MSIconData->entries[x];
-        size = entry->width * entry->height;
-        bpp  = entry->bitcount ? entry->bitcount : entry->ih->bitcount;
-        if (size > best_size) {
-            best = x;
-            best_size = size;
-        } else if (size == best_size && bpp > best_bpp) {
-            best = x;
-            best_bpp = bpp;
+    unsigned int i;
+    unsigned int best;
+    unsigned int bestSize;
+    unsigned int bestBpp;
+
+    for (i = 0, bestSize = 0, bestBpp = 0; i < MSIconData->count; ++i) {
+        IC_Entry const entryP = MSIconData->entries[i];
+        unsigned int const size = entryP->width * entryP->height;
+        unsigned int const bpp  =
+            entryP->bitcount ? entryP->bitcount : entryP->ih->bitcount;
+
+        if (size > bestSize) {
+            best = i;
+            bestSize = size;
+        } else if (size == bestSize && bpp > bestBpp) {
+            best = i;
+            bestBpp = bpp;
         }
     }
     return best;
 }
 
+
+
 static void
 writeXors(FILE *   const multiOutF,
-          char           outputFileBase[], 
-          IC_Entry const entry,
+          char *   const outputFileBase,
+          IC_Entry const entryP,
           int      const entryNum,
           bool     const multiple, 
           bool     const xor) {
@@ -625,85 +659,79 @@ writeXors(FILE *   const multiOutF,
    we are to open a file using outputFileBase[] and 'entryNum' and 'xor'
    to derive its name, and close it afterward.
 -----------------------------------------------------------------------------*/
-    FILE * outF;
-    pixel ** ppm_array;
-    int row;
-    int pel_size;
-    const char *outputFile;
-    int maxval;
-    int forcetext;
+    FILE * ofP;
+    pixel ** pixArray;
+    unsigned int row;
+    const char * outputFileName;
 
     if (multiOutF) {
-        outF = multiOutF;
-        outputFile = strdup("");
+        ofP = multiOutF;
+        outputFileName = strdup("");
     } else {
         if (outputFileBase) {
             if (multiple) {
-                asprintfN(&outputFile, "%s%s_%d.ppm",
-                          outputFileBase,(xor ? "_xor" : ""), entryNum);
+                pm_asprintf(&outputFileName, "%s%s_%d.ppm",
+                            outputFileBase,(xor ? "_xor" : ""), entryNum);
             } else { 
-                asprintfN(&outputFile, "%s%s.ppm",
-                          outputFileBase,(xor ? "_xor" : ""));
+                pm_asprintf(&outputFileName, "%s%s.ppm",
+                            outputFileBase,(xor ? "_xor" : ""));
             }
         } else
-            outputFile = strdup("-");
+            outputFileName = strdup("-");
         
-        outF = pm_openw(outputFile);
+        ofP = pm_openw(outputFileName);
     }
     /* 
-     * allocate an array to save the bmp data into.
-     * note that entry->height will be 1/2 entry->ih->height,
-     * as the latter adds "and" and "xor" height.
-     */
-    ppm_array = ppm_allocarray(entry->width, entry->height);
-    for (row=0; row < entry->height; row++) {
-        u1 * xorRow;
-        int col;
-        switch (entry->bitcount) {
+       Allocate an array to save the bmp data into.
+       note that entry->height will be 1/2 entry->ih->height,
+       as the latter adds "and" and "xor" height.
+    */
+    pixArray = ppm_allocarray(entryP->width, entryP->height);
+    for (row = 0; row < entryP->height; ++row) {
+        switch (entryP->bitcount) {
         case 24:
-        case 32:
-            pel_size = entry->bitcount >> 3;
-            xorRow = entry->xorBitmap + row * entry->width * pel_size;
-            for (col=0; col < entry->width*pel_size;col+=pel_size) {
-                PPM_ASSIGN(ppm_array[row][col/pel_size],
-                           xorRow[col+2],xorRow[col+1],xorRow[col]);
-            }
-            break;
-        default:
-            xorRow = entry->xorBitmap + row * entry->width;
-            for (col=0; col < entry->width; col++) {
-                int colorIndex;
-                IC_Color color;
-                colorIndex  = xorRow[col];
-                color = entry->colors[colorIndex];
-                PPM_ASSIGN(ppm_array[row][col],
-                           color->red,color->green,color->blue);
+        case 32: {
+            unsigned int const pixelSize = entryP->bitcount >> 3;
+            u1 * const xorRow =
+                entryP->xorBitmap + row * entryP->width * pixelSize;
+            unsigned int col;
+            for (col = 0; col < entryP->width * pixelSize; col += pixelSize)
+                PPM_ASSIGN(pixArray[row][col/pixelSize],
+                           xorRow[col+2], xorRow[col+1], xorRow[col]);
+        } break;
+        default: {
+            u1 * const xorRow = entryP->xorBitmap + row * entryP->width;
+            unsigned int col;
+            for (col = 0; col < entryP->width; ++col) {
+                unsigned int const colorIndex = xorRow[col];
+                IC_Color const colorP = entryP->colors[colorIndex];
+                PPM_ASSIGN(pixArray[row][col],
+                           colorP->red, colorP->green, colorP->blue);
             }
-            break;
+        } break;
         }
     }    
     
-    maxval = 255;
-    forcetext = 0;
-
-    ppm_writeppm(outF,ppm_array,entry->width, entry->height, 
-                 (pixval) maxval, forcetext);
-    ppm_freearray(ppm_array,entry->height);
+    ppm_writeppm(ofP, pixArray, entryP->width, entryP->height, 
+                 255 /* maxval */, false /* text */);
+    ppm_freearray(pixArray, entryP->height);
 
-    strfree(outputFile);
+    pm_strfree(outputFileName);
     
     if (!multiOutF) 
-        pm_close(outF);
+        pm_close(ofP);
 }
             
 
 
 static void
-writeAnds(FILE * const multiOutF, 
-          char outputFileBase[], IC_Entry const entry, int const entryNum, 
-          bool multiple) {
+writeAnds(FILE *       const multiOutF, 
+          char         const outputFileBase[],
+          IC_Entry     const entryP,
+          unsigned int const entryNum, 
+          bool         const multiple) {
 /*----------------------------------------------------------------------------
-   Write the "and" image (i.e. the alpha mask) of the image 'IC_Entry' out.
+   Write the "and" image (i.e. the alpha mask) of the image *entryP out.
 
    'multiple' means this is one of multiple images that are being written.
    'entryNum' is the sequence number within the winicon file of the image
@@ -714,114 +742,122 @@ writeAnds(FILE * const multiOutF,
    we are to open a file using outputFileBase[] and 'entryNum' and 'xor'
    to derive its name, and close it afterward.
 -----------------------------------------------------------------------------*/
-    FILE * outF;
-    bit ** pbm_array;
-    u1 * andRow;
-    int row;
+    FILE * ofP;
+    bit ** bitArray;
+    unsigned int row;
 
     if (multiOutF)
-        outF = multiOutF;
+        ofP = multiOutF;
     else {
-        const char *outputFile;
+        const char * outputFileName;
 
         assert(outputFileBase);
 
         if (multiple) 
-            asprintfN(&outputFile, "%s_and_%d.pbm", outputFileBase, entryNum);
+            pm_asprintf(&outputFileName, "%s_and_%u.pbm",
+                        outputFileBase, entryNum);
         else 
-            asprintfN(&outputFile, "%s_and.pbm", outputFileBase);
-        outF = pm_openw(outputFile);
-        strfree(outputFile);
+            pm_asprintf(&outputFileName, "%s_and.pbm", outputFileBase);
+        ofP = pm_openw(outputFileName);
+        pm_strfree(outputFileName);
     }
-    pbm_array = pbm_allocarray(entry->width, entry->height);
-    for (row=0; row < entry->height; row++) {
-        int col;
-        andRow = entry->andBitmap + row * entry->width;
-        for (col=0; col < entry->width; col++) {
+    bitArray = pbm_allocarray(entryP->width, entryP->height);
+    for (row = 0; row < entryP->height; ++row) {
+        u1 * const andRow = entryP->andBitmap + row * entryP->width;
+        unsigned int col;
+        for (col = 0; col < entryP->width; ++col) {
             /* Note: black is transparent in a Netpbm alpha mask */
-            pbm_array[row][col] = andRow[col] ? PBM_BLACK: PBM_WHITE;
+            bitArray[row][col] = andRow[col] ? PBM_BLACK: PBM_WHITE;
         }
     }
 
-    pbm_writepbm(outF, pbm_array, entry->width, entry->height, 0);
+    pbm_writepbm(ofP, bitArray, entryP->width, entryP->height, 0);
 
-    pbm_freearray(pbm_array, entry->height);
+    pbm_freearray(bitArray, entryP->height);
     if (!multiOutF)
-        pm_close (outF);     
+        pm_close(ofP);
 }
 
 
 
 static void
-openMultiXor(char          outputFileBase[], 
+openMultiXor(char    const outputFileBase[], 
              bool    const writeands,
              FILE ** const multiOutFP) {
 
-    const char *outputFile;
+    const char * outputFileName;
 
     if (outputFileBase) {
-        asprintfN(&outputFile, "%s%s.ppm",
-                  outputFileBase, (writeands ? "_xor" : ""));
+        pm_asprintf(&outputFileName, "%s%s.ppm",
+                    outputFileBase, (writeands ? "_xor" : ""));
     } else
-        outputFile = strdup("-");
+        outputFileName = strdup("-");
 
-    /*
-     * Open the output file now, it'll stay open the whole time.
-     */
-    *multiOutFP = pm_openw(outputFile);
+    *multiOutFP = pm_openw(outputFileName);
 
-    strfree(outputFile);
+    pm_strfree(outputFileName);
 }
 
 
 
 static void
-openMultiAnd(char outputFileBase[], FILE ** const multiAndOutFP) {
+openMultiAnd(char    const outputFileBase[],
+             FILE ** const multiAndOutFP) {
 
-    const char *outputFile;
+    const char * outputFileName;
 
     assert(outputFileBase);
 
-    asprintfN(&outputFile, "%s_and.pbm", outputFileBase);
+    pm_asprintf(&outputFileName, "%s_and.pbm", outputFileBase);
     
-    *multiAndOutFP = pm_openw(outputFile);
+    *multiAndOutFP = pm_openw(outputFileName);
 
-    strfree(outputFile);
+    pm_strfree(outputFileName);
 }
 
-static void free_iconentry(IC_Entry entry) {
-    int x;
-    if (entry->colors && entry->color_count) {
-        for (x=0;x<entry->color_count;x++) free(entry->colors[x]);
-        free(entry->colors);
+
+
+static void
+freeIconentry(IC_Entry const entryP) {
+
+    if (entryP->colors && entryP->color_count) {
+        unsigned int i;
+        for (i = 0; i <entryP->color_count; ++i)
+            free(entryP->colors[i]);
+        free(entryP->colors);
     }
-    if (entry->andBitmap) free(entry->andBitmap);
-    if (entry->xorBitmap) free(entry->xorBitmap);
-    if (entry->ih) free(entry->ih);
-    free(entry);
+    if (entryP->andBitmap) free(entryP->andBitmap);
+    if (entryP->xorBitmap) free(entryP->xorBitmap);
+    if (entryP->ih) free(entryP->ih);
+    free(entryP);
 }
 
-static void free_icondata(MS_Ico MSIconData)
-{
-    int x;
-    for (x=0;x<MSIconData->count;x++) {
-    free_iconentry(MSIconData->entries[x]);
-    }
-    free(MSIconData);
+
+
+static void
+freeIcondata(MS_Ico const MSIconDataP) {
+
+    unsigned int i;
+    for (i = 0; i < MSIconDataP->count; ++i)
+        freeIconentry(MSIconDataP->entries[i]);
+
+    free(MSIconDataP);
 }
 
 
+
 int 
-main(int argc, char *argv[]) {
+main(int argc, const char *argv[]) {
 
     struct cmdlineInfo cmdline;
-    int startEntry, endEntry;
-    MS_Ico MSIconData;
+    FILE * ifP;
+    unsigned int startEntry, endEntry;
+    MS_Ico MSIconDataP;
     char * outputFileBase;
     FILE * multiOutF;
     FILE * multiAndOutF;
    
-    ppm_init (&argc, argv);
+    pm_proginit(&argc, argv);
 
     parseCommandLine(argc, argv, &cmdline);
 
@@ -832,13 +868,13 @@ main(int argc, char *argv[]) {
     if (streq(cmdline.outputFilespec, "-"))
         outputFileBase = NULL;
     else
-        outputFileBase = trimOutputName(cmdline.outputFilespec);
+        outputFileBase = trimmedOutputName(cmdline.outputFilespec);
 
-    ifp = pm_openr(cmdline.inputFilespec);
+    ifP = pm_openr(cmdline.inputFilespec);
 
     infname = cmdline.inputFilespec;
 
-    MSIconData = readIconFile(cmdline.verbose);
+    MSIconDataP = readIconFile(ifP, cmdline.verbose);
     /*
      * Now we've read the icon file in (Hopefully! :)
      * Go through each of the entries, and write out files of the
@@ -852,18 +888,15 @@ main(int argc, char *argv[]) {
     /*
      * If allicons is set, we want everything, if not, just go through once.
      */
-    startEntry = 0;
-    if (cmdline.allicons) {
-        endEntry = MSIconData->count;
-    } else {
-        endEntry = 1;
-    }
-    /*
-     * If bestqual is set, find the icon with highest size & bpp.
-     */
     if (cmdline.bestqual) {
-        startEntry = getBestQualityIcon(MSIconData);
+        startEntry = getBestQualityIcon(MSIconDataP);
         endEntry = startEntry+1;
+    } else {
+        startEntry = 0;
+        if (cmdline.allicons)
+            endEntry = MSIconDataP->count;
+        else
+            endEntry = 1;
     }
    
     if (cmdline.multippm) 
@@ -877,24 +910,25 @@ main(int argc, char *argv[]) {
         multiAndOutF = NULL;
 
     {
-        int entryNum;
+        unsigned int entryNum;
 
-        for (entryNum = startEntry ; entryNum < endEntry ; entryNum++ ) {
-            IC_Entry const entry = MSIconData->entries[entryNum];
+        for (entryNum = startEntry; entryNum < endEntry; ++entryNum) {
+            IC_Entry const entryP = MSIconDataP->entries[entryNum];
 
-            writeXors(multiOutF, outputFileBase, entry, entryNum, 
+            writeXors(multiOutF, outputFileBase, entryP, entryNum, 
                       cmdline.allicons, cmdline.writeands);
             if (cmdline.writeands)
                 writeAnds(multiAndOutF, outputFileBase, 
-                          entry, entryNum, cmdline.allicons);
+                          entryP, entryNum, cmdline.allicons);
         }
     }
     if (multiOutF)
-        pm_close (multiOutF);    
+        pm_close(multiOutF);    
     if (multiAndOutF)
         pm_close(multiAndOutF);
     
     /* free up the image data here. */
-    free_icondata(MSIconData);
+    freeIcondata(MSIconDataP);
+
     return 0;
 }
diff --git a/converter/ppm/xim.h b/converter/ppm/xim.h
index ffe60fb6..27556b30 100644
--- a/converter/ppm/xim.h
+++ b/converter/ppm/xim.h
@@ -112,7 +112,7 @@ typedef struct XimAsciiHeader {
 /* Note:
 * - All data is in char's in order to maintain easily portability
 *   across machines, and some human readibility.
-* - Images may be stored as pixmaps (8 bits/pixel) or as seperate
+* - Images may be stored as pixmaps (8 bits/pixel) or as separate
 *   red, green, blue channel data (24+ bits/pixel).
 * - An alpha channel is optional and is found after every num_channels
 *   of data.
diff --git a/converter/ppm/ximtoppm.c b/converter/ppm/ximtoppm.c
index 15589c16..ce5e6396 100644
--- a/converter/ppm/ximtoppm.c
+++ b/converter/ppm/ximtoppm.c
@@ -56,7 +56,7 @@ parseCommandLine(int argc, char ** argv,
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
 
-    optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
+    pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and all of *cmdlineP. */
 
     if (!alphaoutSpec)
@@ -208,7 +208,7 @@ ReadImageChannel(FILE *         const infp,
             }
             marker += i;
         }
-        /* return to the begining of the next image's bufffer */
+        /* return to the beginning of the next image's bufffer */
         if (fseek(infp, marker, 0) == -1) {
             pm_message("ReadImageChannel: can't fseek to location in image buffer" );
             return(0);
diff --git a/converter/ppm/xpmtoppm.c b/converter/ppm/xpmtoppm.c
index 235c3867..27f17931 100644
--- a/converter/ppm/xpmtoppm.c
+++ b/converter/ppm/xpmtoppm.c
@@ -1,43 +1,19 @@
-/* xpmtoppm.c - read an X11 pixmap file and produce a portable pixmap
-**
-** Copyright (C) 1991 by Jef Poskanzer.
-**
-** Permission to use, copy, modify, and distribute this software and its
-** documentation for any purpose and without fee is hereby granted, provided
-** that the above copyright notice appear in all copies and that both that
-** copyright notice and this permission notice appear in supporting
-** documentation.  This software is provided "as is" without express or
-** implied warranty.
-**
-** Upgraded to handle XPM version 3 by
-**   Arnaud Le Hors (lehors@mirsa.inria.fr)
-**   Tue Apr 9 1991
-**
-** Rainer Sinkwitz sinkwitz@ifi.unizh.ch - 21 Nov 91:
-**  - Bug fix, no advance of read ptr, would not read 
-**    colors like "ac c black" because it would find 
-**    the "c" of "ac" and then had problems with "c"
-**    as color.
-**    
-**  - Now understands multiword X11 color names
-**  
-**  - Now reads multiple color keys. Takes the color
-**    of the hightest available key. Lines no longer need
-**    to begin with key 'c'.
-**    
-**  - expanded line buffer to from 500 to 2048 for bigger files
+/* xpmtoppm.c - convert XPM file (X11 pixmap) to PPM
+
+   Copyright and history information is at end of file
 */
 
 #define _BSD_SOURCE   /* Make sure strdup() is in string.h */
 #define _XOPEN_SOURCE 500  /* Make sure strdup() is in string.h */
 
+#include <assert.h>
 #include <string.h>
 
 #include "pm_c_util.h"
-#include "ppm.h"
+#include "mallocvar.h"
 #include "shhopt.h"
 #include "nstring.h"
-#include "mallocvar.h"
+#include "ppm.h"
 
 #define MAX_LINE (8 * 1024)
   /* The maximum size XPM input line we can handle. */
@@ -47,72 +23,321 @@
 
 const char *xpmColorKeys[] =
 {
- "s",					/* key #1: symbol */
- "m",					/* key #2: mono visual */
- "g4",					/* key #3: 4 grays visual */
- "g",					/* key #4: gray visual */
- "c",					/* key #5: color visual */
+ "s",                   /* key #1: symbol */
+ "m",                   /* key #2: mono visual */
+ "g4",                  /* key #3: 4 grays visual */
+ "g",                   /* key #4: gray visual */
+ "c",                   /* key #5: color visual */
 };
 
-struct cmdline_info {
+struct cmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
-    char *input_filespec;  /* Filespecs of input files */
-    char *alpha_filename;
+    const char * input_filespec;  /* Filespecs of input files */
+    const char * alpha_filename;
     int alpha_stdout;
     int verbose;
 };
 
 
-static int verbose;
+static bool verbose;
+
 
 
 static void
-parse_command_line(int argc, char ** argv,
-                   struct cmdline_info *cmdline_p) {
+parseCommandLine(int argc, char ** argv,
+                 struct cmdlineInfo *cmdlineP) {
 /*----------------------------------------------------------------------------
    Note that the file spec array we return is stored in the storage that
    was passed to us as the argv array.
 -----------------------------------------------------------------------------*/
-    optStruct *option_def = malloc(100*sizeof(optStruct));
+    optEntry * option_def;
         /* Instructions to OptParseOptions2 on how to parse our options.
          */
-    optStruct2 opt;
+    optStruct3 opt;
 
     unsigned int option_def_index;
 
-    option_def_index = 0;   /* incremented by OPTENTRY */
-    OPTENTRY(0,   "alphaout",   OPT_STRING, &cmdline_p->alpha_filename, 0);
-    OPTENTRY(0,   "verbose",    OPT_FLAG,   &cmdline_p->verbose,        0);
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    option_def_index = 0;   /* incremented by OPTENT3 */
+    OPTENT3(0,   "alphaout",   OPT_STRING, &cmdlineP->alpha_filename,
+            NULL, 0);
+    OPTENT3(0,   "verbose",    OPT_FLAG,   &cmdlineP->verbose,
+            NULL, 0);
 
-    cmdline_p->alpha_filename = NULL;
-    cmdline_p->verbose = FALSE;
+    cmdlineP->alpha_filename = NULL;
+    cmdlineP->verbose = FALSE;
 
     opt.opt_table = option_def;
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = TRUE;  /* We may have parms that are negative numbers */
 
-    optParseOptions2(&argc, argv, opt, 0);
-        /* Uses and sets argc, argv, and some of *cmdline_p and others. */
+    pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
     if (argc - 1 == 0)
-        cmdline_p->input_filespec = NULL;  /* he wants stdin */
+        cmdlineP->input_filespec = NULL;  /* he wants stdin */
     else if (argc - 1 == 1)
-        cmdline_p->input_filespec = strdup(argv[1]);
+        cmdlineP->input_filespec = strdup(argv[1]);
     else 
         pm_error("Too many arguments.  The only argument accepted\n"
                  "is the input file specification");
 
-    if (cmdline_p->alpha_filename && 
-        streq(cmdline_p->alpha_filename, "-"))
-        cmdline_p->alpha_stdout = TRUE;
+    if (cmdlineP->alpha_filename && 
+        streq(cmdlineP->alpha_filename, "-"))
+        cmdlineP->alpha_stdout = TRUE;
     else 
-        cmdline_p->alpha_stdout = FALSE;
+        cmdlineP->alpha_stdout = FALSE;
+
+}
+
+
+
+struct ColorNameHashTableEntry {
+/*----------------------------------------------------------------------------
+   An entry in the color name hash table.  It maps a color name to a
+   color, or is empty.
+-----------------------------------------------------------------------------*/
+    bool empty;
+    char colorName[3];
+        /* Actual length 0-3.  NOT NUL-terminated */
+    pixel color;
+};
+
+
+
+typedef struct {
+/*----------------------------------------------------------------------------
+   This is a color map which is primarily a hash table that maps an XPM
+   color name to a color.  An XPM color name is a 0-3 character name that
+   appears in the raster of an XPM image to uniquely identify a color.
+   The header of the XPM contains a listing of all the color names that
+   appear in the raster, identifying a color for each.
+
+   We represent a color as a 'pixel'.
+-----------------------------------------------------------------------------*/
+    unsigned int nameSize;
+        /* Size of color names in this hash.  0-3 */
+    struct ColorNameHashTableEntry * transparentP;
+        /* The element of 'table' that is for the transparent color.
+           NULL if there is none.
+        */
+
+    /* This is an internally chained hash table, i.e. there are no linked
+       lists.  You use the hash function to get an index into the hash table.
+       If the entry indexed by that is not for the color name you're looking
+       for, you look at the next entry down, and keep going down until you
+       either find the color name you're looking for or hit an empty entry.
+
+       So that we never run out of space for new color names, we make the
+       creator of the hash table tell us the maximum number of colors there
+       will be.  We allocate twice that size in order to reduce average hash
+       chain length.
+    */
+    unsigned int size;
+    struct ColorNameHashTableEntry * table;
+} ColorNameHash;
+
+
+
+static ColorNameHash *
+hash_create(unsigned int const nColors,
+            unsigned int const nameSize) {
+
+    ColorNameHash * hashP;
+
+    MALLOCVAR_NOFAIL(hashP);
+
+    hashP->nameSize = nameSize;
+
+    hashP->size = nColors * 2;
+
+    MALLOCARRAY(hashP->table, hashP->size);
+
+    if (!hashP->table)
+        pm_error("Failed to allocate memory for a %u-entry "
+                 "color name hash table.", hashP->size);
+
+    {
+        unsigned int i;
+        for (i = 0; i < hashP->size; ++i)
+            hashP->table[i].empty = true;
+    }
+
+    hashP->transparentP = NULL;
+
+    return hashP;
+}
+
+
+
+static void
+hash_destroy(ColorNameHash * const hashP) {
+
+    free(hashP->table);
+
+    free(hashP);
+}
+
+
+
+static unsigned int
+hashColorName(const char * const name,
+              unsigned int const size,
+              unsigned int const hashTableSize) {
+/*----------------------------------------------------------------------------
+   Return the hash value (initial index into the color name hash table)
+   for the color name 'name', which is 'size' characters long.  The hash
+   is to be in the range [0, hashTableSize).
+-----------------------------------------------------------------------------*/
+    /* I have no idea if this is an appropriate hash function.  I borrowed
+       it from pnm_hashTuple()
+    */
+
+    unsigned int const hash_factor[] = {1, 33, 33*33};
+
+    unsigned int i;
+    unsigned int hash;
 
+    hash = 0;  /* initial value */
+    for (i = 0; i < size; ++i) {
+        hash += name[i] * hash_factor[i];
+    }
+    hash %= hashTableSize;
+    return hash;
+}
+
+
+
+static bool
+entryMatch(struct ColorNameHashTableEntry const entry,
+           const char *                   const name,
+           unsigned int                   const size) {
+
+    if (entry.empty)
+        return true;
+
+    assert(size <= ARRAY_SIZE(entry.colorName));
+
+    {
+        unsigned int i;
+        
+        for (i = 0; i < size; ++i) {
+            if (name[i] != entry.colorName[i])
+                return false;
+        }
+    }
+
+    return true;
+}
+
+
+
+static void
+bumpIndex(unsigned int * const indexP,
+          unsigned int   const tableSize,
+          unsigned int   const limit) {
+/*----------------------------------------------------------------------------
+   Bump *indexP to the next entry in a table of size 'tableSize', in a
+   circular fashion.  But abort the program if this would take us to
+   'limit'.
+-----------------------------------------------------------------------------*/
+    *indexP += 1;
+    if (*indexP >= tableSize)
+        *indexP = 0;
+
+    if (*indexP == limit)
+        pm_error("INTERNAL ERROR: color name hash table is full");
+}
+
+
+
+static void
+hash_find(const ColorNameHash *             const hashP,
+          const char *                      const name,
+          struct ColorNameHashTableEntry ** const entryPP) {
+/*----------------------------------------------------------------------------
+   Find the entry in the color hash table *hashP for the color
+   named 'name' in the lexicon of this XPM file.  If the color is in the
+   table, this is where it is.  If it isn't, this is where it should go.
+-----------------------------------------------------------------------------*/
+    unsigned int const initialIndex  =
+        hashColorName(name, hashP->nameSize, hashP->size);
+
+    unsigned int i;
+
+    for (i = initialIndex;
+         !entryMatch(hashP->table[i], name, hashP->nameSize);
+         bumpIndex(&i, hashP->size, initialIndex));
+         
+    *entryPP = &hashP->table[i];
 }
 
 
+
+static void
+hash_add(ColorNameHash * const hashP,
+         const char *    const name,
+         pixel           const color,
+         bool            const isTransparent) {
+
+    struct ColorNameHashTableEntry * entryP;
+
+    hash_find(hashP, name, &entryP);
+
+    if (!entryP->empty)
+        pm_error("Color name appears multiple times in color map");
+
+    entryP->empty = false;
+    {
+        unsigned int i;
+        for (i = 0; i < hashP->nameSize; ++i)
+            entryP->colorName[i] = name[i];
+    }
+    entryP->color = color;
+
+    if (isTransparent) {
+        if (hashP->transparentP)
+            pm_error("There are multiple NONE (transparent) entries in "
+                     "the XPM color map");
+        else
+            hashP->transparentP = entryP;
+    }
+}
+
+
+
+static pixel
+hash_color(const ColorNameHash * const hashP,
+           const char *          const name) {
+
+    struct ColorNameHashTableEntry * entryP;
+
+    hash_find(hashP, name, &entryP);
+
+    if (entryP->empty)
+        pm_error("Color name in raster is not in color map");
+
+    return entryP->color;
+}
+
+
+
+static bool
+hash_isTransparent(const ColorNameHash * const hashP,
+                   const char *          const name) {
+
+    struct ColorNameHashTableEntry * entryP;
+
+    hash_find(hashP, name, &entryP);
+
+    return (entryP == hashP->transparentP);
+}
+
+
+
 static char lastInputLine[MAX_LINE+1];
     /* contents of line most recently read from input */
 static bool backup;
@@ -121,6 +346,7 @@ static bool backup;
     */
 
 
+
 static void
 getLine(char * const line,
         size_t const size,
@@ -158,21 +384,6 @@ getLine(char * const line,
 
 
 
-static unsigned int
-getNumber(char * const p, unsigned int const size) {
-
-    unsigned int retval;
-    unsigned char * q;
-    
-    retval = 0;
-    for (q = p; q < p+size; ++q)
-        retval = (retval << 8) + *q;
-
-    return retval;
-}
-
-
-
 static void
 getword(char * const output, char ** const cursorP) {
 
@@ -191,90 +402,97 @@ getword(char * const output, char ** const cursorP) {
 
 
 static void
-addToColorMap(unsigned int const seqNum,
-              unsigned int const colorNumber, 
-              pixel * const colors, int * const ptab, 
-              char colorspec[], int const isTransparent,
-              int * const transparentP) {
+addToColorMap(ColorNameHash * const hashP,
+              const char *    const colorName,
+              char            const colorspec[],
+              bool            const isTransparent) {
 /*----------------------------------------------------------------------------
-   Add the color named by colorspec[] to the colormap contained in
-   'colors' and 'ptab', as the color associated with XPM color number
-   'colorNumber', which is the seqNum'th color in the XPM color map.
+   Add the color named by colorspec[] to the colormap represented by *hashP,
+   as the color associated with XPM color name 'colorNumber'.
 
-   Iff 'transparent', set *transparentP to the colormap index that 
-   corresponds to this color.
+   Note that *hashP determines how long 'colorName' is.
 -----------------------------------------------------------------------------*/
-    if (ptab == NULL) {
-        /* Index into table. */
-        colors[colorNumber] = ppm_parsecolor(colorspec,
-                                             (pixval) PPM_MAXMAXVAL);
-        if (isTransparent) 
-            *transparentP = colorNumber;
-    } else {
-        /* Set up linear search table. */
-        colors[seqNum] = ppm_parsecolor(colorspec,
-                                        (pixval) PPM_MAXMAXVAL);
-        ptab[seqNum] = colorNumber;
-        if (isTransparent)
-            *transparentP = seqNum;
+    hash_add(hashP, colorName, ppm_parsecolor(colorspec, PPM_MAXMAXVAL),
+             isTransparent);
+}
+
+
+
+static void
+validateColorName(const char * const name,
+                  unsigned int const charsPerPixel) {
+
+    unsigned int i;
+
+    for (i = 0; i < charsPerPixel; ++i) {
+        if (name[i] == '"')
+            pm_error("A color map entry ends in the middle of the colormap "
+                     "index");
+        else if (name[i] == '\0')
+            pm_error("The XPM file ends in the middle of a color map entry");
     }
 }
 
 
 
 static void
-interpretXpm3ColorTableLine(char line[], int const seqNum, 
-                            int const chars_per_pixel,
-                            pixel * const colors, int * const ptab,
-                            int * const transparentP) {
+interpretXpm3ColorTableLine(char               const line[],
+                            unsigned int       const seqNum, 
+                            unsigned int       const charsPerPixel,
+                            ColorNameHash *    const hashP) {
 /*----------------------------------------------------------------------------
-   Interpret one line of the color table in the XPM header.  'line' is
-   the line from the XPM file.  It is the seqNum'th color table entry in
-   the file.  The file uses 'chars_per_pixel' characters per pixel.
+   Interpret one line of the color table in the XPM header.  'line' is the
+   line from the XPM file.  It is the seqNum'th color table entry in the file.
+   The raster in the file uses 'charsPerPixel' characters per pixel (i.e.
+   a an XPM color name is 'charsPerPixel' characters).
 
-   Add the information from this color table entry to the color table
-   'colors' and, if it isn't NULL, the corresponding lookup shadow table
-   'ptab' (see readXpm3ColorTable for a description of these data 
-   structures).
+   Add the information from this color table entry to the color name hash
+   *hashP.
 
    The line may include values for multiple kinds of color (grayscale,
    color, etc.).  We take the highest of these (e.g. color over grayscale).
 
    If a color table entry indicates transparency, set *transparentP
-   to the colormap index that corresponds to the indicated color.
+   to indicate the XPM color name.
 -----------------------------------------------------------------------------*/
     /* Note: this code seems to allow for multi-word color specifications,
        but I'm not aware that such are legal.  Ultimately, ppm_parsecolor()
-       interprets the name, and I believe it only takes single word 
+       interprets the name, and I believe it takes only single word 
        color specifications.  -Bryan 2001.05.06.
     */
     char str2[MAX_LINE+1];    
-    char *t1;
-    char *t2;
+    char * t1;
+    char * t2;
     int endOfEntry;   /* boolean */
     
-    unsigned int curkey, key, highkey;	/* current color key */
-    unsigned int lastwaskey;	
+    unsigned int curkey, key, highkey;  /* current color key */
+    bool lastwaskey;    
         /* The last token we processes was a key, and we have processed
            at least one token.
         */
-    char curbuf[BUFSIZ];		/* current buffer */
-    int isTransparent;
+    char curbuf[BUFSIZ];        /* current buffer */
+    bool isTransparent;
     
-    int colorNumber;
-        /* A color number that appears in the raster */
+    const char * colorName;
+        /* The 0-3 character name this color map line gives the color
+           (i.e. the name that the raster uses).  This is NOT NUL-terminated.
+           It's length is bytesPerPixel.
+        */
+
     /* read the chars */
     t1 = strchr(line, '"');
     if (t1 == NULL)
         pm_error("A line that is supposed to be an entry in the color "
                  "table does not start with a quote.  The line is '%s'.  "
-                 "It is the %dth entry in the color table.", 
+                 "It is the %uth entry in the color table.", 
                  line, seqNum);
     else
-        t1++;  /* Points now to first color number character */
+        ++t1;  /* Points now to first color number character */
+    
+    validateColorName(t1, charsPerPixel);
+    colorName = t1;
 
-    colorNumber = getNumber(t1, chars_per_pixel);
-    t1 += chars_per_pixel;
+    t1 += charsPerPixel;
 
     /*
      * read color keys and values 
@@ -306,30 +524,30 @@ interpretXpm3ColorTableLine(char line[], int const seqNum,
                     pm_error("Missing color key token in color table line "
                              "'%s' before '%s'.", line, str2);
                 if (!lastwaskey) 
-                    strcat(curbuf, " ");		/* append space */
-                if ( (strncmp(str2, "None", 4) == 0) 
-                     || (strncmp(str2, "none", 4) == 0) ) {
+                    strcat(curbuf, " ");        /* append space */
+                if ( (strneq(str2, "None", 4)) 
+                     || (strneq(str2, "none", 4)) ) {
                     /* This entry identifies the transparent color number */
                     strcat(curbuf, "#000000");  /* Make it black */
                     isTransparent = TRUE;
                 } else 
-                    strcat(curbuf, str2);		/* append buf */
-                lastwaskey = 0;
+                    strcat(curbuf, str2);       /* append buf */
+                lastwaskey = FALSE;
             } else { 
                 /* This word is a key.  So we've seen the last of the 
                    info for the previous key, and we must either put it
                    in the color map or ignore it if we already have a higher
                    color form in the colormap for this colormap entry.
                 */
-                if (curkey > highkey) {	/* flush string */
-                    addToColorMap(seqNum, colorNumber, colors, ptab, curbuf,
-                                  isTransparent, transparentP);
+                if (curkey > highkey) { /* flush string */
+                    addToColorMap(hashP, colorName, curbuf, isTransparent);
                     highkey = curkey;
                 }
-                curkey = key;			/* set new key  */
-                curbuf[0] = '\0';		/* reset curbuf */
+                /* intialize state to process this new key */
+                curkey = key;
+                curbuf[0] = '\0';
                 isTransparent = FALSE;
-                lastwaskey = 1;
+                lastwaskey = TRUE;
             }
             if (*t2 == '"') break;
         }
@@ -339,8 +557,7 @@ interpretXpm3ColorTableLine(char line[], int const seqNum,
        entry in it)
     */
     if (curkey > highkey) {
-        addToColorMap(seqNum, colorNumber, colors, ptab, curbuf,
-                      isTransparent, transparentP);
+        addToColorMap(hashP, colorName, curbuf, isTransparent);
         highkey = curkey;
     }
     if (highkey == 1) 
@@ -350,152 +567,208 @@ interpretXpm3ColorTableLine(char line[], int const seqNum,
 
 
 static void
-readXpm3Header(FILE * const stream, int * const widthP, int * const heightP, 
-               int * const chars_per_pixelP, int * const ncolorsP,
-               pixel ** const colorsP, int ** const ptabP,
-               int * const transparentP) {
+readV3ColorTable(FILE *             const ifP,
+                 ColorNameHash **   const colorNameHashPP,
+                 unsigned int       const nColors,
+                 unsigned int       const charsPerPixel) {
 /*----------------------------------------------------------------------------
-  Read the header of the XPM file on stream 'stream'.  Assume the
+   Read the color table from the XPM Version 3 header.
+
+   Assume *ifP is positioned to the color table; leave it positioned after.
+-----------------------------------------------------------------------------*/
+    ColorNameHash * const colorNameHashP = hash_create(nColors, charsPerPixel);
+
+    unsigned int seqNum;
+        /* Sequence number of entry within color table in XPM header */
+
+    for (seqNum = 0; seqNum < nColors; ++seqNum) {
+        char line[MAX_LINE+1];
+        getLine(line, sizeof(line), ifP);
+        /* skip the comment line if any */
+        if (strneq(line, "/*", 2))
+            getLine(line, sizeof(line), ifP);
+            
+        interpretXpm3ColorTableLine(line, seqNum, charsPerPixel,
+                                    colorNameHashP);
+                                    
+    }
+    *colorNameHashPP = colorNameHashP;
+}
+
+
+
+static void
+readXpm3Header(FILE *             const ifP,
+               unsigned int *     const widthP,
+               unsigned int *     const heightP, 
+               unsigned int *     const charsPerPixelP,
+               ColorNameHash **   const colorNameHashPP) {
+/*----------------------------------------------------------------------------
+  Read the header of the XPM file on stream *ifP.  Assume the
   getLine() stream is presently positioned to the beginning of the
   file and it is a Version 3 XPM file.  Leave the stream positioned
   after the header.
 
-  We have two ways to return the colormap, depending on the number of
-  characters per pixel in the XPM:  
-  
-  If it is 1 or 2 characters per pixel, we return the colormap as a
-  Netpbm 'pixel' array *colorsP (in newly malloc'ed storage), such
-  that if a color in the raster is identified by index N, then
-  (*colorsP)[N] is that color.  So this array is either 256 or 64K
-  pixels.  In this case, we return *ptabP = NULL.
-
-  If it is more than 2 characters per pixel, we return the colormap as
-  both a Netpbm 'pixel' array *colorsP and a lookup table *ptabP (both
-  in newly malloc'ed storage).
-
-  If a color in the raster is identified by index N, then for some I,
-  (*ptabP)[I] is N and (*colorsP)[I] is the color in question.  So 
-  you iterate through *ptabP looking for N and then look at the 
-  corresponding entry in *colorsP to get the color.
-
-  Return as *transColorNumberP the value of the XPM color number that
-  represents a transparent pixel, or -1 if no color number does.
+  Return as *widthP and *heightP the dimensions of the image indicated
+  by the header.
+
+  Return as *charsPerPixelP the number of characters the header says the
+  raster uses for each pixel, i.e. the XPM color name length.
+
+  Return the color map as *colorNameHashPP.
 -----------------------------------------------------------------------------*/
     char line[MAX_LINE+1];
     const char * xpm3_signature = "/* XPM */";
     
-    *widthP = *heightP = *ncolorsP = *chars_per_pixelP = -1;
+    unsigned int width, height;
+    unsigned int nColors;
+    unsigned int charsPerPixel;
 
     /* Read the XPM signature comment */
-    getLine(line, sizeof(line), stream);
-    if (strncmp(line, xpm3_signature, strlen(xpm3_signature)) != 0) 
+    getLine(line, sizeof(line), ifP);
+    if (!strneq(line, xpm3_signature, strlen(xpm3_signature))) 
         pm_error("Apparent XPM 3 file does not start with '/* XPM */'.  "
                  "First line is '%s'", xpm3_signature);
 
     /* Read the assignment line */
-    getLine(line, sizeof(line), stream);
-    if (strncmp(line, "static char", 11) != 0)
+    getLine(line, sizeof(line), ifP);
+    if (!strneq(line, "static char", 11))
         pm_error("Cannot find data structure declaration.  Expected a "
                  "line starting with 'static char', but found the line "
                  "'%s'.", line);
 
-	/* Read the hints line */
-    getLine(line, sizeof(line), stream);
-    /* skip the comment line if any */
-    if (!strncmp(line, "/*", 2)) {
+    getLine(line, sizeof(line), ifP);
+
+    /* Skip the comment block, if one starts here */
+    if (strneq(line, "/*", 2)) {
         while (!strstr(line, "*/"))
-            getLine(line, sizeof(line), stream);
-        getLine(line, sizeof(line), stream);
+            getLine(line, sizeof(line), ifP);
+        getLine(line, sizeof(line), ifP);
     }
-    if (sscanf(line, "\"%d %d %d %d\",", widthP, heightP,
-               ncolorsP, chars_per_pixelP) != 4)
+
+    /* Parse the hints line */
+    if (sscanf(line, "\"%u %u %u %u\",", &width, &height,
+               &nColors, &charsPerPixel) != 4)
         pm_error("error scanning hints line");
 
-    if (verbose == 1) 
-    {
-        pm_message("Width x Height:  %d x %d", *widthP, *heightP);
-        pm_message("no. of colors:  %d", *ncolorsP);
-        pm_message("chars per pixel:  %d", *chars_per_pixelP);
+    if (verbose) {
+        pm_message("Width x Height:  %u x %u", width, height);
+        pm_message("no. of colors:  %u", nColors);
+        pm_message("chars per pixel:  %u", charsPerPixel);
     }
 
-    /* Allocate space for color table. */
-    if (*chars_per_pixelP <= 2) {
-        /* Set up direct index (see above) */
-        *colorsP = ppm_allocrow(*chars_per_pixelP == 1 ? 256 : 256*256);
-        *ptabP = NULL;
-    } else {
-        /* Set up lookup table (see above) */
-        *colorsP = ppm_allocrow(*ncolorsP);
-        MALLOCARRAY(*ptabP, *ncolorsP);
-        if (*ptabP == NULL)
-            pm_error("Unable to allocate memory for %d colors", *ncolorsP);
-    }
-    
-    { 
-        /* Read the color table */
-        int seqNum;
-            /* Sequence number of entry within color table in XPM header */
-
-        *transparentP = -1;  /* initial value */
-
-        for (seqNum = 0; seqNum < *ncolorsP; seqNum++) {
-            getLine(line, sizeof(line), stream);
-            /* skip the comment line if any */
-            if (!strncmp(line, "/*", 2))
-                getLine(line, sizeof(line), stream);
-            
-            interpretXpm3ColorTableLine(line, seqNum, *chars_per_pixelP, 
-                                        *colorsP, *ptabP, transparentP);
-        }
+    readV3ColorTable(ifP, colorNameHashPP, nColors, charsPerPixel);
+
+    *widthP         = width;
+    *heightP        = height;
+    *charsPerPixelP = charsPerPixel;
+}
+
+
+
+static void
+readV1ColorTable(FILE *           const ifP,
+                 ColorNameHash ** const colorNameHashPP,
+                 unsigned int     const nColors,
+                 unsigned int     const charsPerPixel) {
+/*----------------------------------------------------------------------------
+   Read the color table from the XPM Version 1 header.
+
+   Assume *ifP is positioned to the color table; leave it positioned after.
+-----------------------------------------------------------------------------*/
+    ColorNameHash * const colorNameHashP = hash_create(nColors, charsPerPixel);
+
+    unsigned int i;
+
+    for (i = 0; i < nColors; ++i) {
+        char line[MAX_LINE+1];
+        char str1[MAX_LINE+1];
+        char str2[MAX_LINE+1];
+        char * t1;
+        char * t2;
+
+        getLine(line, sizeof(line), ifP);
+
+        if ((t1 = strchr(line, '"')) == NULL)
+            pm_error("D error scanning color table");
+        if ((t2 = strchr(t1 + 1, '"')) == NULL)
+            pm_error("E error scanning color table");
+        if (t2 - t1 - 1 != charsPerPixel)
+            pm_error("wrong number of chars per pixel in color table");
+        strncpy(str1, t1 + 1, t2 - t1 - 1);
+        str1[t2 - t1 - 1] = '\0';
+
+        if ((t1 = strchr(t2 + 1, '"')) == NULL)
+            pm_error("F error scanning color table");
+        if ((t2 = strchr(t1 + 1, '"')) == NULL)
+            pm_error("G error scanning color table");
+        strncpy(str2, t1 + 1, t2 - t1 - 1);
+        str2[t2 - t1 - 1] = '\0';
+
+        addToColorMap(colorNameHashP, str1, str2, false);
     }
+    *colorNameHashPP = colorNameHashP;
 }
 
 
+
 static void
-readXpm1Header(FILE * const stream, int * const widthP, int * const heightP, 
-               int * const chars_per_pixelP, int * const ncolorsP, 
-               pixel ** const colorsP, int ** const ptabP) {
+readXpm1Header(FILE *           const ifP,
+               unsigned int *   const widthP,
+               unsigned int *   const heightP, 
+               unsigned int *   const charsPerPixelP,
+               ColorNameHash ** const colorNameHashPP) {
 /*----------------------------------------------------------------------------
-  Read the header of the XPM file on stream 'stream'.  Assume the
+  Read the header of the XPM file on stream *ifP.  Assume the
   getLine() stream is presently positioned to the beginning of the
   file and it is a Version 1 XPM file.  Leave the stream positioned
   after the header.
   
   Return the information from the header the same as for readXpm3Header.
 -----------------------------------------------------------------------------*/
-    char line[MAX_LINE+1], str1[MAX_LINE+1], str2[MAX_LINE+1];
-    char *t1;
-    char *t2;
-    int format;
-    unsigned int v;
-    int i, j;
+    int format, v;
     bool processedStaticChar;  
         /* We have read up to and interpreted the "static char..." line */
+    char * t1;
+    unsigned int nColors;
+    bool gotPixel, gotNColors, gotWidth, gotHeight, gotFormat;
 
-    *widthP = *heightP = *ncolorsP = *chars_per_pixelP = format = -1;
+    gotNColors = false;
+    gotWidth   = false;
+    gotHeight  = false;
+    gotFormat  = false;
+    gotPixel   = false;
 
     /* Read the initial defines. */
     processedStaticChar = FALSE;
     while (!processedStaticChar) {
-        getLine(line, sizeof(line), stream);
+        char line[MAX_LINE+1];
+        char str1[MAX_LINE+1];
+
+        getLine(line, sizeof(line), ifP);
 
         if (sscanf(line, "#define %s %d", str1, &v) == 2) {
-            char *t1;
             if ((t1 = strrchr(str1, '_')) == NULL)
                 t1 = str1;
             else
                 ++t1;
-            if (streq(t1, "format"))
+            if (streq(t1, "format")) {
+                gotFormat = true;
                 format = v;
-            else if (streq(t1, "width"))
+            } else if (streq(t1, "width")) {
+                gotWidth = true;
                 *widthP = v;
-            else if (streq(t1, "height"))
+            } else if (streq(t1, "height")) {
+                gotHeight = true;
                 *heightP = v;
-            else if (streq(t1, "ncolors"))
-                *ncolorsP = v;
-            else if (streq(t1, "pixel"))
-                *chars_per_pixelP = v;
-        } else if (!strncmp(line, "static char", 11)) {
+            } else if (streq(t1, "nColors")) {
+                gotNColors = true;
+                nColors = v;
+            } else if (streq(t1, "pixel")) {
+                gotPixel = TRUE;
+                *charsPerPixelP = v;
+            }
+        } else if (strneq(line, "static char", 11)) {
             if ((t1 = strrchr(line, '_')) == NULL)
                 t1 = line;
             else
@@ -507,85 +780,40 @@ readXpm1Header(FILE * const stream, int * const widthP, int * const heightP,
        t1 points to position of last "_" in the line, or the beginning of
        the line if there is no "_"
     */
-    if (format == -1)
+    if (!gotPixel)
+        pm_error("No 'pixel' value (characters per pixel)");
+    if (!gotFormat)
         pm_error("missing or invalid format");
     if (format != 1)
         pm_error("can't handle XPM version %d", format);
-    if (*widthP == -1)
+    if (!gotWidth)
         pm_error("missing or invalid width");
-    if (*heightP == -1)
+    if (!gotHeight)
         pm_error("missing or invalid height");
-    if (*ncolorsP == -1)
-        pm_error("missing or invalid ncolors");
-    if (*chars_per_pixelP == -1)
-        pm_error("missing or invalid *chars_per_pixelP");
-    if (*chars_per_pixelP > 2)
-        pm_message("WARNING: *chars_per_pixelP > 2 uses a lot of memory");
+    if (!gotNColors)
+        pm_error("missing or invalid nColors");
+
+    if (*charsPerPixelP > 2)
+        pm_message("WARNING: > 2 characters per pixel uses a lot of memory");
 
     /* If there's a monochrome color table, skip it. */
-    if (!strncmp(t1, "mono", 4)) {
+    if (strneq(t1, "mono", 4)) {
         for (;;) {
-            getLine(line, sizeof(line), stream);
-            if (!strncmp(line, "static char", 11))
+            char line[MAX_LINE+1];
+            getLine(line, sizeof(line), ifP);
+            if (strneq(line, "static char", 11))
                 break;
         }
     }
-    /* Allocate space for color table. */
-    if (*chars_per_pixelP <= 2) {
-        /* Up to two chars per pixel, we can use an indexed table. */
-        v = 1;
-        for (i = 0; i < *chars_per_pixelP; ++i)
-            v *= 256;
-        *colorsP = ppm_allocrow(v);
-        *ptabP = NULL;
-    } else {
-        /* Over two chars per pixel, we fall back on linear search. */
-        *colorsP = ppm_allocrow(*ncolorsP);
-        MALLOCARRAY(*ptabP, *ncolorsP);
-        if (*ptabP == NULL)
-            pm_error("Unable to allocate memory for %d colors", *ncolorsP);
-    }
-
-    /* Read color table. */
-    for (i = 0; i < *ncolorsP; ++i) {
-        getLine(line, sizeof(line), stream);
+    readV1ColorTable(ifP, colorNameHashPP, nColors, *charsPerPixelP);
 
-        if ((t1 = strchr(line, '"')) == NULL)
-            pm_error("D error scanning color table");
-        if ((t2 = strchr(t1 + 1, '"')) == NULL)
-            pm_error("E error scanning color table");
-        if (t2 - t1 - 1 != *chars_per_pixelP)
-            pm_error("wrong number of chars per pixel in color table");
-        strncpy(str1, t1 + 1, t2 - t1 - 1);
-        str1[t2 - t1 - 1] = '\0';
-
-        if ((t1 = strchr(t2 + 1, '"')) == NULL)
-            pm_error("F error scanning color table");
-        if ((t2 = strchr(t1 + 1, '"')) == NULL)
-            pm_error("G error scanning color table");
-        strncpy(str2, t1 + 1, t2 - t1 - 1);
-        str2[t2 - t1 - 1] = '\0';
-
-        v = 0;
-        for (j = 0; j < *chars_per_pixelP; ++j)
-            v = (v << 8) + str1[j];
-        if (*chars_per_pixelP <= 2)
-            /* Index into table. */
-            (*colorsP)[v] = ppm_parsecolor(str2,
-                                           (pixval) PPM_MAXMAXVAL);
-        else {
-            /* Set up linear search table. */
-            (*colorsP)[i] = ppm_parsecolor(str2,
-                                           (pixval) PPM_MAXMAXVAL);
-            (*ptabP)[i] = v;
-        }
-    }
     /* Position to first line of raster (which is the line after
        "static char ...").
     */
     for (;;) {
-        getLine(line, sizeof(line), stream);
-        if (strncmp(line, "static char", 11) == 0)
+        char line[MAX_LINE+1];
+        getLine(line, sizeof(line), ifP);
+        if (strneq(line, "static char", 11))
             break;
     }
 }
@@ -593,29 +821,49 @@ readXpm1Header(FILE * const stream, int * const widthP, int * const heightP,
 
 
 static void
-interpretXpmLine(char   const line[],
-                 int    const chars_per_pixel,
-                 int    const ncolors,
-                 int *  const ptab, 
-                 int ** const cursorP,
-                 int *  const maxCursor) {
+validateRasterPixel(const char * const pixelChars,
+                    unsigned int const charsPerPixel) {
+
+    unsigned int i;
+
+    for (i = 0; i < charsPerPixel; ++i) {
+        if (pixelChars[i] == '\0')
+            pm_error("XPM input file ends in the middle of a string "
+                     "that represents a raster line");
+        else if (pixelChars[i] == '"')
+            pm_error("A string that represents a raster line in the "
+                     "XPM input file is too short to contain all the "
+                     "pixels (%u characters each)",
+                     charsPerPixel);
+    }
+}
+
+
+
+static void
+convertRow(char                  const line[],
+           unsigned int          const width,
+           unsigned int          const charsPerPixel,
+           const ColorNameHash * const colorNameHashP,
+           pixel *               const pixrow,
+           bit *                 const alpharow) {
 /*----------------------------------------------------------------------------
-   Interpret one line of XPM input.  The line is in 'line', and its
-   format is 'chars_per_pixel' characters per pixel.  'ptab' is the
-   color table that applies to the line, which table has 'ncolors'
-   colors.
+   Convert one row from XPM input, which describes one raster line of the
+   image, to PPM.  The XPM line is in 'line', and its format is 'width' pixel,
+   'charsPerPixel' characters per pixel.  *colorNameHashP is the color table
+   that applies to the line.
+
+   Put the PPM pixels in 'pixrow'.
 
-   Put the colormap indexes for the pixels represented in 'line' at
-   *cursorP, lined up in the order they are in 'line', and return
-   *cursorP positioned just after the last one.
+   Also produce PBM row 'alpharow' with the transparency information from the
+   row.
 
    If the line doesn't start with a quote (e.g. it is empty), we issue
    a warning and just treat the line as one that describes no pixels.
 
-   Stop processing the line either at the end of the line or when
-   the output would go beyond maxCursor, whichever comes first.
+   Abort program if there aren't exactly 'width' pixels in the line.
 -----------------------------------------------------------------------------*/
-    char * lineCursor;
+    const char * lineCursor;
 
     lineCursor = strchr(line, '"');  /* position to 1st quote in line */
     if (lineCursor == NULL) {
@@ -626,209 +874,208 @@ interpretXpmLine(char   const line[],
                    "line which is supposed to be a line of raster data: "
                    "'%s'.  Ignoring this line.", line);
     } else {
+        unsigned int col;
+    
         ++lineCursor; /* Skip to first character after quote */
 
         /* Handle pixels until a close quote, eol, or we've returned all
            the pixels Caller wants.
         */
-        while (*lineCursor && *lineCursor != '"' && *cursorP <= maxCursor) {
-            int colorNumber;
-            int i;
-            colorNumber = 0;  /* initial value */
-            for (i = 0; i < chars_per_pixel; ++i)
-                colorNumber = (colorNumber << 8) + *(lineCursor++);
-            if (ptab == NULL)
-                /* colormap is indexed directly by XPM color number */
-                *(*cursorP)++ = colorNumber;
-            else {
-                /* colormap shadows ptab[].  Find this color # in ptab[] */
-                int i;
-                for (i = 0; i < ncolors && ptab[i] != colorNumber; ++i);
-                if (i < ncolors)
-                    *(*cursorP)++ = i;
-                else
-                    pm_error("Color number %d is in raster, but not in "
-                             "colormap.  Line it's in: '%s'",
-                             colorNumber, line);
-            }
+        for (col = 0; col < width; ++col) {
+
+            validateRasterPixel(lineCursor, charsPerPixel);
+
+            pixrow[col] = hash_color(colorNameHashP, lineCursor);
+
+            alpharow[col] = hash_isTransparent(colorNameHashP, lineCursor) ?
+                PBM_BLACK : PBM_WHITE;
+            
+            lineCursor += charsPerPixel;
         }
+        if (*lineCursor != '"')
+            pm_error("A raster line continues past width of image");
     }
 }
 
 
 
 static void
-ReadXPMFile(FILE * const stream, int * const widthP, int * const heightP, 
-            pixel ** const colorsP, int ** const dataP, 
-            int * const transparentP) {
+convertRaster(FILE *                const ifP,
+              unsigned int          const cols,
+              unsigned int          const rows, 
+              unsigned int          const charsPerPixel,
+              const ColorNameHash * const colorNameHashP,
+              FILE *                const imageOutFileP,
+              FILE *                const alphaOutFileP) {
 /*----------------------------------------------------------------------------
-   Read the XPM file from stream 'stream'.
+  Read the XPM raster from *ifP and write the PPM raster to *imageOutFileP
+  and the alpha channel to *alphaOutFileP (where those are, respectively,
+  non-null).
 
-   Return the dimensions of the image as *widthP and *heightP.
-   Return the color map as *colorsP, which is an array of *ncolorsP
-   colors.
+  The dimensions are 'cols' by 'rows' and the color map for the XPM
+  raster is *colorNameHashP.
+-----------------------------------------------------------------------------*/
+    char line[MAX_LINE+1];
+    pixel * pixrow;
+    bit * alpharow;
+    unsigned int row;
 
-   Return the raster in newly malloced storage, an array of *widthP by
-   *heightP integers, each of which is an index into the colormap
-   *colorsP (and therefore less than *ncolorsP).  Return the address
-   of the array as *dataP.
+    pixrow   = ppm_allocrow(cols);
+    alpharow = pbm_allocrow(cols);
 
-   In the colormap, put black for the transparent color, if the XPM 
-   image contains one.
------------------------------------------------------------------------------*/
-    char line[MAX_LINE+1], str1[MAX_LINE+1];
-    int totalpixels;
-    int *cursor;  /* cursor into *dataP */
-    int *maxcursor;  /* value of above cursor for last pixel in image */
-    int *ptab;   /* colormap - malloc'ed */
-    int rc;
-    int ncolors;
-    int chars_per_pixel;
+    for (row = 0; row < rows; ++row) {
+        bool haveLine;
 
-    backup = FALSE;
+        for (haveLine = false; !haveLine; ) {
+            getLine(line, sizeof(line), ifP); 
 
-    /* Read the header line */
-    getLine(line, sizeof(line), stream);
-    backup = TRUE;  /* back up so next read reads this line again */
-    
-    rc = sscanf(line, "/* %s */", str1);
-    if (rc == 1 && strncmp(str1, "XPM", 3) == 0) {
-        /* It's an XPM version 3 file */
-        readXpm3Header(stream, widthP, heightP, &chars_per_pixel,
-                       &ncolors, colorsP, &ptab, transparentP);
-    } else {				/* try as an XPM version 1 file */
-        /* Assume it's an XPM version 1 file */
-        readXpm1Header(stream, widthP, heightP, &chars_per_pixel, 
-                       &ncolors, colorsP, &ptab);
-        *transparentP = -1;  /* No transparency in version 1 */
-    }
-    totalpixels = *widthP * *heightP;
-    MALLOCARRAY(*dataP, totalpixels);
-    if (*dataP == NULL)
-        pm_error("Could not get %d bytes of memory for image", totalpixels);
-    cursor = *dataP;
-    maxcursor = *dataP + totalpixels - 1;
-	getLine(line, sizeof(line), stream); 
-        /* read next line (first line may not always start with comment) */
-    while (cursor <= maxcursor) {
-        if (strncmp(line, "/*", 2) == 0) {
-            /* It's a comment.  Ignore it. */
-        } else {
-            interpretXpmLine(line, chars_per_pixel, 
-                             ncolors, ptab, &cursor, maxcursor);
+            if (strneq(line, "/*", 2)) {
+                /* It's a comment.  Ignore it. */
+            } else
+                haveLine = true;
         }
-        if (cursor <= maxcursor)
-            getLine(line, sizeof(line), stream);
+        convertRow(line, cols, charsPerPixel, colorNameHashP,
+                   pixrow, alpharow);
+
+        if (imageOutFileP)
+            ppm_writeppmrow(imageOutFileP, 
+                            pixrow, cols, PPM_MAXMAXVAL, 0);
+            if (alphaOutFileP)
+                pbm_writepbmrow(alphaOutFileP, alpharow, cols, 0);
     }
-    if (ptab) free(ptab);
+
+    pbm_freerow(alpharow);
+    ppm_freerow(pixrow);
 }
  
 
 
 static void
-writeOutput(FILE * const imageout_file,
-            FILE * const alpha_file,
-            int const cols, int const rows, 
-            pixel * const colors, int * const data,
-            int transparent) {
+readXpmHeader(FILE *           const ifP,
+              unsigned int *   const widthP,
+              unsigned int *   const heightP, 
+              unsigned int *   const charsPerPixelP,
+              ColorNameHash ** const colorNameHashPP) {
 /*----------------------------------------------------------------------------
-   Write the image in 'data' to open PPM file stream 'imageout_file',
-   and the alpha mask for it to open PBM file stream 'alpha_file',
-   except if either is NULL, skip it.
+  Read the XPM header, including color map.
 
-   'data' is an array of cols * rows integers, each one being an index
-   into the colormap 'colors'.
-
-   Where the index 'transparent' occurs in 'data', the pixel is supposed
-   to be transparent.  If 'transparent' < 0, no pixels are transparent.
+  In the colormap, put black for the transparent color, if the XPM image
+  contains one.
 -----------------------------------------------------------------------------*/
-    int row;
-    pixel *pixrow;
-    bit * alpharow;
-
-    if (imageout_file)
-        ppm_writeppminit(imageout_file, cols, rows, PPM_MAXMAXVAL, 0);
-    if (alpha_file)
-        pbm_writepbminit(alpha_file, cols, rows, 0);
-
-    pixrow = ppm_allocrow(cols);
-    alpharow = pbm_allocrow(cols);
+    char line[MAX_LINE+1];
+    char str1[MAX_LINE+1];
+    int rc;
+    unsigned int charsPerPixel;
+    unsigned int width, height;
 
-    for (row = 0; row < rows; ++row ) {
-        int col;
-        int * const datarow = data+(row*cols);
+    backup = FALSE;
 
-        for (col = 0; col < cols; ++col) {
-            pixrow[col] = colors[datarow[col]];
-            if (datarow[col] == transparent)
-                alpharow[col] = PBM_BLACK;
-            else
-                alpharow[col] = PBM_WHITE;
-        }
-        if (imageout_file)
-            ppm_writeppmrow(imageout_file, 
-                            pixrow, cols, (pixval) PPM_MAXMAXVAL, 0);
-        if (alpha_file)
-            pbm_writepbmrow(alpha_file, alpharow, cols, 0);
+    /* Read the header line */
+    getLine(line, sizeof(line), ifP);
+    backup = TRUE;  /* back up so next read reads this line again */
+    
+    rc = sscanf(line, "/* %s */", str1);
+    if (rc == 1 && strneq(str1, "XPM", 3)) {
+        /* It's an XPM version 3 file */
+        readXpm3Header(ifP, &width, &height, &charsPerPixel, colorNameHashPP);
+    } else {
+        /* Assume it's an XPM version 1 file */
+        readXpm1Header(ifP, &width, &height, &charsPerPixel, colorNameHashPP);
     }
-    ppm_freerow(pixrow);
-    pbm_freerow(alpharow);
-
-    if (imageout_file)
-        pm_close(imageout_file);
-    if (alpha_file)
-        pm_close(alpha_file);
-}    
-
+    *widthP         = width;
+    *heightP        = height;
+    *charsPerPixelP = charsPerPixel;
+}
+ 
 
 
 int
 main(int argc, char *argv[]) {
 
-    FILE *ifp;
-    FILE *alpha_file, *imageout_file;
-    pixel *colormap;
-    int cols, rows;
-    int transparent;  /* value of 'data' that means transparent */
-    int *data;
-        /* The image as an array of width * height integers, each one
-           being an index int colormap[].
-        */
+    FILE * ifP;
+    FILE * alphaOutFileP;
+    FILE * imageOutFileP;
+    unsigned int cols, rows;
+    unsigned int charsPerPixel;
+    ColorNameHash * colorNameHashP;
 
-    struct cmdline_info cmdline;
+    struct cmdlineInfo cmdline;
 
     ppm_init(&argc, argv);
 
-    parse_command_line(argc, argv, &cmdline);
+    parseCommandLine(argc, argv, &cmdline);
 
     verbose = cmdline.verbose;
 
     if ( cmdline.input_filespec != NULL ) 
-        ifp = pm_openr( cmdline.input_filespec);
+        ifP = pm_openr( cmdline.input_filespec);
     else
-        ifp = stdin;
+        ifP = stdin;
 
     if (cmdline.alpha_stdout)
-        alpha_file = stdout;
+        alphaOutFileP = stdout;
     else if (cmdline.alpha_filename == NULL) 
-        alpha_file = NULL;
+        alphaOutFileP = NULL;
     else {
-        alpha_file = pm_openw(cmdline.alpha_filename);
+        alphaOutFileP = pm_openw(cmdline.alpha_filename);
     }
 
     if (cmdline.alpha_stdout) 
-        imageout_file = NULL;
+        imageOutFileP = NULL;
     else
-        imageout_file = stdout;
+        imageOutFileP = stdout;
 
-    ReadXPMFile(ifp, &cols, &rows, &colormap, &data, &transparent);
-    
-    pm_close(ifp);
+    readXpmHeader(ifP, &cols, &rows, &charsPerPixel, &colorNameHashP);
 
-    writeOutput(imageout_file, alpha_file, cols, rows, colormap, data,
-                transparent);
+    if (imageOutFileP)
+        ppm_writeppminit(imageOutFileP, cols, rows, PPM_MAXMAXVAL, 0);
+    if (alphaOutFileP)
+        pbm_writepbminit(alphaOutFileP, cols, rows, 0);
 
-    free(colormap);
+
+    convertRaster(ifP, cols, rows, charsPerPixel, colorNameHashP,
+                  imageOutFileP, alphaOutFileP);
+    
+    pm_close(ifP);
+    if (imageOutFileP)
+        pm_close(imageOutFileP);
+    if (alphaOutFileP)
+        pm_close(alphaOutFileP);
+
+    hash_destroy(colorNameHashP);
     
     return 0;
 }
+
+
+
+/*
+**
+** Copyright (C) 1991 by Jef Poskanzer.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation.  This software is provided "as is" without express or
+** implied warranty.
+**
+** Upgraded to handle XPM version 3 by
+**   Arnaud Le Hors (lehors@mirsa.inria.fr)
+**   Tue Apr 9 1991
+**
+** Rainer Sinkwitz sinkwitz@ifi.unizh.ch - 21 Nov 91:
+**  - Bug fix, no advance of read ptr, would not read 
+**    colors like "ac c black" because it would find 
+**    the "c" of "ac" and then had problems with "c"
+**    as color.
+**    
+**  - Now understands multiword X11 color names
+**  
+**  - Now reads multiple color keys. Takes the color
+**    of the hightest available key. Lines no longer need
+**    to begin with key 'c'.
+**    
+**  - expanded line buffer to from 500 to 2048 for bigger files
+*/
+
diff --git a/converter/ppm/yuvsplittoppm.c b/converter/ppm/yuvsplittoppm.c
index b3088812..5343a21e 100644
--- a/converter/ppm/yuvsplittoppm.c
+++ b/converter/ppm/yuvsplittoppm.c
@@ -57,7 +57,7 @@ parseCommandLine(int                 argc,
    was passed to us as the argv array.  We also trash *argv.
 -----------------------------------------------------------------------------*/
     optEntry *option_def = malloc(100*sizeof(optEntry));
-        /* Instructions to optParseOptions3 on how to parse our options.
+        /* Instructions to pm_optParseOptions3 on how to parse our options.
          */
     optStruct3 opt;
 
@@ -71,7 +71,7 @@ parseCommandLine(int                 argc,
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
 
-    optParseOptions3( &argc, argv, opt, sizeof(opt), 0);
+    pm_optParseOptions3( &argc, argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
 
@@ -196,9 +196,9 @@ main(int argc, char **argv) {
 
     parseCommandLine(argc, argv, &cmdline);
         
-    asprintfN(&ufname, "%s.U", cmdline.filenameBase);
-    asprintfN(&vfname, "%s.V", cmdline.filenameBase);
-    asprintfN(&yfname, "%s.Y", cmdline.filenameBase);
+    pm_asprintf(&ufname, "%s.U", cmdline.filenameBase);
+    pm_asprintf(&vfname, "%s.V", cmdline.filenameBase);
+    pm_asprintf(&yfname, "%s.Y", cmdline.filenameBase);
 
     uf = pm_openr(ufname);
     vf = pm_openr(vfname);
@@ -241,9 +241,9 @@ main(int argc, char **argv) {
     }
     pm_close(stdout);
 
-    strfree(yfname);
-    strfree(vfname);
-    strfree(ufname);
+    pm_strfree(yfname);
+    pm_strfree(vfname);
+    pm_strfree(ufname);
 
     pm_close(yf);
     pm_close(uf);
diff --git a/converter/ppm/yuvtoppm.c b/converter/ppm/yuvtoppm.c
index 2b44c65f..151ff9f9 100644
--- a/converter/ppm/yuvtoppm.c
+++ b/converter/ppm/yuvtoppm.c
@@ -20,96 +20,201 @@
 ** implied warranty.
 */
 
-#include "ppm.h"
+#include "pm_c_util.h"
 #include "mallocvar.h"
+#include "shhopt.h"
+#include "ppm.h"
 
-/* x must be signed for the following to work correctly */
-#define limit(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16)
 
-int
-main(argc, argv)
-	char          **argv;
-{
-	FILE           *ifp;
-	pixel          *pixrow;
-	int             argn, rows, cols, row;
-	const char     * const usage = "<width> <height> [yuvfile]";
-    struct yuv {
-        /* This is an element of a YUV file.  It describes two 
-           side-by-side pixels.
-        */
-        unsigned char u;
-        unsigned char y1;
-        unsigned char v;
-        unsigned char y2;
-    } *yuvbuf;
-
-	ppm_init(&argc, argv);
-
-	argn = 1;
-
-	if (argn + 2 > argc)
-		pm_usage(usage);
-
-	cols = atoi(argv[argn++]);
-	rows = atoi(argv[argn++]);
-	if (cols <= 0 || rows <= 0)
-		pm_usage(usage);
-
-	if (argn < argc) {
-		ifp = pm_openr(argv[argn]);
-		++argn;
-	} else
-		ifp = stdin;
-
-	if (argn != argc)
-		pm_usage(usage);
-
-    if (cols % 2 != 0) {
-        pm_error("Number of columns (%d) is odd.  A YUV image must have an "
-                 "even number of columns.", cols);
+
+struct CmdlineInfo {
+    /* All the information the user supplied in the command line,
+       in a form easy for the program to use.
+    */
+    unsigned int cols;
+    unsigned int rows;
+    const char * inputFileName;  /* Name of input file */
+};
+
+
+
+static void
+parseCommandLine(int argc, const char ** argv,
+                 struct CmdlineInfo * const cmdlineP) {
+
+    optEntry * option_def;
+        /* Instructions to OptParseOptions3 on how to parse our options */
+    optStruct3 opt;
+
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    OPTENTINIT;
+
+    opt.opt_table = option_def;
+    opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
+    opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
+
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
+
+    if (argc-1 < 2)
+        pm_error("You need at least two arguments: width and height in "
+                 "pixels.  You specified %u", argc-1);
+    else {
+        int const widthArg  = atoi(argv[1]);
+        int const heightArg = atoi(argv[2]);
+
+        if (widthArg < 0)
+            pm_error("Negative number for width: %d", widthArg);
+        if (heightArg < 0)
+            pm_error("Negative number for height: %d", heightArg);
+
+        cmdlineP->cols = widthArg;
+        cmdlineP->rows = heightArg;
+                 
+        if (cmdlineP->cols % 2 != 0)
+            pm_error("Number of columns (%u) is odd.  "
+                     "A YUV image must have an "
+                     "even number of columns.", cmdlineP->cols);
+
+        if (argc-1 < 3)
+            cmdlineP->inputFileName = "-";
+        else {
+            cmdlineP->inputFileName = argv[3];
+
+            if (argc-1 > 3)
+                pm_error("Too many arguments: %u.  "
+                         "The only possible arguments are "
+                         "width, height, and input file name", argc-1);
+        }
     }
+}
 
-	ppm_writeppminit(stdout, cols, rows, (pixval) 255, 0);
-	pixrow = ppm_allocrow(cols);
-    MALLOCARRAY(yuvbuf, (cols+1)/2);
-    if (yuvbuf == NULL)
-        pm_error("Unable to allocate YUV buffer for %d columns.", cols);
 
-	for (row = 0; row < rows; ++row) {
-		int    col;
 
-		fread(yuvbuf, cols * 2, 1, ifp);
+static int
+limit(int const x) {
 
-		for (col = 0; col < cols; col += 2) {
-            /* Produce two pixels in pixrow[] */
-            int y1, u, v, y2, r, g, b;
+    if (x > 0xffffff)
+        return 0xff;
+    else if (x <= 0xffff)
+        return 0;
+    else
+        return ((x >> 16) & 0xff);
+}
+
+
+
+static int
+nonneg(int const x) {
+/*----------------------------------------------------------------------------
+  Raise 'x' to 0 if negative
+-----------------------------------------------------------------------------*/
+    return x < 0 ? 0 : x;
+}
+
+
+
+struct Yuv {
+/*----------------------------------------------------------------------------
+  This is an element of a YUV file.  It describes two side-by-side pixels.
+
+  This is the actual layout of the data in the file (4 bytes).
+-----------------------------------------------------------------------------*/
+    unsigned char u;
+    unsigned char y1;
+    unsigned char v;
+    unsigned char y2;
+};
 
-			u = yuvbuf[col/2].u-128;
 
-            y1 = yuvbuf[col/2].y1 - 16;
-			if (y1 < 0) y1 = 0;
 
-            v = yuvbuf[col/2].v - 128;
+static void
+readYuv(FILE *       const ifP,
+        struct Yuv * const yuvP) {
 
-            y2 = yuvbuf[col/2].y2 - 16;
-			if (y2 < 0) y2 = 0;
+    size_t readCt;
 
-			r = 104635 * v;
-			g = -25690 * u + -53294 * v;
-			b = 132278 * u;
+    readCt = fread(yuvP, sizeof(*yuvP), 1, ifP);
 
-			y1*=76310; y2*=76310;
+    if (readCt != 1) {
+        if (feof(ifP))
+            pm_error("Premature end of input.");
+        else
+            pm_error("Error reading input.");
+    }
+}
+
+
+
+static void
+yuvtoppm(FILE *       const ifP,
+         unsigned int const cols,
+         unsigned int const rows,
+         FILE *       const ofP) {
+
+    pixval const maxval = 255;
+
+    pixel * pixrow;
+    unsigned int row;
+
+    ppm_writeppminit(ofP, cols, rows, maxval, 0);
+
+    pixrow = ppm_allocrow(cols);
+
+    for (row = 0; row < rows; ++row) {
+        unsigned int col;
+        for (col = 0; col < cols; col += 2) {
+            /* Produce two pixels in pixrow[] */
+            struct Yuv yuv;
+            int     y1, u, v, y2, r, g, b;
+
+            readYuv(ifP, &yuv);
+
+            u = yuv.u - 128;
+            y1 = nonneg (yuv.y1 - 16);
+            v = yuv.v - 128;
+            y2 = nonneg (yuv.y2 - 16);
+
+            r = 104635 * v;
+            g = -25690 * u + -53294 * v;
+            b = 132278 * u;
+
+            y1 *= 76310;
+            y2 *= 76310;
+
+            PPM_ASSIGN(pixrow[col],
+                       limit(r + y1), limit(g + y1), limit(b + y1));
+            PPM_ASSIGN(pixrow[col + 1],
+                       limit(r + y2), limit(g + y2), limit(b + y2));
+        }
+        ppm_writeppmrow(ofP, pixrow, cols, maxval, 0);
+    }
 
-			PPM_ASSIGN(pixrow[col], limit(r+y1), limit(g+y1), limit(b+y1));
-			PPM_ASSIGN(pixrow[col+1], limit(r+y2), limit(g+y2), limit(b+y2));
-		}
-		ppm_writeppmrow(stdout, pixrow, cols, (pixval) 255, 0);
-	}
-    free(yuvbuf);
     ppm_freerow(pixrow);
-	pm_close(ifp);
-	pm_close(stdout);
 
-	exit(0);
+    if (fgetc(ifP) != EOF)
+        pm_message("Extraneous data at end of image.");
+}
+
+
+
+int
+main (int argc, const char ** argv) {
+
+    FILE * ifP;
+    struct CmdlineInfo cmdline;
+
+    pm_proginit(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+
+    ifP = pm_openr(cmdline.inputFileName);
+
+    yuvtoppm(ifP, cmdline.cols, cmdline.rows, stdout);
+    
+    pm_close(ifP);
+    pm_close(stdout);
+
+    return 0;
 }