about summary refs log tree commit diff
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2022-11-30 18:35:27 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2022-11-30 18:35:27 +0000
commit05018861dc3a7fe3a12227925615a32a1419d0bb (patch)
tree53275ffb3d2a2b456449157edfda4e84cb0f71ed
parentb49f36cbb54909fbae5a1f55f5ec86e053acc2c1 (diff)
downloadnetpbm-mirror-05018861dc3a7fe3a12227925615a32a1419d0bb.tar.gz
netpbm-mirror-05018861dc3a7fe3a12227925615a32a1419d0bb.tar.xz
netpbm-mirror-05018861dc3a7fe3a12227925615a32a1419d0bb.zip
Add -listfile
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@4469 9d0c8265-081b-0410-96cb-a4ca84ce46f8
-rw-r--r--doc/HISTORY3
-rw-r--r--editor/pamcat.c214
2 files changed, 189 insertions, 28 deletions
diff --git a/doc/HISTORY b/doc/HISTORY
index f7d89460..264adecd 100644
--- a/doc/HISTORY
+++ b/doc/HISTORY
@@ -6,6 +6,8 @@ CHANGE HISTORY
 
 not yet  BJH  Release 11.00.01
 
+              pamcat: Add -listfile .
+
               pamtojpeg2k: add -size option.  Doesn't precisely work (and
               -compression has never worked precisely either); should be
               fixed some day.
@@ -16,6 +18,7 @@ not yet  BJH  Release 11.00.01
               packaging: Fix library minor number to 100 + Netpbm minor number
               so it is higher than previous ones in library major 100.
               I.e. libnetpbm.so.100.101 instead of libnetpbm.so.100.1.
+              Introduced in Netpbm 11.00.00.
 
 22.09.28 BJH  Release 11.00.00
 
diff --git a/editor/pamcat.c b/editor/pamcat.c
index c7f0482d..7823bdfc 100644
--- a/editor/pamcat.c
+++ b/editor/pamcat.c
@@ -9,6 +9,8 @@
 
 =============================================================================*/
 
+#include <stdio.h>
+#include <limits.h>
 #include <assert.h>
 
 #include "pm_c_util.h"
@@ -36,12 +38,43 @@ enum Orientation {TOPBOTTOM, LEFTRIGHT};
 enum Justification {JUST_CENTER, JUST_MIN, JUST_MAX};
   /* Justification of images in concatenation */
 
+/* FOPEN_MAX is usually defined in stdio.h, PATH_MAX in limits.h
+   Given below are typical values.  Adjust as necessary.
+ */
+
+#ifndef FOPEN_MAX
+  #define FOPEN_MAX 16
+#endif
+
+#ifndef PATH_MAX
+  #define PATH_MAX 255
+#endif
+
+
+static const char **
+copyOfStringList(const char ** const list,
+                 unsigned int  const size) {
+
+    const char ** retval;
+    unsigned int i;
+
+    MALLOCARRAY_NOFAIL(retval, size);
+
+    for (i = 0; i < size; ++i)
+        retval[i] = pm_strdup(list[i]);
+
+    return retval;
+}
+
+
+
 struct CmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
     const char **       inputFileName;
-    unsigned int        fileCt;
+    unsigned int        inputFileCt;
+    const char *        listfile;  /* NULL if not specified */
     enum PadColorMethod padColorMethod;
     enum Orientation    orientation;
     enum Justification  justification;
@@ -49,7 +82,6 @@ struct CmdlineInfo {
 };
 
 
