about summary refs log tree commit diff
path: root/editor
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2020-02-16 04:19:43 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2020-02-16 04:19:43 +0000
commit7e8574e4fbe371768eb8bb372741c92c1cb25907 (patch)
tree5a8991eb649082bb451fe2533160dab293a8e156 /editor
parent3e1f9cb3b38e68d3e273a0e37c372f158ed0c17c (diff)
downloadnetpbm-mirror-7e8574e4fbe371768eb8bb372741c92c1cb25907.tar.gz
netpbm-mirror-7e8574e4fbe371768eb8bb372741c92c1cb25907.tar.xz
netpbm-mirror-7e8574e4fbe371768eb8bb372741c92c1cb25907.zip
Add -listfile, sanity checks on file name pattern
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@3739 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'editor')
-rw-r--r--editor/pamundice.c418
1 files changed, 277 insertions, 141 deletions
diff --git a/editor/pamundice.c b/editor/pamundice.c
index aae3d65b..60360f17 100644
--- a/editor/pamundice.c
+++ b/editor/pamundice.c
@@ -18,27 +18,25 @@
 #include "nstring.h"
 #include "mallocvar.h"
 
-#define MAXFILENAMELEN 80
-    /* Maximum number of characters we accept in filenames */
-
-struct cmdlineInfo {
+struct CmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
     const char * inputFilePattern;
-        /* null-terminated string, max MAXFILENAMELEN-10 characters */
     unsigned int across;
     unsigned int down;
     unsigned int hoverlap;
     unsigned int voverlap;
+    const char * listfile;
+    unsigned int listfileSpec;
     unsigned int verbose;
 };
 
 
 
 static void
