about summary refs log tree commit diff
path: root/lib/libppm1.c
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2006-08-29 16:19:20 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2006-08-29 16:19:20 +0000
commit89973760e357aaf87b834f93e133ffb76b157d4b (patch)
tree2c24ce7e2601af9836726b0d5b91af8ef204c134 /lib/libppm1.c
parent3821270a4899d4d9915bcc9f105b65b849467a3f (diff)
downloadnetpbm-mirror-89973760e357aaf87b834f93e133ffb76b157d4b.tar.gz
netpbm-mirror-89973760e357aaf87b834f93e133ffb76b157d4b.tar.xz
netpbm-mirror-89973760e357aaf87b834f93e133ffb76b157d4b.zip
Add pm_errormsg(), pm_setusererrormsg(), pm_setusermessage(), release memory before longjmping
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@30 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'lib/libppm1.c')
-rw-r--r--lib/libppm1.c290
1 files changed, 199 insertions, 91 deletions
diff --git a/lib/libppm1.c b/lib/libppm1.c
index 57a1db7d..a7ea78cf 100644
--- a/lib/libppm1.c
+++ b/lib/libppm1.c
@@ -19,6 +19,7 @@
 #include <string.h>
 #include <stdio.h>
 #include <errno.h>
+
 #include "ppm.h"
 #include "libppm.h"
 #include "pgm.h"
@@ -29,6 +30,7 @@
 #include "libpam.h"
 #include "fileio.h"
 #include "mallocvar.h"
+#include "nstring.h"
 
 
 pixel *
