From 3403204f2e3feb6ac39148d2a5fe4257037af752 Mon Sep 17 00:00:00 2001 From: giraffedata Date: Tue, 19 May 2015 02:31:58 +0000 Subject: cleanup git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@2497 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- converter/pbm/atktopbm.c | 425 +++++++++++++++++++++++------------------------ 1 file changed, 207 insertions(+), 218 deletions(-) diff --git a/converter/pbm/atktopbm.c b/converter/pbm/atktopbm.c index 62664999..807e4f4a 100644 --- a/converter/pbm/atktopbm.c +++ b/converter/pbm/atktopbm.c @@ -61,17 +61,24 @@ */ /* macros to generate case entries for switch statement */ -#define case1(v) case v -#define case4(v) case v: case (v)+1: case (v)+2: case(v)+3 -#define case6(v) case4(v): case ((v)+4): case ((v)+5) -#define case8(v) case4(v): case4((v)+4) +#define CASE1(v) case v +#define CASE4(v) case v: case (v)+1: case (v)+2: case(v)+3 +#define CASE6(v) CASE4(v): case ((v)+4): case ((v)+5) +#define CASE8(v) CASE4(v): CASE4((v)+4) + + static long -ReadRow(FILE * const file, unsigned char * const row, long const length) { +ReadRow(FILE * const file, + unsigned char * const row, + long const length) { /*---------------------------------------------------------------------------- 'file' is where to get them from. 'row' is where to put bytes. 'length' is how many bytes in row must be filled. + + Return the delimiter that marks the end of the row, or EOF if EOF marks + the end of the row, or NUL in some cases. -----------------------------------------------------------------------------*/ /* Each input character is processed by the central loop. There are ** some input codes which require two or three characters for @@ -80,18 +87,23 @@ ReadRow(FILE * const file, unsigned char * const row, long const length) { ** to the Ready state whenever a character unacceptable to the ** current state is read. */ - enum stateCode { - Ready, /* any input code is allowed */ - HexDigitPending, /* have seen the first of a hex digit pair */ - RepeatPending, /* repeat code has been seen: - must be followed by two hex digits */ - RepeatAndDigit}; /* have seen repeat code and its first - following digit */ - enum stateCode InputState; /* current state */ - register int c; /* the current input character */ - register long repeatcount = 0; /* current repeat value */ - register long hexval; /* current hex value */ - long pendinghex = 0; /* the first of a pair of hex characters */ + enum StateCode { + Ready, + /* any input code is allowed */ + HexDigitPending, + /* have seen the first of a hex digit pair */ + RepeatPending, + /* repeat code has been seen: must be followed by two hex digits + */ + RepeatAndDigit + /* have seen repeat code and its first following digit */ + }; + + enum StateCode InputState; /* current state */ + int c; /* the current input character */ + long repeatcount; /* current repeat value */ + long hexval; /* current hex value */ + long pendinghex; /* the first of a pair of hex characters */ int lengthRemaining; unsigned char * cursor; @@ -101,262 +113,239 @@ ReadRow(FILE * const file, unsigned char * const row, long const length) { ** zero, we ungetc the byte. */ - lengthRemaining = length; - cursor = row; + repeatcount = 0; /* initial value */ + pendinghex = 0; /* initial value */ + + lengthRemaining = length; /* initial value */ + cursor = row; /* initial value */ + InputState = Ready; /* initial value */ - InputState = Ready; while ((c=getc(file)) != EOF) switch (c) { - case8(0x0): - case8(0x8): - case8(0x10): - case8(0x18): - case1(' '): - /* control characters and space are legal and ignored */ - break; - case1(0x40): /* '@' */ - case1(0x5B): /* '[' */ - case4(0x5D): /* ']' '^' '_' '`' */ - case4(0x7D): /* '}' '~' DEL 0x80 */ - default: /* all above 0x80 */ - /* error code: Ignored at present. Reset InputState. */ - InputState = Ready; - break; - - case1(0x7B): /* '{' */ - case1(0x5C): /* '\\' */ - /* illegal end of line: exit anyway */ - ungetc(c, file); /* retain terminator in stream */ - /* DROP THROUGH */ - case1(0x7C): /* '|' */ - /* legal end of row: may have to pad */ - while (lengthRemaining-- > 0) - *cursor++ = WHITEBYTE; - return c; + CASE8(0x0): + CASE8(0x8): + CASE8(0x10): + CASE8(0x18): + CASE1(' '): + /* control characters and space are legal and ignored */ + break; + CASE1(0x40): /* '@' */ + CASE1(0x5B): /* '[' */ + CASE4(0x5D): /* ']' '^' '_' '`' */ + CASE4(0x7D): /* '}' '~' DEL 0x80 */ + default: /* all above 0x80 */ + /* error code: Ignored at present. Reset InputState. */ + InputState = Ready; + break; + + CASE1(0x7B): /* '{' */ + CASE1(0x5C): /* '\\' */ + /* illegal end of line: exit anyway */ + ungetc(c, file); /* retain terminator in stream */ + /* DROP THROUGH */ + CASE1(0x7C): /* '|' */ + /* legal end of row: may have to pad */ + while (lengthRemaining-- > 0) + *cursor++ = WHITEBYTE; + return c; - case1(0x21): - case6(0x22): - case8(0x28): - /* punctuation characters: repeat byte given by two - ** succeeding hex chars - */ - if (lengthRemaining <= 0) { - ungetc(c, file); - return('\0'); - } - repeatcount = c - OTHERZERO; - InputState = RepeatPending; - break; - - case8(0x30): - case8(0x38): - /* digit (or following punctuation) - hex digit */ - hexval = c - 0x30; - goto hexdigit; - case6(0x41): - /* A ... F - hex digit */ - hexval = c - (0x41 - 0xA); - goto hexdigit; - case6(0x61): - /* a ... f - hex digit */ - hexval = c - (0x61 - 0xA); - goto hexdigit; - - case8(0x67): - case8(0x6F): - case4(0x77): - /* g ... z - multiple WHITE bytes */ - if (lengthRemaining <= 0) { - ungetc(c, file); - return('\0'); - } - repeatcount = c - WHITEZERO; - hexval = WHITEBYTE; - goto store; - case8(0x47): - case8(0x4F): - case4(0x57): - /* G ... Z - multiple BLACK bytes */ - if (lengthRemaining <= 0) { - ungetc(c, file); - return('\0'); - } - repeatcount = c - BLACKZERO; - hexval = BLACKBYTE; - goto store; - -hexdigit: - /* process a hex digit. Use InputState to determine - what to do with it. */ - if (lengthRemaining <= 0) { - ungetc(c, file); - return('\0'); - } - switch(InputState) { - case Ready: - InputState = HexDigitPending; - pendinghex = hexval << 4; + CASE1(0x21): + CASE6(0x22): + CASE8(0x28): + /* punctuation characters: repeat byte given by two + ** succeeding hex chars + */ + if (lengthRemaining <= 0) { + ungetc(c, file); + return('\0'); + } + repeatcount = c - OTHERZERO; + InputState = RepeatPending; break; - case HexDigitPending: - hexval |= pendinghex; - repeatcount = 1; + + CASE8(0x30): + CASE8(0x38): + /* digit (or following punctuation) - hex digit */ + hexval = c - 0x30; + goto hexdigit; + CASE6(0x41): + /* A ... F - hex digit */ + hexval = c - (0x41 - 0xA); + goto hexdigit; + CASE6(0x61): + /* a ... f - hex digit */ + hexval = c - (0x61 - 0xA); + goto hexdigit; + + CASE8(0x67): + CASE8(0x6F): + CASE4(0x77): + /* g ... z - multiple WHITE bytes */ + if (lengthRemaining <= 0) { + ungetc(c, file); + return('\0'); + } + repeatcount = c - WHITEZERO; + hexval = WHITEBYTE; goto store; - case RepeatPending: - InputState = RepeatAndDigit; - pendinghex = hexval << 4; - break; - case RepeatAndDigit: - hexval |= pendinghex; + CASE8(0x47): + CASE8(0x4F): + CASE4(0x57): + /* G ... Z - multiple BLACK bytes */ + if (lengthRemaining <= 0) { + ungetc(c, file); + return('\0'); + } + repeatcount = c - BLACKZERO; + hexval = BLACKBYTE; goto store; - } - break; - -store: - /* generate byte(s) into the output row - Use repeatcount, depending on state. */ - if (lengthRemaining < repeatcount) - /* reduce repeat count if it would exceed - available space */ - repeatcount = lengthRemaining; - lengthRemaining -= repeatcount; /* do this before repeatcount-- */ - while (repeatcount-- > 0) + + hexdigit: + /* process a hex digit. Use InputState to determine + what to do with it. */ + if (lengthRemaining <= 0) { + ungetc(c, file); + return('\0'); + } + switch(InputState) { + case Ready: + InputState = HexDigitPending; + pendinghex = hexval << 4; + break; + case HexDigitPending: + hexval |= pendinghex; + repeatcount = 1; + goto store; + case RepeatPending: + InputState = RepeatAndDigit; + pendinghex = hexval << 4; + break; + case RepeatAndDigit: + hexval |= pendinghex; + goto store; + } + break; + + store: + /* generate byte(s) into the output row + Use repeatcount, depending on state. */ + if (lengthRemaining < repeatcount) + /* reduce repeat count if it would exceed + available space */ + repeatcount = lengthRemaining; + lengthRemaining -= repeatcount; /* do this before repeatcount-- */ + while (repeatcount-- > 0) *cursor++ = hexval; - InputState = Ready; - break; + InputState = Ready; + break; - } /* end of while( - )switch( - ) */ + } /* end of while( - )switch( - ) */ return EOF; } -#undef case1 -#undef case4 -#undef case6 -#undef case8 +#undef CASE1 +#undef CASE4 +#undef CASE6 +#undef CASE8 static void -ReadATKRaster(FILE * const file, - int * const rwidth, - int * const rheight, - unsigned char ** const destaddrP) { +ReadATKRaster(FILE * const ifP) { - int row, rowlen; /* count rows; byte length of row */ + int row; /* count rows; byte length of row */ int version; char keyword[6]; int discardid; int objectid; /* id read for the incoming pixel image */ long tc; /* temp */ int width, height; /* dimensions of image */ + bit * bitrow; - if (fscanf(file, "\\begindata{raster,%d", &discardid) != 1 - || getc(file) != '}' || getc(file) != '\n') - pm_error ("input file not Andrew raster object"); + if (fscanf(ifP, "\\begindata{raster,%d", &discardid) != 1 + || getc(ifP) != '}' || getc(ifP) != '\n') + pm_error ("input file not Andrew raster object"); - fscanf(file, " %d ", &version); + fscanf(ifP, " %d ", &version); if (version < 2) - pm_error ("version too old to parse"); + pm_error ("version too old to parse"); { unsigned int options; long xscale, yscale; long xoffset, yoffset, subwidth, subheight; /* ignore all these features: */ - fscanf(file, " %u %ld %ld %ld %ld %ld %ld", + fscanf(ifP, " %u %ld %ld %ld %ld %ld %ld", &options, &xscale, &yscale, &xoffset, &yoffset, &subwidth, &subheight); } /* scan to end of line in case this is actually something beyond V2 */ - while (((tc=getc(file)) != '\n') && (tc != '\\') && (tc != EOF)) {} + while (((tc=getc(ifP)) != '\n') && (tc != '\\') && (tc != EOF)) {} /* read the keyword */ - fscanf(file, " %5s", keyword); + fscanf(ifP, " %5s", keyword); if (!streq(keyword, "bits")) - pm_error ("keyword is not 'bits'!"); + pm_error ("keyword is not 'bits'!"); - fscanf(file, " %d %d %d ", &objectid, &width, &height); + fscanf(ifP, " %d %d %d ", &objectid, &width, &height); if (width < 1 || height < 1 || width > 1000000 || height > 1000000) - pm_error ("bad width or height"); - - *rwidth = width; - *rheight = height; - rowlen = (width + 7) / 8; - MALLOCARRAY(*destaddrP, height * rowlen); - if (destaddrP == NULL) - pm_error("Unable to allocate %u bytes for the input image.", - height * rowlen); - for (row = 0; row < height; row++) - { - long c; - - c = ReadRow(file, *destaddrP + (row * rowlen), rowlen); - if (c != '|') - { - if (c == EOF) - pm_error ("premature EOF"); - else - pm_error ("bad format"); - break; - } - } - while (! feof(file) && getc(file) != '\\') {}; /* scan for \enddata */ - if (fscanf(file, "enddata{raster,%d", &discardid) != 1 - || getc(file) != '}' || getc(file) != '\n') - pm_error ("missing end-of-object marker"); -} + pm_error("bad width or height"); + pbm_writepbminit(stdout, width, height, 0); + bitrow = pbm_allocrow_packed(width); + for (row = 0; row < height; ++row) { + unsigned int const rowlen = (width + 7) / 8; + long const nextChar = ReadRow(ifP, bitrow, rowlen); -int -main(int argc, char **argv) { + switch (nextChar) { + case '|': + pbm_writepbmrow_packed(stdout, bitrow, width, 0); + break; + case EOF: + pm_error("premature EOF"); + break; + default: + pm_error("bad format"); + } + } - FILE *ifp; - register bit *bitrow, *bP; - int rows, cols, row, col, charcount; - unsigned char *data, mask; + pbm_freerow_packed(bitrow); + while (! feof(ifP) && getc(ifP) != '\\') {}; /* scan for \enddata */ - pbm_init ( &argc, argv ); + if (fscanf(ifP, "enddata{raster,%d", &discardid) != 1 + || getc(ifP) != '}' || getc(ifP) != '\n') + pm_error("missing end-of-object marker"); +} - if ( argc > 2 ) - pm_usage( "[raster obj]" ); - - if ( argc == 2 ) - ifp = pm_openr( argv[1] ); - else - ifp = stdin; - ReadATKRaster( ifp, &cols, &rows, &data ); - pm_close( ifp ); +int +main(int argc, const char ** argv) { - pbm_writepbminit( stdout, cols, rows, 0 ); - bitrow = pbm_allocrow( cols ); + FILE * ifP; - for ( row = 0; row < rows; ++row ) - { - charcount = 0; - mask = 0x80; - for ( col = 0, bP = bitrow; col < cols; ++col, ++bP ) - { - if ( charcount >= 8 ) - { - ++data; - charcount = 0; - mask = 0x80; - } - *bP = ( *data & mask ) ? PBM_BLACK : PBM_WHITE; - ++charcount; - mask >>= 1; - } - ++data; - pbm_writepbmrow( stdout, bitrow, cols, 0 ); + pm_proginit(&argc, argv); + + if (argc-1 < 1) + ifP = stdin; + else { + ifP = pm_openr(argv[1]); + + if (argc-1 > 1) + pm_error("Too many arguments. The only possible argument is " + "the input file name"); } - pm_close( stdout ); - exit( 0 ); -} + ReadATKRaster(ifP); + + pm_close(ifP); + pm_close(stdout); + + return 0; +} -- cgit 1.4.1