about summary refs log tree commit diff
path: root/lib/libpgm1.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/libpgm1.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/libpgm1.c')
-rw-r--r--lib/libpgm1.c186
1 files changed, 124 insertions, 62 deletions
diff --git a/lib/libpgm1.c b/lib/libpgm1.c
index 75fa365b..5b17910a 100644
--- a/lib/libpgm1.c
+++ b/lib/libpgm1.c
@@ -28,6 +28,7 @@
 #include "libpam.h"
 #include "fileio.h"
 #include "mallocvar.h"
+#include "nstring.h"
 
 
 gray *
@@ -190,105 +191,166 @@ pgm_getrawsample(FILE * const file,
 
 
 
-void
-pgm_readpgmrow(FILE * const file,
+static void
+readRpgmRow(FILE * const fileP,
                gray * const grayrow, 
                int    const cols,
                gray   const maxval,
                int    const format) {
 
-    switch (format) {
-    case PGM_FORMAT: {
-        unsigned int col;
-        for (col = 0; col < cols; ++col) {
-            grayrow[col] = pm_getuint(file);
-            if (grayrow[col] > maxval)
-                pm_error("value out of bounds (%u > %u)",
-                         grayrow[col], maxval);
+    unsigned int const bytesPerSample = maxval < 256 ? 1 : 2;
+    int          const bytesPerRow    = cols * bytesPerSample;
+    
+    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 (rc == 0)
+            asprintfN(&error, "Error reading row.  fread() errno=%d (%s)",
+                      errno, strerror(errno));
+        else if (rc != bytesPerRow)
+            asprintfN(&error, "Error reading row.  Short read of %u bytes "
+                      "instead of %u", rc, bytesPerRow);
+        else {
+            error = NULL;
+            if (maxval < 256) {
+                unsigned int col;
+                for (col = 0; col < cols; ++col)
+                    grayrow[col] = (gray)rowBuffer[col];
+            } else {
+                unsigned int bufferCursor;
+                unsigned int col;
+                
+                bufferCursor = 0;  /* Start at beginning of rowBuffer[] */
+                
+                for (col = 0; col < cols; ++col) {
+                    gray g;
+                    
+                    g = rowBuffer[bufferCursor++] << 8;
+                    g |= rowBuffer[bufferCursor++];
+                    
+                    grayrow[col] = g;
+                }
+            }
         }
+        free(rowBuffer);
     }
-    break;
-        
-    case RPGM_FORMAT: {
-        unsigned int const bytesPerSample = maxval < 256 ? 1 : 2;
-        int          const bytesPerRow    = cols * bytesPerSample;
+    if (error) {
+        pm_errormsg("%s", error);
+        strfree(error);
+        pm_longjmp();
+    }
+} 
 
-        unsigned char * rowBuffer;
-        ssize_t rc;
 
-        MALLOCARRAY(rowBuffer, bytesPerRow);
-        if (rowBuffer == NULL)
-            pm_error("Unable to allocate memory for row buffer "
-                     "for %u columns", cols);
 
-        rc = fread(rowBuffer, 1, bytesPerRow, file);
-        if (rc == 0)
-            pm_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);
+static void
+readPbmRow(FILE * const fileP,
+           gray * const grayrow, 
+           int    const cols,
+           gray   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)
+            grayrow[col] = (bitrow[col] == PBM_WHITE ) ? maxval : 0;
 
-        if (maxval < 256) {
-            unsigned int col;
-            for (col = 0; col < cols; ++col)
-                grayrow[col] = (gray)rowBuffer[col];
-        } else {
-            unsigned int bufferCursor;
-            unsigned int col;
+        pm_setjmpbuf(origJmpbufP);
+    }
+    pbm_freerow(bitrow);
+}
 
-            bufferCursor = 0;  /* Start at beginning of rowBuffer[] */
 
-            for (col = 0; col < cols; ++col) {
-                gray g;
 
-                g = rowBuffer[bufferCursor++] << 8;
-                g |= rowBuffer[bufferCursor++];
+void
+pgm_readpgmrow(FILE * const fileP,
+               gray * const grayrow, 
+               int    const cols,
+               gray   const maxval,
+               int    const format) {
 
-                grayrow[col] = g;
-            }
+    switch (format) {
+    case PGM_FORMAT: {
+        unsigned int col;
+        for (col = 0; col < cols; ++col) {
+            grayrow[col] = pm_getuint(fileP);
+            if (grayrow[col] > maxval)
+                pm_error("value out of bounds (%u > %u)",
+                         grayrow[col], maxval);
         }
-        free(rowBuffer);
     }
+    break;
+        
+    case RPGM_FORMAT:
+        readRpgmRow(fileP, grayrow, cols, maxval, format);
         break;
     
     case PBM_FORMAT:
-    case RPBM_FORMAT: {
-        bit * bitrow;
-        int col;
-
-        bitrow = pbm_allocrow(cols);
-        pbm_readpbmrow( file, bitrow, cols, format );
-        for (col = 0; col < cols; ++col)
-            grayrow[col] = (bitrow[col] == PBM_WHITE ) ? maxval : 0;
-        pbm_freerow(bitrow);
-    }
+    case RPBM_FORMAT:
+        readPbmRow(fileP, grayrow, cols, maxval, format);
         break;
         
     default:
-        pm_error( "can't happen" );
+        pm_error("can't happen");
     }
 }
 
 
 
 gray **
-pgm_readpgm(FILE * const file,
+pgm_readpgm(FILE * const fileP,
             int *  const colsP,
             int *  const rowsP, 
             gray * const maxvalP) {
 
-    gray** grays;
-    int row;
+    gray ** grays;
+    int rows, cols;
+    gray maxval;
     int format;
+    jmp_buf jmpbuf;
+    jmp_buf * origJmpbufP;
 
-    pgm_readpgminit( file, colsP, rowsP, maxvalP, &format );
+    pgm_readpgminit(fileP, &cols, &rows, &maxval, &format);
     
-    grays = pgm_allocarray( *colsP, *rowsP );
-    
-    for ( row = 0; row < *rowsP; ++row )
-        pgm_readpgmrow( file, grays[row], *colsP, *maxvalP, format );
+    grays = pgm_allocarray(cols, rows);
+
+    if (setjmp(jmpbuf) != 0) {
+        pgm_freearray(grays, rows);
+        pm_setjmpbuf(origJmpbufP);
+        pm_longjmp();
+    } else {
+        unsigned int row;
     
+        pm_setjmpbufsave(&jmpbuf, &origJmpbufP);
+
+        for (row = 0; row < rows; ++row)
+            pgm_readpgmrow(fileP, grays[row], cols, maxval, format);
+
+        pm_setjmpbuf(origJmpbufP);
+    }
+    *colsP = cols;
+    *rowsP = rows;
+    *maxvalP = maxval;
     return grays;
 }