about summary refs log tree commit diff
path: root/converter/pbm/pktopbm.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/pbm/pktopbm.c')
-rw-r--r--converter/pbm/pktopbm.c828
1 files changed, 526 insertions, 302 deletions
diff --git a/converter/pbm/pktopbm.c b/converter/pbm/pktopbm.c
index 712f339f..201b046a 100644
--- a/converter/pbm/pktopbm.c
+++ b/converter/pbm/pktopbm.c
@@ -7,159 +7,277 @@
      * fix bitmap y placement of dynamically packed char
      * skip char early if no output file allocated
      - added debug output
-  
+
   compile with: cc -lpbm -o pktopbm pktopbm.c
   */
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <string.h>
 
 #include "pm_c_util.h"
 #include "nstring.h"
+#include "mallocvar.h"
+#include "shhopt.h"
 #include "pbm.h"
 
 #define NAMELENGTH 80
 #define MAXROWWIDTH 3200
 #define MAXPKCHAR 256
 
-typedef int integer ;
-typedef unsigned char quarterword ;
-typedef char boolean ;
-typedef quarterword eightbits ;
-
-static FILE *pkfile ;
-static char pkname[NAMELENGTH+1] ;
-static integer pktopbm_pkloc = 0;
-static char *filename[MAXPKCHAR] ;
-static bit **bitmap = NULL ;
-static integer dynf ;
-static eightbits inputbyte ;
-static eightbits bitweight ;
-static integer repeatcount ;
-static integer flagbyte ;
-static integer debug=0;
+struct CmdlineInfo {
+    /* All the information the user supplied in the command line,
+       in a form easy for the program to use.
+    */
+    const char * inputFileNm;
+    unsigned int outputFileCt;
+        /* The number of output files */
+    const char * outputFileNm[MAXPKCHAR];
+        /* The output file name, in order */
+    unsigned int character;
+    unsigned int xSpec;
+    unsigned int x;
+    unsigned int ySpec;
+    unsigned int y;
+    unsigned int debug;
+};
+
 
-#define dprintf(s,d) if (debug) printf(s,d)
-#define dprintf0(s) if (debug) printf(s)
 
-/* add a suffix to a filename in an allocated space */
 static void