@@ -150,124 +152,211 @@ ppm_readppminit(FILE *   const fileP,
 
 
 
-void
-ppm_readppmrow(FILE*  const fileP, 
-               pixel* const pixelrow, 
-               int    const cols, 
-               pixval const maxval, 
-               int    const format) {
-
-    switch (format) {
-    case PPM_FORMAT: {
-        unsigned int col;
-        for (col = 0; col < cols; ++col) {
-            pixval const r = pm_getuint(fileP);
-            pixval const g = pm_getuint(fileP);
-            pixval const b = pm_getuint(fileP);
-
-            if (r > maxval)
-                pm_error("Red sample value %u is greater than maxval (%u)",
-                         r, maxval);
-            if (g > maxval)
-                pm_error("Green sample value %u is greater than maxval (%u)",
-                         g, maxval);
-            if (b > maxval)
-                pm_error("Blue sample value %u is greater than maxval (%u)",
-                         b, maxval);
-
-            PPM_ASSIGN(pixelrow[col], r, g, b);
-        }
+static void
+readppm(FILE *       const fileP, 
+        pixel *      const pixelrow, 
+        unsigned int const cols, 
+        pixval       const maxval, 
+        int          const format) {
+
+    unsigned int col;
+
+    for (col = 0; col < cols; ++col) {
+        pixval const r = pm_getuint(fileP);
+        pixval const g = pm_getuint(fileP);
+        pixval const b = pm_getuint(fileP);
+        
+        if (r > maxval)
+            pm_error("Red sample value %u is greater than maxval (%u)",
+                     r, maxval);
+        if (g > maxval)
+            pm_error("Green sample value %u is greater than maxval (%u)",
+                     g, maxval);
+        if (b > maxval)
+            pm_error("Blue sample value %u is greater than maxval (%u)",
+                     b, maxval);
+        
+        PPM_ASSIGN(pixelrow[col], r, g, b);
     }
-    break;
+}
 
-    /* For PAM, we require a depth of 3, which means the raster format
-       is identical to Raw PPM!  How convenient.
-    */
-    case PAM_FORMAT:
-    case RPPM_FORMAT: {
-        unsigned int const bytesPerSample = maxval < 256 ? 1 : 2;
-        unsigned int const bytesPerRow    = cols * 3 * bytesPerSample;
-        
-        unsigned int bufferCursor;
-        unsigned char * rowBuffer;
-        ssize_t rc;
 
-        MALLOCARRAY(rowBuffer, bytesPerRow);
+
+static void
+readrppm(FILE *       const fileP, 
+         pixel *      const pixelrow, 
+         unsigned int const cols, 
+         pixval       const maxval, 
+         int          const format) {
+
+    unsigned int const bytesPerSample = maxval < 256 ? 1 : 2;
+    unsigned int const bytesPerRow    = cols * 3 * bytesPerSample;
         
-        if (rowBuffer == NULL)
-            pm_error("Unable to allocate memory for row buffer "
-                     "for %u columns", cols);
+    unsigned char * rowBuffer;
+    const char * error;
+    
+    MALLOCARRAY(rowBuffer, bytesPerRow);
+        
+    if (rowBuffer == NULL)
+        asprintfN(&error, "Unable to allocate memory for row buffer "
+                  "for %u columns", cols);
+    else {
+        ssize_t rc;
 
         rc = fread(rowBuffer, 1, bytesPerRow, fileP);
     
         if (feof(fileP))
-            pm_error("Unexpected EOF reading row of PPM image.");
+            asprintfN(&error, "Unexpected EOF reading row of PPM image.");
         else if (ferror(fileP))
-            pm_error("Error reading row.  fread() errno=%d (%s)",
-                     errno, strerror(errno));
+            asprintfN(&error, "Error reading row.  fread() errno=%d (%s)",
+                      errno, strerror(errno));
         else if (rc != bytesPerRow)
-            pm_error("Error reading row.  Short read of %u bytes "
-                     "instead of %u", rc, bytesPerRow);
-    
-        bufferCursor = 0;  /* start at beginning of rowBuffer[] */
+            asprintfN(&error, "Error reading row.  Short read of %u bytes "
+                      "instead of %u", rc, bytesPerRow);
+        else {
+            unsigned int bufferCursor;
+
+            error = NULL;
+
+            bufferCursor = 0;  /* start at beginning of rowBuffer[] */
         
-        if (bytesPerSample == 1) {
-            unsigned int col;
-            for (col = 0; col < cols; ++col) {
-                pixval const r = rowBuffer[bufferCursor++];
-                pixval const g = rowBuffer[bufferCursor++];
-                pixval const b = rowBuffer[bufferCursor++];
-                PPM_ASSIGN(pixelrow[col], r, g, b);
-            }
-        } else  {
-            /* two byte samples */
-            unsigned int col;
-            for (col = 0; col < cols; ++col) {
-                pixval r, g, b;
-
-                r = rowBuffer[bufferCursor++] << 8;
-                r |= rowBuffer[bufferCursor++];
-
-                g = rowBuffer[bufferCursor++] << 8;
-                g |= rowBuffer[bufferCursor++];
-
-                b = rowBuffer[bufferCursor++] << 8;
-                b |= rowBuffer[bufferCursor++];
-                
-                PPM_ASSIGN(pixelrow[col], r, g, b);
+            if (bytesPerSample == 1) {
+                unsigned int col;
+                for (col = 0; col < cols; ++col) {
+                    pixval const r = rowBuffer[bufferCursor++];
+                    pixval const g = rowBuffer[bufferCursor++];
+                    pixval const b = rowBuffer[bufferCursor++];
+                    PPM_ASSIGN(pixelrow[col], r, g, b);
+                }
+            } else  {
+                /* two byte samples */
+                unsigned int col;
+                for (col = 0; col < cols; ++col) {
+                    pixval r, g, b;
+                    
+                    r = rowBuffer[bufferCursor++] << 8;
+                    r |= rowBuffer[bufferCursor++];
+                    
+                    g = rowBuffer[bufferCursor++] << 8;
+                    g |= rowBuffer[bufferCursor++];
+                    
+                    b = rowBuffer[bufferCursor++] << 8;
+                    b |= rowBuffer[bufferCursor++];
+                    
+                    PPM_ASSIGN(pixelrow[col], r, g, b);
+                }
             }
         }
         free(rowBuffer);
     }
-    break;
+    if (error) {
+        pm_errormsg("%s", error);
+        strfree(error);
+        pm_longjmp();
+    }
+}
 
-    case PGM_FORMAT:
-    case RPGM_FORMAT: {
-        gray * const grayrow = pgm_allocrow(cols);
+
+
+static void
+readpgm(FILE *       const fileP, 
+        pixel *      const pixelrow, 
+        unsigned int const cols, 
+        pixval       const maxval, 
+        int          const format) {
+
+    jmp_buf jmpbuf;
+    jmp_buf * origJmpbufP;
+    gray * grayrow;
+
+    grayrow = pgm_allocrow(cols);
+
+    if (setjmp(jmpbuf) != 0) {
+        pgm_freerow(grayrow);
+        pm_setjmpbuf(origJmpbufP);
+        pm_longjmp();
+    } else {
         unsigned int col;
+    
+        pm_setjmpbufsave(&jmpbuf, &origJmpbufP);
 
         pgm_readpgmrow(fileP, grayrow, cols, maxval, format);
+
         for (col = 0; col < cols; ++col) {
             pixval const g = grayrow[col];
             PPM_ASSIGN(pixelrow[col], g, g, g);
         }
-        pgm_freerow(grayrow);
+        pm_setjmpbuf(origJmpbufP);
     }
-    break;
+    pgm_freerow(grayrow);
+}
 
-    case PBM_FORMAT:
-    case RPBM_FORMAT: {
-        bit * const bitrow = pbm_allocrow(cols);
+
+
+static void
+readpbm(FILE *       const fileP, 
+        pixel *      const pixelrow, 
+        unsigned int const cols, 
+        pixval       const maxval, 
+        int          const format) {
+
+    jmp_buf jmpbuf;
+    jmp_buf * origJmpbufP;
+    bit * bitrow;
+
+    bitrow = pbm_allocrow(cols);
+
+    if (setjmp(jmpbuf) != 0) {
+        pbm_freerow(bitrow);
+        pm_setjmpbuf(origJmpbufP);
+        pm_longjmp();
+    } else {
         unsigned int col;
 
+        pm_setjmpbufsave(&jmpbuf, &origJmpbufP);
+
         pbm_readpbmrow(fileP, bitrow, cols, format);
+
         for (col = 0; col < cols; ++col) {
             pixval const g = (bitrow[col] == PBM_WHITE) ? maxval : 0;
             PPM_ASSIGN(pixelrow[col], g, g, g);
         }
-        pbm_freerow(bitrow);
+        pm_setjmpbuf(origJmpbufP);
     }
-    break;
+    pbm_freerow(bitrow);
+}
+
+
+
+void
+ppm_readppmrow(FILE *  const fileP, 
+               pixel * const pixelrow, 
+               int     const cols, 
+               pixval  const maxval, 
+               int     const format) {
+
+    switch (format) {
+    case PPM_FORMAT:
+        readppm(fileP, pixelrow, cols, maxval, format);
+        break;
+
+    /* For PAM, we require a depth of 3, which means the raster format
+       is identical to Raw PPM!  How convenient.
+    */
+    case PAM_FORMAT:
+    case RPPM_FORMAT:
+        readrppm(fileP, pixelrow, cols, maxval, format);
+        break;
+
+    case PGM_FORMAT:
+    case RPGM_FORMAT:
+        readpgm(fileP, pixelrow, cols, maxval, format);
+        break;
+
+    case PBM_FORMAT:
+    case RPBM_FORMAT:
+        readpbm(fileP, pixelrow, cols, maxval, format);
+        break;
 
     default:
         pm_error("Invalid format code");
@@ -281,17 +370,36 @@ ppm_readppm(FILE *   const fileP,
             int *    const colsP, 
             int *    const rowsP, 
             pixval * const maxvalP) {
-    pixel** pixels;
-    int row;
+
+    jmp_buf jmpbuf;
+    jmp_buf * origJmpbufP;
+    pixel ** pixels;
+    int cols, rows;
+    pixval maxval;
     int format;
 
-    ppm_readppminit(fileP, colsP, rowsP, maxvalP, &format);
+    ppm_readppminit(fileP, &cols, &rows, &maxval, &format);
 
-    pixels = ppm_allocarray(*colsP, *rowsP);
+    pixels = ppm_allocarray(cols, rows);
 
-    for (row = 0; row < *rowsP; ++row)
-        ppm_readppmrow(fileP, pixels[row], *colsP, *maxvalP, format);
+    if (setjmp(jmpbuf) != 0) {
+        ppm_freearray(pixels, rows);
+        pm_setjmpbuf(origJmpbufP);
+        pm_longjmp();
+    } else {
+        unsigned int row;
 
+        pm_setjmpbufsave(&jmpbuf, &origJmpbufP);
+
+        for (row = 0; row < rows; ++row)
+            ppm_readppmrow(fileP, pixels[row], cols, maxval, format);
+
+        *colsP = cols;
+        *rowsP = rows;
+        *maxvalP = maxval;
+
+        pm_setjmpbuf(origJmpbufP);
+    }
     return pixels;
 }