-
 static void
 parseCommandLine(int argc, const char ** const argv,
                  struct CmdlineInfo * const cmdlineP) {
@@ -67,6 +99,7 @@ parseCommandLine(int argc, const char ** const argv,
     unsigned int leftright, topbottom;
     unsigned int black, white;
     unsigned int jtop, jbottom, jleft, jright, jcenter;
+    unsigned int listfileSpec;
 
     MALLOCARRAY_NOFAIL(option_def, 100);
 
@@ -82,6 +115,8 @@ parseCommandLine(int argc, const char ** const argv,
     OPTENT3(0, "jleft",       OPT_FLAG,   NULL, &jleft,             0);
     OPTENT3(0, "jright",      OPT_FLAG,   NULL, &jright,            0);
     OPTENT3(0, "jcenter",     OPT_FLAG,   NULL, &jcenter,           0);
+    OPTENT3(0, "listfile",    OPT_STRING, &cmdlineP->listfile,
+            &listfileSpec,      0);
     OPTENT3(0, "verbose",     OPT_FLAG,   NULL, &cmdlineP->verbose, 0);
 
     opt.opt_table = option_def;
@@ -148,27 +183,144 @@ parseCommandLine(int argc, const char ** const argv,
         }
     }
 
-    if (argc-1 < 1) {
-        MALLOCARRAY_NOFAIL(cmdlineP->inputFileName, 1);
-        cmdlineP->inputFileName[0] = "-";
-        cmdlineP->fileCt = 1;
+    if (listfileSpec) {
+        if (argc-1 > 0)
+          pm_error ("You can not specify files on the command line and "
+                    "also -listfile.");
     } else {
-        unsigned int i;
-        unsigned int stdinCt;
+        cmdlineP->listfile = NULL;
+
+        if (argc-1 < 1) {
+            MALLOCARRAY_NOFAIL(cmdlineP->inputFileName, 1);
+            cmdlineP->inputFileName[0] = "-";
+            cmdlineP->inputFileCt = 1;
+        } else {
+            unsigned int i;
+            unsigned int stdinCt;
             /* Number of input files user specified as Standard Input */
 
-        MALLOCARRAY_NOFAIL(cmdlineP->inputFileName, argc-1);
+            MALLOCARRAY_NOFAIL(cmdlineP->inputFileName, argc-1);
+
+            for (i = 0, stdinCt = 0; i < argc-1; ++i) {
+                cmdlineP->inputFileName[i] = argv[1+i];
+                if (streq(argv[1+i], "-"))
+                    ++stdinCt;
+            }
+            cmdlineP->inputFileCt = argc-1;
+            if (stdinCt > 1)
+                pm_error("At most one input image can come from "
+                         "Standard Input.  You specified %u", stdinCt);
+        }
+    }
+}
+
+
+
+static void
+freeCmdLine(struct CmdlineInfo const cmdline) {
+
+    if (!cmdline.listfile)
+        free(cmdline.inputFileName);
+}
+
+
 
-        for (i = 0, stdinCt = 0; i < argc-1; ++i) {
-            cmdlineP->inputFileName[i] = argv[1+i];
-            if (streq(argv[1+i], "-"))
-                ++stdinCt;
+static void
+createInFileListFmFile(const char  *        const listFileNm,
+                       bool                 const verbose,
+                       const char ***       const inputFileNmP,
+                       unsigned int *       const inputFileCtP) {
+
+    FILE * const lfP = pm_openr(listFileNm);
+
+    const char ** inputFileNm;
+    unsigned int inputFileCt;
+    unsigned int emptyLineCt;
+    unsigned int stdinCt;
+    int eof;
+
+    MALLOCARRAY_NOFAIL(inputFileNm, FOPEN_MAX);
+
+    for (inputFileCt = emptyLineCt = stdinCt = eof = 0; !eof; ) {
+
+        size_t lineLen;
+        char * buf;
+        size_t bufferSz;
+
+        buf = NULL;  /* initial value */
+        bufferSz = 0;  /* initial value */
+
+        pm_getline(lfP, &buf, &bufferSz, &eof, &lineLen);
+
+        if (!eof) {
+            if (lineLen == 0)
+                ++emptyLineCt;
+            else if (lineLen > PATH_MAX)
+                pm_error("Path/file name in list file is too long "
+                         "(%u bytes).  Maximum is %u bytes",
+                         (unsigned)lineLen, PATH_MAX);
+            else /* 0 < lineLen < PATH_MAX */ {
+                if (inputFileCt >= FOPEN_MAX)
+                    pm_error("Too many files in list file.  Maximum is %u",
+                             FOPEN_MAX);
+                else {
+                    inputFileNm[inputFileCt] = buf;
+                    ++inputFileCt;
+                    if (streq(buf, "-"))
+                        ++stdinCt;
+                }
+            }
         }
-        cmdlineP->fileCt = argc-1;
-        if (stdinCt > 1)
-            pm_error("At most one input image can come from Standard Input.  "
-                     "You specified %u", stdinCt);
     }
+
+    pm_close(lfP);
+
+    if (stdinCt > 1)
+        pm_error("At most one input image can come from Standard Input.  "
+                 "You specified %u", stdinCt);
+
+    if (inputFileCt == 0)
+        pm_error("No files specified in list file.");
+
+    if (verbose) {
+        pm_message("%u files specified and %u blank lines in list file",
+                   inputFileCt, emptyLineCt);
+    }
+
+    *inputFileCtP = inputFileCt;
+    *inputFileNmP = inputFileNm;
+}
+
+
+
+static void
+createInFileList(struct CmdlineInfo const cmdline,
+                 bool               const verbose,
+                 const char ***     const inputFileNmP,
+                 unsigned int *     const inputFileCtP) {
+
+    if (cmdline.listfile)
+        createInFileListFmFile(cmdline.listfile, verbose,
+                               inputFileNmP, inputFileCtP);
+    else {
+        *inputFileCtP = cmdline.inputFileCt;
+        *inputFileNmP = copyOfStringList(cmdline.inputFileName,
+                                         cmdline.inputFileCt);
+    }
+}
+
+
+
+static void
+freeInFileList(const char ** const inputFileNm,
+               unsigned int  const inputFileCt) {
+
+    unsigned int i;
+
+    for (i = 0; i < inputFileCt; ++i)
+        pm_strfree(inputFileNm[i]);
+
+    free(inputFileNm);
 }
 
 
@@ -1237,6 +1389,8 @@ main(int           argc,
      const char ** argv) {
 
     struct CmdlineInfo cmdline;
+    const char ** inputFileNm;
+    unsigned int inputFileCt;
     struct pam * inpam;  /* malloc'ed array */
     struct pam outpam;
     unsigned int i;
@@ -1245,20 +1399,23 @@ main(int           argc,
 
     parseCommandLine(argc, argv, &cmdline);
 
-    MALLOCARRAY_NOFAIL(inpam, cmdline.fileCt);
+    createInFileList(cmdline, !!cmdline.verbose, &inputFileNm, &inputFileCt);
+
+    MALLOCARRAY_NOFAIL(inpam, inputFileCt);
 
-    for (i = 0; i < cmdline.fileCt; ++i) {
-        FILE * const ifP = pm_openr(cmdline.inputFileName[i]);
+    for (i = 0; i < inputFileCt; ++i) {
+        FILE *  ifP;
+        ifP = pm_openr(inputFileNm[i]);
         inpam[i].comment_p = NULL;  /* Don't want to see the comments */
         pnm_readpaminit(ifP, &inpam[i], PAM_STRUCT_SIZE(opacity_plane));
     }
 
-    computeOutputParms(cmdline.fileCt, cmdline.orientation, inpam,
+    computeOutputParms(inputFileCt, cmdline.orientation, inpam,
                        cmdline.verbose, &outpam);
 
     outpam.file = stdout;
 
-    for (i = 0; i < cmdline.fileCt; ++i)
+    for (i = 0; i < inputFileCt; ++i)
         pnm_setminallocationdepth(&inpam[i], outpam.depth);
 
     pnm_writepaminit(&outpam);
@@ -1266,12 +1423,12 @@ main(int           argc,
     if (outpam.format == RPBM_FORMAT) {
         switch (cmdline.orientation) {
         case LEFTRIGHT:
-            concatenateLeftRightPbm(&outpam, inpam, cmdline.fileCt,
+            concatenateLeftRightPbm(&outpam, inpam, inputFileCt,
                                     cmdline.justification,
                                     cmdline.padColorMethod);
             break;
         case TOPBOTTOM:
-            concatenateTopBottomPbm(&outpam, inpam, cmdline.fileCt,
+            concatenateTopBottomPbm(&outpam, inpam, inputFileCt,
                                     cmdline.justification,
                                     cmdline.padColorMethod);
             break;
@@ -1279,21 +1436,22 @@ main(int           argc,
     } else {
         switch (cmdline.orientation) {
         case LEFTRIGHT:
-            concatenateLeftRightGen(&outpam, inpam, cmdline.fileCt,
+            concatenateLeftRightGen(&outpam, inpam, inputFileCt,
                                     cmdline.justification,
                                     cmdline.padColorMethod);
             break;
         case TOPBOTTOM:
-            concatenateTopBottomGen(&outpam, inpam, cmdline.fileCt,
+            concatenateTopBottomGen(&outpam, inpam, inputFileCt,
                                     cmdline.justification,
                                     cmdline.padColorMethod);
             break;
         }
     }
-    for (i = 0; i < cmdline.fileCt; ++i)
+    for (i = 0; i < inputFileCt; ++i)
         pm_close(inpam[i].file);
-    free(cmdline.inputFileName);
     free(inpam);
+    freeInFileList(inputFileNm, inputFileCt);
+    freeCmdLine(cmdline);
     pm_close(stdout);
 
     return 0;