-pktopbm_add_suffix(char *       const name, 
-                   const char * const suffix) {
-
-    char * const slash = strrchr(name, '/');
-    char * const dot   = strrchr(name, '.');
-    
-    if ((dot && slash ? dot < slash : !dot) && !streq(name, "-"))
-        strcat(name, suffix);
+parseCommandLine(int argc, const char ** argv,
+                 struct CmdlineInfo * const cmdlineP) {
+/*----------------------------------------------------------------------------
+   Note that the file spec strings we return are stored in the storage that
+   was passed to us as the argv array.
+-----------------------------------------------------------------------------*/
+    optEntry * option_def;
+    optStruct3 opt;
+
+    unsigned int option_def_index;
+    unsigned int characterSpec;
+    unsigned int firstOutputArgNm;
+
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    option_def_index = 0;   /* incremented by OPTENTRY */
+    OPTENT3(0, "character",   OPT_UINT, &cmdlineP->character,
+            &characterSpec, 0);
+    OPTENT3(0, "x",   OPT_UINT, &cmdlineP->x,
+            &cmdlineP->xSpec, 0);
+    OPTENT3(0, "X",   OPT_UINT, &cmdlineP->x,
+            &cmdlineP->xSpec, 0);
+    OPTENT3(0, "y",   OPT_UINT, &cmdlineP->y,
+            &cmdlineP->ySpec, 0);
+    OPTENT3(0, "Y",   OPT_UINT, &cmdlineP->y,
+            &cmdlineP->ySpec, 0);
+    OPTENT3(0, "debug",   OPT_UINT, NULL,
+            &cmdlineP->debug, 0);
+
+    opt.opt_table = option_def;
+    opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
+    opt.allowNegNum = FALSE;  /* We may have parms that are negative numbers */
+
+    pm_optParseOptions4(&argc, argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
+
+    if (characterSpec) {
+        if (cmdlineP->character >= MAXPKCHAR)
+            pm_error("Character number (-character) must be in range 0 to %u",
+                     MAXPKCHAR-1);
+    } else
+        cmdlineP->character = 0;
+
+    if (argc-1 < 1) {
+        cmdlineP->inputFileNm = "-";
+        firstOutputArgNm = 1;
+    } else {
+        cmdlineP->inputFileNm = argv[1];
+        firstOutputArgNm = 2;
+    }
+
+    cmdlineP->outputFileCt = 0;  /* initial value */
+    {
+        unsigned int argn;
+        bool stdoutUsed;
+        for (argn = firstOutputArgNm, stdoutUsed = false;
+             argn < argc;
+             ++argn) {
+            if (cmdlineP->outputFileCt >= MAXPKCHAR)
+                pm_error("You may not specify more than %u output files.",
+                         MAXPKCHAR);
+            cmdlineP->outputFileNm[cmdlineP->outputFileCt++] = argv[argn];
+            if (streq(argv[argn], "-")) {
+                if (stdoutUsed)
+                    pm_error("You cannot specify Standard Output ('-') "
+                             "for more than one output file");
+                stdoutUsed = true;
+            }
+        }
+    }
+    if (cmdlineP->outputFileCt < 1)
+        cmdlineP->outputFileNm[cmdlineP->outputFileCt++] = "-";
+
+    if (cmdlineP->character + cmdlineP->outputFileCt >= MAXPKCHAR)
+        pm_error("Number of output files (%u) "
+                 "plus -character value (%u) exceeds "
+                 "the maximum number of characters is a PK font file (%u)",
+                 cmdlineP->character, cmdlineP->outputFileCt, MAXPKCHAR);
 }
 
 
 
-/* get a byte from the PK file */
-static eightbits 
-pktopbm_pkbyte(void) {
-   pktopbm_pkloc++ ;
-   return(getc(pkfile)) ;
+typedef unsigned char eightbits ;
+
+static FILE * ifP;
+static unsigned int pkLoc;
+static const char * fileName[MAXPKCHAR];
+static int dynf ;
+static eightbits inputByte ;
+static eightbits bitWeight ;
+static int repeatCount ;
+static int flagByte ;
+static int debug = 0;
+
+#define dprintf(s,d) if (debug) printf(s,d)
+#define dprintf0(s) if (debug) printf(s)
+
+static eightbits
+pkByte() {
+/*----------------------------------------------------------------------------
+  Get a byte from the PK file
+-----------------------------------------------------------------------------*/
+    ++pkLoc;
+
+    return getc(ifP);
 }
 
 
 
-/* get a 16-bit half word from the PK file */
-static integer 
-get16(void) {
-   integer const a = pktopbm_pkbyte() ;
-   return((a<<8) + pktopbm_pkbyte()) ;
+static int
+get16() {
+/*----------------------------------------------------------------------------
+  Get a 16-bit half word from the PK file
+-----------------------------------------------------------------------------*/
+    int const a = pkByte() ;
+
+    return (a<<8) + pkByte();
 }
 
 
 
-/* get a 32-bit word from the PK file */
-static integer get32(void) {
-    integer a;
-    a = get16() ;
-    if (a > 32767) a -= 65536 ;
-    return((a<<16) + get16()) ;
+static int
+get32() {
+/*----------------------------------------------------------------------------
+  Get a 32-bit word from the PK file
+-----------------------------------------------------------------------------*/
+    int a;
+
+    a = get16();  /* initial value */
+
+    if (a > 32767)
+        a -= 65536;
+
+    return (a << 16) + get16();
 }
 
 
 
-/* get a nibble from current input byte, or new byte if no current byte */
-static integer 
-getnyb(void) {
+static int
+getNybble() {
+/*----------------------------------------------------------------------------
+  Get a nibble from current input byte, or new byte if no current byte
+-----------------------------------------------------------------------------*/
     eightbits temp;
-    if (bitweight == 0) {
-        inputbyte = pktopbm_pkbyte() ;
-        bitweight = 16 ;
+
+    if (bitWeight == 0) {
+        inputByte = pkByte() ;
+        bitWeight = 16 ;
     }
-    temp = inputbyte / bitweight ;
-    inputbyte -= temp * bitweight ;
-    bitweight >>= 4 ;
-    return(temp) ;
+    temp = inputByte / bitWeight ;
+    inputByte -= temp * bitWeight ;
+    bitWeight >>= 4 ;
+
+    return temp;
 }
 
 
 
-/* get a bit from the current input byte, or a new byte if no current byte */
 static bool
-getbit(void) {
+getBit() {
+/*----------------------------------------------------------------------------
+  Get a bit from the current input byte, or a new byte if no current byte
+-----------------------------------------------------------------------------*/
     bool temp ;
-    bitweight >>= 1 ;
-    if (bitweight == 0) {
-        inputbyte = pktopbm_pkbyte() ;
-        bitweight = 128 ;
+
+    bitWeight >>= 1 ;
+    if (bitWeight == 0) {
+        inputByte = pkByte();
+        bitWeight = 128 ;
     }
-    temp = (inputbyte >= bitweight) ;
-    if (temp) inputbyte -= bitweight ;
-    return(temp) ;
+    temp = (inputByte >= bitWeight);
+    if (temp)
+        inputByte -= bitWeight;
+
+    return temp;
 }
 
 
 
-/* unpack a dynamically packed number. dynf is dynamic packing threshold  */
-static integer 
-pkpackednum(void) {
-    integer i, j ;
-    i = getnyb() ;
+static int
+pkPackedNum() {
+/*----------------------------------------------------------------------------
+  Unpack a dynamically packed number. dynf is dynamic packing threshold
+-----------------------------------------------------------------------------*/
+    int i, j ;
+
+    i = getNybble() ;
+
     if (i == 0) {           /* large run count, >= 3 nibbles */
         do {
-            j = getnyb() ;          /* count extra nibbles */
+            j = getNybble() ;          /* count extra nibbles */
             i++ ;
         } while (j == 0) ;
         while (i > 0) {
-            j = (j<<4) + getnyb() ; /* add extra nibbles */
+            j = (j<<4) + getNybble() ; /* add extra nibbles */
             i-- ;
         }
         return (j - 15 +((13 - dynf)<<4) + dynf) ;
     } else if (i <= dynf) return (i) ;  /* number > 0 and <= dynf */
-    else if (i < 14) return (((i - dynf - 1)<<4) + getnyb() + dynf + 1) ;
+    else if (i < 14) return (((i - dynf - 1)<<4) + getNybble() + dynf + 1) ;
     else {
-        if (i == 14) repeatcount = pkpackednum() ;  /* get repeat count */
-        else repeatcount = 1 ;      /* value 15 indicates repeat count 1 */
-        return(pkpackednum()) ;
+        if (i == 14)
+            repeatCount = pkPackedNum() ;  /* get repeat count */
+        else
+            repeatCount = 1 ;      /* value 15 indicates repeat count 1 */
+
+        return pkPackedNum();
     }
 }
 
 
 
-/* skip specials in PK files, inserted by Metafont or some other program */
 static void
-skipspecials(void) {
-    integer i, j;
+skipSpecials() {
+/*----------------------------------------------------------------------------
+  Skip specials in PK files, inserted by Metafont or some other program
+-----------------------------------------------------------------------------*/
     do {
-        flagbyte = pktopbm_pkbyte() ;
-        if (flagbyte >= 240)
-            switch(flagbyte) {
+        flagByte = pkByte() ;
+        if (flagByte >= 240)
+            switch(flagByte) {
             case 240:           /* specials of size 1-4 bytes */
             case 241:
             case 242:
-            case 243:
+            case 243: {
+                int i, j;
+
                 i = 0 ;
-                for (j = 240 ; j <= flagbyte ; ++j) 
-                    i = (i<<8) + pktopbm_pkbyte() ;
-                for (j = 1 ; j <= i ; ++j) 
-                    pktopbm_pkbyte() ;  /* ignore special */
-                break ;
+                for (j = 240 ; j <= flagByte ; ++j)
+                    i = (i<<8) + pkByte() ;
+                for (j = 1 ; j <= i ; ++j)
+                    pkByte() ;  /* ignore special */
+            } break ;
             case 244:           /* no-op, parameters to specials */
                 get32() ;
             case 245:           /* start of postamble */
@@ -174,272 +292,378 @@ skipspecials(void) {
             case 253:
             case 254:
             case 255:
-                pm_error("unexpected flag byte %d", flagbyte) ;
+                pm_error("unexpected flag byte %d", flagByte) ;
             }
-    } while (!(flagbyte < 240 || flagbyte == 245)) ;
+    } while (!(flagByte < 240 || flagByte == 245)) ;
 }
 
 
 
-/* ignore character packet */
 static void
-ignorechar(integer const car, 
-           integer const endofpacket) {
+ignoreChar(int          const car,
+           unsigned int const endOfPacket) {
+/*----------------------------------------------------------------------------
+   ignore character packet
+-----------------------------------------------------------------------------*/
+   while (pkLoc != endOfPacket)
+       pkByte();
 
-   while (pktopbm_pkloc != endofpacket) pktopbm_pkbyte() ;
    if (car < 0 || car >= MAXPKCHAR)
       pm_message("Character %d out of range", car) ;
-   skipspecials() ;
+
+   skipSpecials() ;
 }
 
 
 
-int
-main(int argc, char *argv[]) {
-    integer x;
-    integer endofpacket ;
-    boolean turnon ;
-    integer i, j;
-    integer car ;
-    integer bmx=0, bmy=0;
-    integer set_bmx=0, set_bmy=0;
-    bit row[MAXROWWIDTH+1] ;
-    const char * const usage = 
-        "pkfile[.pk] [-d] [[-x width] [-y height] [-c num] pbmfile]...";
-   
-    pbm_init(&argc, argv);
-    for (i = 0 ; i < MAXPKCHAR ; i ++) filename[i] = NULL ;
-
-    pm_message("This is PKtoPBM, version 2.5") ;
-
-    if (--argc < 1) pm_usage(usage) ;
-
-    ++argv;
-    if(strlen(*argv) + 4 > NAMELENGTH)
-        pm_error("pkname is too long");
-    strcpy(pkname, *argv) ;
-    pktopbm_add_suffix(pkname, ".pk") ;
-
-    car = 0 ;
-    /* urg: use getopt */
-    while (++argv, --argc) {
-        if (argv[0][0] == '-' && argv[0][1])
-            switch (argv[0][1]) {
-            case 'X':
-            case 'x':
-                if (argv[0][2]) bmx = atoi(*argv+2) ;
-                else if (++argv, --argc) set_bmx = atoi(*argv) ;
-                else pm_usage(usage) ;
-                continue ;
-            case 'Y':
-            case 'y':
-                if (argv[0][2]) bmy = atoi(*argv+2) ;
-                else if (++argv, --argc) set_bmy = atoi(*argv) ;
-                else pm_usage(usage) ;
-                continue ;
-            case 'C':
-            case 'c':
-                if (argv[0][2]) car = atoi(*argv+2) ;
-                else if (++argv, --argc) car = atoi(*argv) ;
-                else pm_usage(usage) ;
-                break ;
-            case 'd':
-                debug=1;
-                break ;
-            default:
-                pm_usage(usage) ;
-            } else if (car < 0 || car >= MAXPKCHAR) {
-                pm_error("character must be in range 0 to %d (-c)", 
-                         MAXPKCHAR-1) ;
-            } else filename[car++] = *argv ;
-    }
+static void
+readHeader() {
+/*----------------------------------------------------------------------------
+   Read the header of the input file.
+
+   Surprisingly, nothing in the header is useful to this program, so we're
+   just reading past it and doing some validation.
 
-    pkfile = pm_openr(pkname);
-    if (pktopbm_pkbyte() != 247)
+   We read through the first flag byte and update the global variable
+   'flagByte'.
+-----------------------------------------------------------------------------*/
+    unsigned int commentSz;
+    unsigned int i;
+
+    if (pkByte() != 247)
         pm_error("bad PK file (pre command missing)") ;
-    if (pktopbm_pkbyte() != 89)
+
+    if (pkByte() != 89)
         pm_error("wrong version of packed file") ;
-    j = pktopbm_pkbyte() ;              /* get header comment size */
-    for (i = 1 ; i <= j ; i ++) pktopbm_pkbyte() ;  /* ignore header comment */
+
+    commentSz = pkByte() ;              /* get header comment size */
+
+    for (i = 1 ; i <= commentSz ; ++i)
+        pkByte() ;  /* ignore header comment */
+
     get32() ;                   /* ignore designsize */
     get32() ;                   /* ignore checksum */
     if (get32() != get32())         /* h & v pixels per point */
         pm_message("Warning: aspect ratio not 1:1") ;
-    skipspecials() ;
-    while (flagbyte != 245) {           /* not at postamble */
-        integer cheight, cwidth ;
-        integer xoffs=0, yoffs=0;
-        FILE *ofp;
-
-        bmx=set_bmx;
-        bmy=set_bmy;
-        dynf = (flagbyte>>4) ;          /* get dynamic packing value */
-        flagbyte &= 15 ;
-        turnon = (flagbyte >= 8) ;      /* black or white initially? */
-        if (turnon) flagbyte &= 7 ;     /* long or short form */
-        if (flagbyte == 7) {            /* long form preamble */
-            integer packetlength = get32() ;    /* character packet length */
-            car = get32() ;         /* character number */
-            endofpacket = packetlength + pktopbm_pkloc;
-                /* calculate end of packet */
-            if ((car >= MAXPKCHAR) || !filename[car]) {
-                ignorechar(car, endofpacket);
-                continue;
-            }
-            dprintf0 ("flagbyte7\n");
-            dprintf ("car: %d\n", car);
-            get32() ;               /* ignore tfmwidth */
-            x=get32() ;             /* ignore horiz escapement */
-            x=get32() ;             /* ignore vert escapement */
-            dprintf ("horiz esc %d\n", x);
-            dprintf ("vert esc %d\n", x);
-            cwidth = get32() ;          /* bounding box width */
-            cheight = get32() ;         /* bounding box height */
-            dprintf ("cwidth %d\n", cwidth);
-            dprintf ("cheight %d\n", cheight);
-            if (cwidth < 0 || cheight < 0 || 
-                cwidth > 65535 || cheight > 65535) {
-                ignorechar(car, endofpacket);
-                continue;
-            }
-            xoffs= get32() ;              /* horiz offset */
-            yoffs= get32() ;              /* vert offset */
-            dprintf ("xoffs %d\n", xoffs);
-            dprintf ("yoffs %d\n", yoffs);
-        } else if (flagbyte > 3) {      /* extended short form */
-            integer packetlength = ((flagbyte - 4)<<16) + get16() ;
-            /* packet length */
-            car = pktopbm_pkbyte() ;            /* char number */
-            endofpacket = packetlength + pktopbm_pkloc ; 
-                /* calculate end of packet */
-            if ((car >= MAXPKCHAR) || !filename[car]) {
-                ignorechar(car, endofpacket);
-                continue;
-            }
-            dprintf0 ("flagbyte>3\n");
-            dprintf ("car: %d\n", car);
-            pktopbm_pkbyte() ;              /* ignore tfmwidth (3 bytes) */
-            get16() ;               /* ignore tfmwidth (3 bytes) */
-            get16() ;               /* ignore horiz escapement */
-            cwidth = get16() ;          /* bounding box width */
-            cheight = get16() ;         /* bounding box height */
-            dprintf ("cwidth %d\n", cwidth);
-            dprintf ("cheight %d\n", cheight);
-            xoffs=get16();                         /* horiz offset */
-            if (xoffs >= 32768)
-                xoffs-= 65536;
-            yoffs=get16();                         /* vert offset */
-            if (yoffs >= 32768)
-                yoffs-= 65536;
-            dprintf ("xoffs %d\n", xoffs);
-            dprintf ("yoffs %d\n", yoffs);
-        } else {                    /* short form preamble */
-            integer packetlength = (flagbyte<<8) + pktopbm_pkbyte() ;
-            /* packet length */
-            car = pktopbm_pkbyte() ;            /* char number */
-            endofpacket = packetlength + pktopbm_pkloc ;    
-                /* calculate end of packet */
-            if ((car >= MAXPKCHAR) || !filename[car]) {
-                ignorechar(car, endofpacket);
-                continue;
-            }
-            dprintf0 ("flagbyte<=3\n");
-            dprintf ("car: %d\n", car);
-            pktopbm_pkbyte() ;          /* ignore tfmwidth (3 bytes) */
-            get16() ;               /* ignore tfmwidth (3 bytes) */
-            x = pktopbm_pkbyte() ;  /* ignore horiz escapement */
-            dprintf ("horiz esc %d\n", x);
-            cwidth = pktopbm_pkbyte() ;            /* bounding box width */
-            cheight = pktopbm_pkbyte() ;           /* bounding box height */
-            dprintf ("cwidth %d\n", cwidth);
-            dprintf ("cheight %d\n", cheight);
-            xoffs=pktopbm_pkbyte ();               /* horiz offset */
-            if (xoffs >= 128)
-                xoffs-=256;
-            yoffs=pktopbm_pkbyte ();               /* vert offset */
-            if (yoffs >= 128)
-                yoffs-=256;
+
+    skipSpecials();
+}
+
+
+
+static void
+readCharacterHeader(int *          const carP,
+                    unsigned int * const endOfPacketP,
+                    bool *         const mustIgnoreP,
+                    int *          const cheightP,
+                    int *          const cwidthP,
+                    int *          const xoffsP,
+                    int *          const yoffsP,
+                    bool *         const turnonP) {
+
+    int packetLength;
+        /* character packet length field value */
+    int cheight, cwidth;
+        /* bounding box height, width field values */
+    int xoffs=0, yoffs=0;
+    bool turnon ;
+    int x;
+
+    dynf = (flagByte >> 4);          /* get dynamic packing value */
+    flagByte &= 15;
+    turnon = (flagByte >= 8) ;      /* black or white initially? */
+    if (turnon)
+        flagByte &= 7;     /* long or short form */
+
+    if (flagByte == 7) {            /* long form preamble */
+        packetLength  = get32();
+        *carP         = get32();         /* character number */
+
+        dprintf0("flagByte7\n");
+        dprintf("car: %d\n", *carP);
+        get32();               /* ignore tfmwidth */
+        x=get32();             /* ignore horiz escapement */
+        dprintf("horiz esc %d\n", x);
+        x=get32();             /* ignore vert escapement */
+        dprintf("vert esc %d\n", x);
+        cwidth = get32();          /* bounding box width */
+        cheight = get32();         /* bounding box height */
+        dprintf("cwidth %d\n", cwidth);
+        dprintf("cheight %d\n", cheight);
+        if (cwidth < 0 || cheight < 0 ||
+            cwidth > 65535 || cheight > 65535) {
+            *mustIgnoreP = true;
+        } else {
+            *mustIgnoreP = false;
+            xoffs = get32() ;              /* horiz offset */
+            yoffs = get32() ;              /* vert offset */
             dprintf ("xoffs %d\n", xoffs);
             dprintf ("yoffs %d\n", yoffs);
         }
-        if (filename[car]) {
-            if (!bmx) bmx= cwidth;
-            if (!bmy) bmy= cheight;
-            bitmap = pbm_allocarray(bmx, bmy) ;
-            if (bitmap == NULL)
-                pm_error("out of memory allocating bitmap") ;
-        } else {
-            ignorechar(car, endofpacket);
-            continue;
+    } else if (flagByte > 3) {      /* extended short form */
+        packetLength = ((flagByte - 4)<<16) + get16() ;
+
+        *carP = pkByte() ;            /* char number */
+
+        *mustIgnoreP = false;
+
+        dprintf0("flagByte>3\n");
+        dprintf("car: %d\n", *carP);
+        pkByte();              /* ignore tfmwidth (3 bytes) */
+        get16();               /* ignore tfmwidth (3 bytes) */
+        get16();               /* ignore horiz escapement */
+        cwidth = get16();          /* bounding box width */
+        cheight = get16();         /* bounding box height */
+        dprintf("cwidth %d\n", cwidth);
+        dprintf("cheight %d\n", cheight);
+        xoffs = get16();                         /* horiz offset */
+        if (xoffs >= 32768)
+            xoffs -= 65536;
+        yoffs = get16();                         /* vert offset */
+        if (yoffs >= 32768)
+            yoffs -= 65536;
+        dprintf("xoffs %d\n", xoffs);
+        dprintf("yoffs %d\n", yoffs);
+    } else {                    /* short form preamble */
+        packetLength  = (flagByte << 8) + pkByte();
+        *carP         = pkByte();            /* char number */
+
+        *mustIgnoreP = false;
+
+        dprintf0("flagByte<=3\n");
+        dprintf("car: %d\n", *carP);
+        pkByte();          /* ignore tfmwidth (3 bytes) */
+        get16();               /* ignore tfmwidth (3 bytes) */
+        x = pkByte() ;  /* ignore horiz escapement */
+        dprintf("horiz esc %d\n", x);
+        cwidth = pkByte();            /* bounding box width */
+        cheight = pkByte() ;           /* bounding box height */
+        dprintf("cwidth %d\n", cwidth);
+        dprintf("cheight %d\n", cheight);
+        xoffs = pkByte();               /* horiz offset */
+        if (xoffs >= 128)
+            xoffs -=256;
+        yoffs = pkByte();               /* vert offset */
+        if (yoffs >= 128)
+            yoffs -= 256;
+        dprintf("xoffs %d\n", xoffs);
+        dprintf("yoffs %d\n", yoffs);
+    }
+    if (packetLength < 0)
+        pm_error("Invalid character header - negative packet length");
+    if (packetLength > UINT_MAX - pkLoc)
+        pm_error("Invalid character header - excessive packet length");
+
+    *endOfPacketP = packetLength + pkLoc;
+
+    *cheightP = cheight;
+    *cwidthP  = cwidth;
+    *xoffsP   = xoffs;
+    *yoffsP   = yoffs;
+    *turnonP  = turnon;
+}
+
+
+
+static void
+readOneCharacter(bool           const bmxOverrideSpec,
+                 int            const bmxOverride,
+                 bool           const bmyOverrideSpec,
+                 int            const bmyOverride,
+                 unsigned int * const carP,
+                 bool *         const mustIgnoreP,
+                 bit ***        const bitmapP,
+                 unsigned int * const bmxP,
+                 unsigned int * const bmyP) {
+
+    int car;
+    unsigned int endOfPacket;
+    bool mustIgnore;
+    int cheight, cwidth;
+    int xoffs, yoffs;
+    bool turnon;
+    bit row[MAXROWWIDTH+1];
+
+    readCharacterHeader(&car, &endOfPacket, &mustIgnore,
+                        &cheight, &cwidth, &xoffs, &yoffs, &turnon);
+
+    *carP = car;
+
+    if (mustIgnore || !fileName[car]) {
+        /* Ignore this character in the font */
+        ignoreChar(car, endOfPacket);
+        *mustIgnoreP = true;
+    } else {
+        bit ** bitmap;
+        unsigned int i;
+
+        int const bmx = bmxOverrideSpec ? bmxOverride : cwidth;
+        int const bmy = bmyOverrideSpec ? bmyOverride : cheight;
+
+        *mustIgnoreP = false;
+
+        bitmap = pbm_allocarray(bmx, bmy);
+
+        bitWeight = 0 ;
+        for (i = 0 ; i < bmy ; ++i) {
+            /* make it blank */
+            unsigned int j;
+
+            for (j = 0 ; j < bmx ; ++j)
+                bitmap[i][j] = PBM_WHITE;
         }
-        bitweight = 0 ;
-        for (i = 0 ; i < bmy ; i ++)           /* make it blank */
-            for (j = 0 ; j < bmx ; j ++)
-                bitmap[i][j]= PBM_WHITE;
         if (dynf == 14) {               /* bitmapped character */
-            dprintf ("bmy: %d\n ", bmy);
-            dprintf ("y: %d\n ", bmy-yoffs-1);
-            for (i = 0 ; i < cheight ; i ++) {
-                int yi= i+(bmy-yoffs-1);
-                for (j = 0 ; j < cwidth ; j ++) {
-                    int xj= j-xoffs;
-                    if (getbit() && 0<=xj && xj<bmx && 0<=yi && yi<bmy)
+            dprintf("bmy: %d\n ", bmy);
+            dprintf("y: %d\n ", bmy - yoffs - 1);
+            for (i = 0 ; i < cheight ; ++i) {
+                unsigned int const yi = i + (bmy - yoffs - 1);
+                unsigned int j;
+                for (j = 0 ; j < cwidth ; ++j) {
+                    unsigned int const xj = j - xoffs;
+                    if (getBit() && 0 <= xj && xj < bmx && 0 <= yi && yi < bmy)
                         bitmap[yi][xj] = PBM_BLACK ;
                 }
             }
         } else {                    /* dynamically packed char */
-            integer rowsleft = cheight ;
-            integer hbit = cwidth ;
-            integer rp = 0;
-            repeatcount = 0 ;
-            dprintf ("bmy: %d\n ", bmy);
-            dprintf ("y: %d\n", cheight-rowsleft+(bmy-2*yoffs-1));
+            int rowsleft = cheight ;
+            int hbit = cwidth ;
+            int rp = 0;
+            repeatCount = 0 ;
+            dprintf("bmy: %d\n ", bmy);
+            dprintf("y: %d\n", cheight-rowsleft+(bmy-2*yoffs-1));
             while (rowsleft > 0) {
-                integer count = pkpackednum() ; /* get current color count */
+                int count = pkPackedNum() ; /* get current color count */
                 while (count > 0) {
                     if (count < hbit) {     /* doesn't extend past row */
                         hbit -= count ;
                         while (count--)
                             row[rp++] = turnon ? PBM_BLACK : PBM_WHITE;
                     } else {                /* reaches end of row */
-                        count -= hbit ;
+                        count -= hbit;
                         while (hbit--)
                             row[rp++] = turnon ? PBM_BLACK : PBM_WHITE;
-                        for (i = 0; i <= repeatcount; i++) {  /* fill row */
-                            int yi= i+cheight-rowsleft-1;
-                            if (0<=yi && yi < bmy)
+                        for (i = 0; i <= repeatCount; i++) {  /* fill row */
+                            unsigned int const yi = i + cheight - rowsleft - 1;
+                            if (0 <= yi && yi < bmy) {
+                                unsigned int j;
                                 for (j = 0; j < cwidth; j++) {
-                                    int xj= j-xoffs;
-                                    if (0<=xj && xj<bmx)
+                                    unsigned int const xj= j - xoffs;
+                                    if (0 <= xj && xj < bmx)
                                         bitmap[yi][xj] = row[j] ;
                                 }
+                            }
                         }
-                        rowsleft -= repeatcount + 1;
-                        repeatcount = rp = 0 ;
-                        hbit = cwidth ;
+                        rowsleft -= repeatCount + 1;
+                        repeatCount = rp = 0;
+                        hbit = cwidth;
                     }
                 }
-                turnon = !turnon ;
+                turnon = !turnon;
             }
             if (rowsleft != 0 || hbit != cwidth)
                 pm_error("bad pk file (more bits than required)") ;
         }
-        if (endofpacket != pktopbm_pkloc)
+        if (endOfPacket != pkLoc)
             pm_error("bad pk file (bad packet length)") ;
-
-        ofp = pm_openw(filename[car]);
-        filename[car] = NULL;
-        pbm_writepbm(ofp, bitmap, bmx, bmy, 0) ;
-        pbm_freearray(bitmap, bmy) ;
-        pm_close(ofp) ;
-        skipspecials() ;
+        *bitmapP = bitmap;
+        *bmxP    = bmx;
+        *bmyP    = bmy;
     }
-    while (! feof(pkfile)) pktopbm_pkbyte() ;       /* skip trailing junk */
-    pm_close(pkfile);
-    for (car = 0; car < MAXPKCHAR; car++)
-        if (filename[car])
+}
+
+
+
+static void
+generatePbmFile(const char * const fileNm,
+                bit **       const bitmap,
+                unsigned int const cols,
+                unsigned int const rows) {
+
+    FILE * ofP;
+
+    ofP = pm_openw(fileNm);
+
+    pbm_writepbm(ofP, bitmap, cols, rows, 0);
+
+    pm_close(ofP);
+}
+
+
+
+static void
+warnMissingCodePoint() {
+
+    unsigned int car;
+
+    for (car = 0; car < MAXPKCHAR; ++car) {
+        if (fileName[car])
             pm_message("Warning: No character in position %d (file %s).",
-                       car, filename[car]) ;
-    pm_message("%d bytes read from packed file.", pktopbm_pkloc-1) ;
+                       car, fileName[car]) ;
+    }
+}
+
+
+
+int
+main(int argc, const char ** argv) {
+
+    struct CmdlineInfo cmdline;
+    unsigned int i;
+
+    pm_proginit(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+
+    debug = cmdline.debug;
+
+    for (i = 0; i < cmdline.character; ++i)
+        fileName[i] = NULL;
+    for (i = 0; i < cmdline.outputFileCt; ++i)
+        fileName[cmdline.character + i] = cmdline.outputFileNm[i];
+    for (i = cmdline.character + cmdline.outputFileCt;
+         i < MAXPKCHAR;
+         ++i)
+        fileName[i] = NULL;
+
+    ifP = pm_openr(cmdline.inputFileNm);
+
+    pkLoc = 0;
+
+    readHeader();
+
+    while (flagByte != 245) {  /* not at postamble */
+
+        unsigned int car;
+        bool mustIgnore;
+        bit ** bitmap;
+        unsigned int cols, rows;
+
+        readOneCharacter(!!cmdline.xSpec, cmdline.x,
+                         !!cmdline.ySpec, cmdline.y,
+                         &car, &mustIgnore, &bitmap, &cols, &rows);
+
+        if (!mustIgnore) {
+            generatePbmFile(fileName[car], bitmap, cols, rows);
+
+            pbm_freearray(bitmap, rows) ;
+        }
+
+        fileName[car] = NULL;
+
+        skipSpecials();
+    }
+
+    while (!feof(ifP))
+        pkByte() ;       /* skip trailing junk */
+
+    pm_close(ifP);
+
+    warnMissingCodePoint();
+
+    pm_message("%u bytes read from packed file.", pkLoc);
+
     return 0;
 }
+
+
+