-parseCommandLine(int argc, char ** argv,
-                 struct cmdlineInfo * const cmdlineP ) {
+parseCommandLine(int argc, const char ** argv,
+                 struct CmdlineInfo * const cmdlineP ) {
 /*----------------------------------------------------------------------------
    parse program command line described in Unix standard form by argc
    and argv.  Return the information in the options as *cmdlineP.
@@ -69,6 +67,8 @@ parseCommandLine(int argc, char ** argv,
             &hoverlapSpec,                    0);
     OPTENT3(0, "voverlap",    OPT_UINT,    &cmdlineP->voverlap,
             &voverlapSpec,                    0);
+    OPTENT3(0, "listfile",    OPT_STRING,  &cmdlineP->listfile,
+            &cmdlineP->listfileSpec,          0);
     OPTENT3(0, "verbose",     OPT_FLAG,    NULL,
             &cmdlineP->verbose,               0);
 
@@ -76,13 +76,19 @@ 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 */
 
-    pm_optParseOptions3( &argc, argv, opt, sizeof(opt), 0 );
+    pm_optParseOptions3( &argc, (char **)argv, opt, sizeof(opt), 0 );
         /* Uses and sets argc, argv, and some of *cmdline_p and others. */
 
-    if (!acrossSpec)
+    if (acrossSpec) {
+        if (cmdlineP->across == 0)
+            pm_error ("-across value must be positive");
+    } else
         cmdlineP->across = 1;
 
-    if (!downSpec)
+    if (downSpec) {
+        if (cmdlineP->down == 0)
+            pm_error ("-down value must be positive");
+    } else
         cmdlineP->down = 1;
 
     if (!hoverlapSpec)
@@ -91,16 +97,23 @@ parseCommandLine(int argc, char ** argv,
     if (!voverlapSpec)
         cmdlineP->voverlap = 0;
 
-    if (argc-1 < 1)
-        pm_error("You must specify one argument: the input file name "
-                 "pattern (e.g. 'myimage%%2a%%2d.pnm')");
-    else {
-        cmdlineP->inputFilePattern = argv[1];
-
-        if (argc-1 > 1)
-            pm_error("Program takes at most one parameter: input file name.  "
-                     "You specified %u", argc-1);
+    if (cmdlineP->listfileSpec) {
+        if (argc-1 > 0)
+            pm_error("Program takes no parameters when -listfile is "
+                     "specified.  You specified %u", argc-1);
+        else
+            cmdlineP->inputFilePattern = NULL;
+    } else {
+        if (argc-1 < 1)
+            pm_error("You must specify one argument, the input file name "
+                     "pattern (e.g. 'myimage%%2a%%2d.pnm'), or -listfile");
+        else if (argc-1 > 1)
+            pm_error("Program takes at most one parameter: "
+                     "the input file name pattern.  You specified %u", argc-1);
+        else
+            cmdlineP->inputFilePattern = argv[1];
     }
+    free(option_def);
 }
 
 
@@ -202,13 +215,24 @@ getPrecision(const char *   const pattern,
 
 
 
+typedef struct {
+    /* Context of % substitutions as we progress through a file name pattern */
+    bool downSub;
+        /* There has been a %d (down) substitution */
+    bool acrossSub;
+        /* There has been a %a (across) substitution */
+} SubstContext;
+
+
+
 static void
 doSubstitution(const char *    const pattern,
                unsigned int    const startInCursor,
                unsigned int    const rank,
                unsigned int    const file,
                struct buffer * const bufferP,
-               unsigned int *  const newInCursorP) {
+               unsigned int *  const newInCursorP,
+               SubstContext *  const substContextP) {
 
     unsigned int inCursor;
 
@@ -232,16 +256,28 @@ doSubstitution(const char *    const pattern,
 
             switch (pattern[inCursor]) {
             case 'a':
-                pm_asprintf(&substString, "%0*u", precision, file);
-                pm_asprintf(&desc, "file (across)");
+                if (substContextP->acrossSub)
+                    pm_error("Format specifier 'a' appears more than "
+                             "once in input file pattern '%s'", pattern);
+                else {
+                    pm_asprintf(&substString, "%0*u", precision, file);
+                    pm_asprintf(&desc, "file (across)");
+                    substContextP->acrossSub = true;
+                }
                 break;
             case 'd':
-                pm_asprintf(&substString, "%0*u", precision, rank);
-                pm_asprintf(&desc, "rank (down)");
+                if (substContextP->downSub)
+                    pm_error("Format specifier 'd' appears more than "
+                             "once in input file pattern '%s'", pattern);
+                else {
+                    pm_asprintf(&substString, "%0*u", precision, rank);
+                    pm_asprintf(&desc, "rank (down)");
+                    substContextP->downSub = true;
+                }
                 break;
             default:
                 pm_error("Unknown format specifier '%c' in input file "
-                         "pattern '%s'.  Recognized format specifier s are "
+                         "pattern '%s'.  Recognized format specifiers are "
                          "'%%a' (across) and '%%d (down)'",
                          pattern[inCursor], pattern);
             }
@@ -268,25 +304,32 @@ static void
 computeInputFileName(const char *  const pattern,
                      unsigned int  const rank,
                      unsigned int  const file,
-                     const char ** const fileNameP) {
+                     const char ** const fileNameP,
+                     bool *        const rankFileIndependentP) {
 
     struct buffer buffer;
     unsigned int inCursor;
+    SubstContext substContext;
 
     buffer_init(&buffer);
 
     inCursor = 0;
+    substContext.downSub   = 0;
+    substContext.acrossSub = 0;
 
     while (pattern[inCursor] != '\0') {
         if (pattern[inCursor] == '%') {
             ++inCursor;
 
-            doSubstitution(pattern, inCursor, rank, file, &buffer, &inCursor);
+            doSubstitution(pattern, inCursor, rank, file, &buffer, &inCursor,
+                           &substContext);
 
         } else
             buffer_addChar(&buffer, pattern[inCursor++]);
     }
 
+    *rankFileIndependentP = !substContext.downSub && !substContext.acrossSub;
+
     pm_asprintf(fileNameP, "%s", buffer.string);
 
     buffer_term(&buffer);
@@ -295,8 +338,127 @@ computeInputFileName(const char *  const pattern,
 
 
 
+
+static void
+createInFileListFmFile(const char  *  const listFile,
+                       unsigned int   const nRank,
+                       unsigned int   const nFile,
+                       const char *** const inputFileListP) {
+
+    FILE * const lfP = pm_openr(listFile);
+    unsigned int const fileCt = nRank * nFile;
+
+    const char ** inputFileList;
+    unsigned int fileSeq;
+
+    MALLOCARRAY_NOFAIL(inputFileList, nRank * nFile);
+
+    for (fileSeq = 0; fileSeq < fileCt; ) {
+        int eof;
+        size_t lineLen;
+        char * buf = NULL;   /* initial value */
+        size_t bufferSz = 0; /* initial value */
+
+        pm_getline(lfP, &buf, &bufferSz, &eof, &lineLen);
+
+        if (eof)
+            pm_error("Premature EOF reading list file.  "
+                     "Read %u files.  Should be %u.", fileSeq, fileCt);
+        else if (lineLen > 0) {
+            inputFileList[fileSeq] = buf;
+            ++fileSeq;
+        }
+    }
+    pm_close(lfP);
+
+    *inputFileListP = inputFileList;
+
+}
+
+
+
+static void
+createInFileListFmPattern(const char  *  const pattern,
+                          unsigned int   const nRank,
+                          unsigned int   const nFile,
+                          const char *** const inputFileListP) {
+
+    const char ** inputFileList;
+    unsigned int rank, file;
+    bool warnedSingleFile;
+
+    MALLOCARRAY_NOFAIL(inputFileList, nRank * nFile);
+
+    for (rank = 0, warnedSingleFile = false; rank < nRank ; ++rank) {
+         for (file = 0; file < nFile ; ++file) {
+             const unsigned int idx = rank * nFile + file;
+
+             bool fileNmIsRankFileIndependent;
+
+             computeInputFileName(pattern, rank, file, &inputFileList[idx],
+                                  &fileNmIsRankFileIndependent);
+
+             if (fileNmIsRankFileIndependent && !warnedSingleFile) {
+                 pm_message("Warning: No grid location (%%a/%%d) specified "
+                            "in input file pattern '%s'.  "
+                            "Input is single file", pattern);
+                 warnedSingleFile = true;
+             }
+         }
+    }
+    *inputFileListP = inputFileList;
+}
+
+
+
+static void
+destroyInFileList(const char ** const inputFileList,
+                  unsigned int  const nRank,
+                  unsigned int  const nFile) {
+
+    unsigned int const fileCt = nRank * nFile;
+
+    unsigned int fileSeq;
+
+    for (fileSeq = 0; fileSeq < fileCt; ++fileSeq)
+        pm_strfree(inputFileList[fileSeq]);
+
+    free(inputFileList);
+}
+
+
+
+typedef struct {
+    unsigned int nRank;  /* Number of images in the vertical direction */
+    unsigned int nFile;  /* Number of images in the horizontal direction */
+    unsigned int hoverlap;    /* horizontal overlap */
+    unsigned int voverlap;    /* vertical overlap */
+    const char ** list;  /* List (1-dimensional array) of filenames */
+                         /* Row-major, top to bottom, left to right */
+} InputFiles;
+
+
+
+static const char *
+inputFileName(InputFiles     const inputFiles,
+              unsigned int   const rank,
+              unsigned int   const file) {
+/*----------------------------------------------------------------------------
+    A selected entry from "inputFiles.list" based on "rank" and "file".
+
+    Currently we assume that the list is a one-dimensional represetation
+    of an array, row-major, top to bottom and left to right in each row.
+----------------------------------------------------------------------------*/
+    assert(rank < inputFiles.nRank);
+    assert(file < inputFiles.nFile);
+
+    return inputFiles.list[rank * inputFiles.nFile + file];
+}
+
+
+
 static void
-getCommonInfo(const char *   const inputFilePattern,
+getCommonInfo(InputFiles     const inputFiles,
               int *          const formatP,
               unsigned int * const depthP,
               sample *       const maxvalP,
@@ -306,16 +468,12 @@ getCommonInfo(const char *   const inputFilePattern,
    among all input images and the output image.  I.e. everything except
    width and height.
 -----------------------------------------------------------------------------*/
-    const char * fileName;
-        /* Name of top left input image */
     FILE * ifP;
         /* Top left input image stream */
     struct pam inpam00;
         /* Description of top left input image */
 
-    computeInputFileName(inputFilePattern, 0, 0, &fileName);
-
-    ifP = pm_openr(fileName);
+    ifP = pm_openr(inputFileName(inputFiles, 0, 0));
 
     pnm_readpaminit(ifP, &inpam00, PAM_STRUCT_SIZE(tuple_type));
 
@@ -325,40 +483,19 @@ getCommonInfo(const char *   const inputFilePattern,
     strcpy(tupleType, inpam00.tuple_type);
 
     pm_close(ifP);
-
-    pm_strfree(fileName);
-}
-
-
-
-static FILE *
-openInputImage(const char * const inputFilePattern,
-               unsigned int const rank,
-               unsigned int const file) {
-
-    FILE * retval;
-    const char * fileName;
-
-    computeInputFileName(inputFilePattern, rank, file, &fileName);
-
-    retval = pm_openr(fileName);
-
-    pm_strfree(fileName);
-
-    return retval;
 }
 
 
 
 static void
-getImageInfo(const char * const inputFilePattern,
+getImageInfo(InputFiles   const inputFiles,
              unsigned int const rank,
              unsigned int const file,
              struct pam * const pamP) {
 
     FILE * ifP;
 
-    ifP = openInputImage(inputFilePattern, rank, file);
+    ifP = pm_openr(inputFileName(inputFiles, rank, file));
 
     pnm_readpaminit(ifP, pamP, PAM_STRUCT_SIZE(tuple_type));
 
@@ -369,76 +506,70 @@ getImageInfo(const char * const inputFilePattern,
 
 
 static void
-getOutputWidth(const char * const inputFilePattern,
-               unsigned int const nFile,
-               unsigned int const hoverlap,
-               int *        const widthP) {
+getOutputWidth(InputFiles const inputFiles,
+               int *      const widthP) {
 /*----------------------------------------------------------------------------
-   Get the output width by adding up the widths of all 'nFile' images of
-   the top rank, and allowing for overlap of 'hoverlap' pixels.
+   Get the output width by adding up the widths of all 'inputFiles.nFile'
+   images of the top rank, and allowing for overlap of 'inputFiles.hoverlap'
+   pixels.
 -----------------------------------------------------------------------------*/
-    unsigned int totalWidth;
+    double       totalWidth;
     unsigned int file;
 
-    for (file = 0, totalWidth = 0; file < nFile; ++file) {
+    for (file = 0, totalWidth = 0; file < inputFiles.nFile; ++file) {
         struct pam inpam;
 
-        getImageInfo(inputFilePattern, 0, file, &inpam);
+        getImageInfo(inputFiles, 0, file, &inpam);
 
-        if (inpam.width < hoverlap)
+        if (inpam.width < inputFiles.hoverlap)
             pm_error("Rank 0, file %u image has width %u, "
                      "which is less than the horizontal overlap of %u pixels",
-                     file, inpam.width, hoverlap);
+                     file, inpam.width, inputFiles.hoverlap);
         else {
             totalWidth += inpam.width;
 
-            if (file < nFile-1)
-                totalWidth -= hoverlap;
+            if (file < inputFiles.nFile-1)
+                totalWidth -= inputFiles.hoverlap;
         }
     }
-    *widthP = totalWidth;
+    *widthP = (int) totalWidth;
 }
 
 
 
 static void
-getOutputHeight(const char *  const inputFilePattern,
-                unsigned int  const nRank,
-                unsigned int  const voverlap,
-                int *         const heightP) {
+getOutputHeight(InputFiles const inputFiles,
+                int *      const heightP) {
 /*----------------------------------------------------------------------------
-   Get the output height by adding up the widths of all 'nRank' images of
-   the left file, and allowing for overlap of 'voverlap' pixels.
+   Get the output height by adding up the widths of all 'inputFiles.nRank'
+   images of the left file, and allowing for overlap of 'inputFiles.voverlap'
+   pixels.
 -----------------------------------------------------------------------------*/
-    unsigned int totalHeight;
+    double       totalHeight;
     unsigned int rank;
 
-    for (rank = 0, totalHeight = 0; rank < nRank; ++rank) {
+    for (rank = 0, totalHeight = 0; rank < inputFiles.nRank; ++rank) {
         struct pam inpam;
 
-        getImageInfo(inputFilePattern, rank, 0, &inpam);
+        getImageInfo(inputFiles, rank, 0, &inpam);
 
-        if (inpam.height < voverlap)
+        if (inpam.height < inputFiles.voverlap)
             pm_error("Rank %u, file 0 image has height %u, "
                      "which is less than the vertical overlap of %u pixels",
-                     rank, inpam.height, voverlap);
+                     rank, inpam.height, inputFiles.voverlap);
 
         totalHeight += inpam.height;
 
-        if (rank < nRank-1)
-            totalHeight -= voverlap;
+        if (rank < inputFiles.nRank-1)
+            totalHeight -= inputFiles.voverlap;
     }
-    *heightP = totalHeight;
+    *heightP = (int) totalHeight;
 }
 
 
 
 static void
-initOutpam(const char * const inputFilePattern,
-           unsigned int const nFile,
-           unsigned int const nRank,
-           unsigned int const hoverlap,
-           unsigned int const voverlap,
+initOutpam(InputFiles   const inputFiles,
            FILE *       const ofP,
            bool         const verbose,
            struct pam * const outpamP) {
@@ -447,10 +578,10 @@ initOutpam(const char * const inputFilePattern,
    *outpamP.
 
    Do this by examining the top rank and left file of the input images,
-   which are in files named by 'inputFilePattern', 'nFile', and 'nRank'.
+   which are in 'inputFiles.list'.
 
-   In computing dimensions, assume 'hoverlap' pixels of horizontal
-   overlap and 'voverlap' pixels of vertical overlap.
+   In computing dimensions, assume 'inputFiles.hoverlap' pixels of horizontal
+   overlap and 'inputFiles.voverlap' pixels of vertical overlap.
 
    We overlook any inconsistencies among the images.  E.g. if two images
    have different depths, we just return one of them.  If two images in
@@ -459,23 +590,23 @@ initOutpam(const char * const inputFilePattern,
    Therefore, Caller must check all the input images to make sure they are
    consistent with the information we return.
 -----------------------------------------------------------------------------*/
-    assert(nFile >= 1);
-    assert(nRank >= 1);
+    assert(inputFiles.nFile >= 1);
+    assert(inputFiles.nRank >= 1);
 
     outpamP->size        = sizeof(*outpamP);
     outpamP->len         = PAM_STRUCT_SIZE(tuple_type);
     outpamP->file        = ofP;
     outpamP->plainformat = 0;
 
-    getCommonInfo(inputFilePattern, &outpamP->format, &outpamP->depth,
+    getCommonInfo(inputFiles, &outpamP->format, &outpamP->depth,
                   &outpamP->maxval, outpamP->tuple_type);
 
-    getOutputWidth(inputFilePattern, nFile, hoverlap, &outpamP->width);
+    getOutputWidth(inputFiles,  &outpamP->width);
 
-    getOutputHeight(inputFilePattern, nRank, voverlap, &outpamP->height);
+    getOutputHeight(inputFiles, &outpamP->height);
 
     if (verbose) {
-        pm_message("Output width = %u pixels", outpamP->width);
+        pm_message("Output width = %u pixels",  outpamP->width);
         pm_message("Output height = %u pixels", outpamP->height);
     }
 }
@@ -485,22 +616,19 @@ initOutpam(const char * const inputFilePattern,
 static void
 openInStreams(struct pam         inpam[],
               unsigned int const rank,
-              unsigned int const fileCount,
-              char         const inputFilePattern[]) {
+              InputFiles   const inputFiles) {
 /*----------------------------------------------------------------------------
    Open the input files for a single horizontal slice (there's one file
    for each vertical slice) and read the Netpbm headers from them.  Return
    the pam structures to describe each as inpam[].
 
-   Open the files for horizontal slice number 'rank', assuming there are
-   'fileCount' vertical slices (so open 'fileCount' files).  Use
-   inputFilePattern[] with each rank and file number to compute the name of
-   each file.
+   Open the files for horizontal slice number 'rank', as described by
+   'inputFiles'.
 -----------------------------------------------------------------------------*/
     unsigned int file;
 
-    for (file = 0; file < fileCount; ++file) {
-        FILE * const ifP = openInputImage(inputFilePattern, rank, file);
+    for (file = 0; file < inputFiles.nFile; ++file) {
+        FILE * const ifP = pm_openr(inputFileName(inputFiles, rank, file));
 
         pnm_readpaminit(ifP, &inpam[file], PAM_STRUCT_SIZE(tuple_type));
     }
@@ -510,14 +638,14 @@ openInStreams(struct pam         inpam[],
 
 static void
 closeInFiles(struct pam         pam[],
-             unsigned int const fileCount) {
+             unsigned int const fileCt) {
 /*----------------------------------------------------------------------------
-   Close the 'fileCount' input file streams represented by pam[].
+   Close the 'fileCt' input file streams represented by pam[].
 -----------------------------------------------------------------------------*/
-    unsigned int file;
+    unsigned int fileSeq;
 
-    for (file = 0; file < fileCount; ++file)
-        pm_close(pam[file].file);
+    for (fileSeq = 0; fileSeq < fileCt; ++fileSeq)
+        pm_close(pam[fileSeq].file);
 }
 
 
@@ -525,13 +653,13 @@ closeInFiles(struct pam         pam[],
 static void
 assembleRow(tuple              outputRow[],
             struct pam         inpam[],
-            unsigned int const fileCount,
+            unsigned int const fileCt,
             unsigned int const hOverlap) {
 /*----------------------------------------------------------------------------
-   Assemble the row outputRow[] from the 'fileCount' input files
+   Assemble the row outputRow[] from the 'fileCt' input files
    described out inpam[].
 
-   'hOverlap', which is meaningful only when fileCount is greater than 1,
+   'hOverlap', which is meaningful only when 'fileCt' is greater than 1,
    is the amount by which files overlap each other.  We assume every
    input image is at least that wide.
 
@@ -539,19 +667,17 @@ assembleRow(tuple              outputRow[],
    entire assembly.
 -----------------------------------------------------------------------------*/
     tuple * inputRow;
-    unsigned int file;
+    unsigned int fileSeq;
 
-    for (file = 0, inputRow = &outputRow[0];
-         file < fileCount;
-         ++file) {
+    for (fileSeq = 0, inputRow = &outputRow[0]; fileSeq < fileCt; ++fileSeq) {
 
-        unsigned int const overlap = file == fileCount - 1 ? 0 : hOverlap;
+        unsigned int const overlap = fileSeq == fileCt - 1 ? 0 : hOverlap;
 
-        assert(hOverlap <= inpam[file].width);
+        assert(hOverlap <= inpam[fileSeq].width);
 
-        pnm_readpamrow(&inpam[file], inputRow);
+        pnm_readpamrow(&inpam[fileSeq], inputRow);
 
-        inputRow += inpam[file].width - overlap;
+        inputRow += inpam[fileSeq].width - overlap;
     }
 }
 
@@ -574,6 +700,7 @@ allocInpam(unsigned int  const rankCount,
 
 
 
+
 static void
 verifyRankFileAttributes(struct pam *       const inpam,
                          unsigned int       const nFile,
@@ -637,11 +764,7 @@ verifyRankFileAttributes(struct pam *       const inpam,
 
 static void
 assembleTiles(struct pam * const outpamP,
-              const char * const inputFilePattern,
-              unsigned int const nFile,
-              unsigned int const nRank,
-              unsigned int const hoverlap,
-              unsigned int const voverlap,
+              InputFiles   const inputFiles,
               struct pam         inpam[],
               tuple *      const tuplerow) {
 
@@ -650,11 +773,16 @@ assembleTiles(struct pam * const outpamP,
            sequentially starting at 0.
         */
 
+    unsigned int const nRank    = inputFiles.nRank;
+    unsigned int const nFile    = inputFiles.nFile;
+    unsigned int const hoverlap = inputFiles.hoverlap;
+    unsigned int const voverlap = inputFiles.voverlap;
+
     for (rank = 0; rank < nRank; ++rank) {
         unsigned int row;
         unsigned int rankHeight;
 
-        openInStreams(inpam, rank, nFile, inputFilePattern);
+        openInStreams(inpam, rank, inputFiles);
 
         verifyRankFileAttributes(inpam, nFile, outpamP, hoverlap, rank);
 
@@ -672,9 +800,10 @@ assembleTiles(struct pam * const outpamP,
 
 
 int
-main(int argc, char ** argv) {
+main(int argc, const char ** argv) {
 
-    struct cmdlineInfo cmdline;
+    struct CmdlineInfo cmdline;
+    InputFiles inputFiles;
     struct pam outpam;
     struct pam * inpam;
         /* malloc'ed.  inpam[x] is the pam structure that controls the
@@ -682,30 +811,37 @@ main(int argc, char ** argv) {
         */
     tuple * tuplerow;
 
-    pnm_init(&argc, argv);
+    pm_proginit(&argc, argv);
 
     parseCommandLine(argc, argv, &cmdline);
 
     allocInpam(cmdline.across, &inpam);
 
-    initOutpam(cmdline.inputFilePattern, cmdline.across, cmdline.down,
-               cmdline.hoverlap, cmdline.voverlap, stdout, cmdline.verbose,
-               &outpam);
+    if (cmdline.listfileSpec)
+        createInFileListFmFile(cmdline.listfile,
+                               cmdline.down, cmdline.across,
+                               &inputFiles.list);
+    else
+        createInFileListFmPattern(cmdline.inputFilePattern,
+                                  cmdline.down, cmdline.across,
+                                  &inputFiles.list);
+
+    inputFiles.nFile    = cmdline.across;
+    inputFiles.nRank    = cmdline.down;
+    inputFiles.hoverlap = cmdline.hoverlap;
+    inputFiles.voverlap = cmdline.voverlap;
+
+    initOutpam(inputFiles, stdout, cmdline.verbose, &outpam);
 
     tuplerow = pnm_allocpamrow(&outpam);
 
     pnm_writepaminit(&outpam);
 
-    assembleTiles(&outpam,
-                  cmdline.inputFilePattern, cmdline.across, cmdline.down,
-                  cmdline.hoverlap, cmdline.voverlap, inpam, tuplerow);
+    assembleTiles(&outpam, inputFiles, inpam, tuplerow);
 
     pnm_freepamrow(tuplerow);
-
+    destroyInFileList(inputFiles.list, inputFiles.nRank, inputFiles.nFile);
     free(inpam);
 
     return 0;
 }
-
-
-