-/* Tool for working with BIF-6809 images.\r// Written by Joel Matthew Rees, Amagasaki, Japan, April 2019,\r// Parts adapted from the author's 32col.c, written 1999.\r// Copyright 1999, 2019, Joel Matthew Rees.\r// Permission granted in advance for all uses\r// with the condition that this copyright and permission notice are retained.\r//\r// BIF-6809 project page: https://osdn.net/projects/bif-6809/\r*/\r\r#include <stdio.h>\r#include <stdlib.h> /* for EXIT_SUCCESS */\r#include <string.h>\r#include <ctype.h>\r\r\r#define ScreenWidth 32\r#define ScreenHeight 32\r#define BufferPlay 3 /* room for CR/LF and NUL */\r#define BufferWidth ( ScreenWidth + BufferPlay ) \r\r\r#define TO_SCREEN 1\rconst char kTo_ScreenStr[] = "--to-screens";\r#define TO_EOLN_TEXT 2\rconst char kTo_EOLN_textStr[] = "--to-eoln-text";\r\r\rvoid toEOLNtext( FILE * input, FILE * output /*, int linecountflag */ )\r{\r char buffer[ ScreenHeight ][ BufferWidth ];\r\r while ( !feof( input ) )\r {\r int lineCount;\r for ( lineCount = 0; lineCount < ScreenHeight && !feof( input ); ++lineCount )\r {\r int length = fread( buffer[ lineCount ], sizeof (char), ScreenWidth, input );\r while ( --length >= 0 \r && ( isspace( buffer[ lineCount ][ length ] ) \r || !isprint( buffer[ lineCount ][ length ] ) ) )\r /* "empty" loop */;\r buffer[ lineCount ][ ++length ] = '\0';\r }\r if ( lineCount > 1 \r || ( lineCount == 1 && buffer[ 0 ][ 0 ] != '\0' ) )\r {\r int line = 0;\r while ( --lineCount > 0 && buffer[ lineCount ][ 0 ] == '\0' )\r /* "empty" loop */;\r for ( line = 0; line <= lineCount; ++line ) /* check end conditions again. */\r { fputs( buffer[ line ], output );\r fputc( '\n', output );\r }\r fputc( '\f', output );\r }\r }\r}\r\r\r#define FILE_START 0x200 /* beyond char range. */\r#define LINE_START 0x400 /* beyond char range. */\r\r\rvoid toScreens( FILE * input, FILE * output /*, int linecountflag */ )\r{\r char buffer[ ScreenHeight ][ BufferWidth ];\r int eolFlag = FILE_START;\r while ( !feof( input ) )\r {\r int lineCount;\r for ( lineCount = 0; lineCount < ScreenHeight; ++lineCount )\r {\r int length = 0;\r char * line = buffer[ lineCount ];\r int ch = LINE_START;\r while ( ( length < ScreenWidth ) && !feof( input ) )\r { ch = fgetc( input );\r if ( ( length == 0 )\r && ( ( ( ch == '\r' ) && ( eolFlag == '\n' ) )\r || ( ( ch == '\n' ) && ( eolFlag == '\r' ) ) )\r )\r { ch = fgetc( input );\r }\r eolFlag = ch;\r if ( ( ch == '\n' ) || ( ch == '\r' ) || feof( input ) )\r { break; /* The habit is to set a NUL, but not for SCREENs. */\r }\r line[ length++ ] = ch;\r/* dbg * / putchar( ch ); */\r }\r/* dbg * / printf( "||end:%d:", length ); */\r while ( length < ScreenWidth )\r { line[ length++ ] = ' ';\r/* dbg * / putchar( '*' );*/\r }\r/* dbg * / printf( "||:%d:%d\n", length, lineCount ); */\r }\r/* dbg * / printf( "<<screen:%d:>>\n", lineCount ); */\r if ( lineCount > 0 )\r { int line = 0;\r for ( line = 0; line < lineCount; ++line )\r { fwrite( buffer[ line ], sizeof (char), ScreenWidth, output ); \r }\r }\r }\r}\r\r\rint main(int argc, char * argv[] )\r{\r FILE * input = stdin;\r FILE * output = stdout;\r int direction = 0;\r int blocksize = 1024;\r int offset = 0;\r int count = 0;\r\r if ( argc > 3 )\r {\r if ( strcmp( argv[ 1 ], kTo_ScreenStr ) == 0 )\r {\r direction = TO_SCREEN;\r }\r else if ( strcmp( argv[ 1 ], kTo_EOLN_textStr ) == 0 )\r {\r direction = TO_EOLN_TEXT;\r }\r if ( direction != 0 )\r {\r if ( strcmp( argv[ 2 ], "--" ) != 0 )\r {\r input = fopen( argv[ 2 ], "rb" );\r }\r if ( input == NULL )\r {\r printf( "Error opening file <%s> for input.\n", argv[ 2 ] );\r direction = -1;\r }\r if ( strcmp( argv[ 3 ], "--" ) != 0 )\r {\r output = fopen( argv[ 3 ], "wb" );\r }\r if ( output == NULL )\r {\r printf( "Error opening file <%s> for output.\n", argv[ 3 ] );\r fclose( input );\r direction = -1;\r }\r }\r }\r if ( direction < 0 )\r {\r printf( "*** %s quitting. ***\n", argv[ 0 ] );\r return EXIT_FAILURE;\r }\r else if ( direction == 0 )\r {\r puts( "usage:" );\r printf( "\t%s %s <infile> <outfile>\n", argv[ 0 ], kTo_ScreenStr );\r printf( "\t%s %s <infile> <outfile> [ [ -size=<block-size> ] -off=<offset> [ -count=<count> ] ]\n", argv[ 0 ], kTo_EOLN_textStr );\r printf( "** Default block size is 1024, compatible with Forth SCREENs.\n" );\r printf( "** Default count is length of input file.\n" );\r printf( "** 0xhexadecimal and 0octal permitted for size, etc.\n" );\r printf( "** Replace <file> with -- for stdfiles in pipes\n" );\r /* printf( "\t%s --to-image <filename> <imagename> <offset>\n", argv[ 0 ] ); */\r return EXIT_SUCCESS;\r }\r\r switch ( direction )\r {\r case TO_SCREEN:\r toScreens( input, output );\r break;\r case TO_EOLN_TEXT:\r toEOLNtext( input, output );\r break;\r }\r\r return EXIT_SUCCESS;\r}\r\r
\ No newline at end of file
+/* Tool for working with BIF-6809 images.\r// Written by Joel Matthew Rees, Amagasaki, Japan, April 2019,\r// Parts adapted from the author's 32col.c, written 1999.\r// Copyright 1999, 2019, Joel Matthew Rees.\r// Permission granted in advance for all uses\r// with the condition that this copyright and permission notice are retained.\r//\r// BIF-6809 project page: https://osdn.net/projects/bif-6809/\r*/\r\r#include <limits.h>\r#include <stdio.h>\r#include <stdlib.h> /* for EXIT_SUCCESS */\r#include <string.h>\r#include <ctype.h>\r\r\r#define ScreenWidth 32\r#define ScreenHeight 32\r#define BufferPlay 3 /* room for CR/LF and NUL */\r#define BufferWidth ( ScreenWidth + BufferPlay ) \r\r\r#define TO_SCREEN 1\rconst char kTo_ScreenStr[] = "--to-screens";\r#define TO_EOLN_TEXT 2\rconst char kTo_EOLN_textStr[] = "--to-eoln-text";\r\rconst char kBlockSize[] = "-size";\rconst char kBlockOffset[] = "-off";\rconst char kBlockCount[] = "-count";\r\r\rvoid toEOLNtext( FILE * input, FILE * output, unsigned blocksize, unsigned offset, unsigned count /*, int linecountflag */ )\r{\r char buffer[ ScreenHeight ][ BufferWidth ];\r unsigned long start = blocksize * offset;\r unsigned long bytecount = blocksize * count;\r unsigned long totalBytes = 0;\r\r/* dbg */ printf( "size: %u; off: %u; count: %u\n", blocksize, offset, count ); \r\r if ( start > 0 )\r { fseek( input, start, SEEK_SET );\r }\r while ( !feof( input ) && ( totalBytes < bytecount ) )\r {\r int lineCount;\r for ( lineCount = 0; lineCount < ScreenHeight && !feof( input ); ++lineCount )\r {\r int length = fread( buffer[ lineCount ], sizeof (char), ScreenWidth, input );\r totalBytes += length;\r while ( --length >= 0 \r && ( isspace( buffer[ lineCount ][ length ] ) \r || !isprint( buffer[ lineCount ][ length ] ) ) )\r /* "empty" loop */;\r buffer[ lineCount ][ ++length ] = '\0';\r }\r if ( lineCount > 1 \r || ( lineCount == 1 && buffer[ 0 ][ 0 ] != '\0' ) )\r {\r int line = 0;\r while ( --lineCount > 0 && buffer[ lineCount ][ 0 ] == '\0' ) /* This actually is probably a bug. */\r /* "empty" loop */;\r for ( line = 0; line <= lineCount; ++line ) /* check end conditions again. */\r { fputs( buffer[ line ], output );\r fputc( '\n', output );\r }\r /* fputc( '\f', output ); This is not useful. */\r }\r }\r}\r\r\r#define FILE_START 0x200 /* beyond char range. */\r#define LINE_START 0x400 /* beyond char range. */\r\r\rvoid toScreens( FILE * input, FILE * output /*, int linecountflag */ )\r{\r char buffer[ ScreenHeight ][ BufferWidth ];\r\r int eolFlag = FILE_START;\r while ( !feof( input ) )\r {\r int lineCount;\r for ( lineCount = 0; lineCount < ScreenHeight; ++lineCount )\r {\r int length = 0;\r char * line = buffer[ lineCount ];\r int ch = LINE_START;\r while ( ( length < ScreenWidth ) && !feof( input ) )\r { ch = fgetc( input );\r if ( ( length == 0 )\r && ( ( ( ch == '\r' ) && ( eolFlag == '\n' ) )\r || ( ( ch == '\n' ) && ( eolFlag == '\r' ) ) )\r )\r { ch = fgetc( input );\r }\r eolFlag = ch;\r if ( ( ch == '\n' ) || ( ch == '\r' ) || feof( input ) )\r { break; /* The habit is to set a NUL, but not for SCREENs. */\r }\r line[ length++ ] = ch;\r/* dbg * / putchar( ch ); */\r }\r/* dbg * / printf( "||end:%d:", length ); */\r while ( length < ScreenWidth )\r { line[ length++ ] = ' ';\r/* dbg * / putchar( '*' );*/\r }\r/* dbg * / printf( "||:%d:%d\n", length, lineCount ); */\r }\r/* dbg * / printf( "<<screen:%d:>>\n", lineCount ); */\r if ( lineCount > 0 )\r { int line = 0;\r for ( line = 0; line < lineCount; ++line )\r { fwrite( buffer[ line ], sizeof (char), ScreenWidth, output ); \r }\r }\r }\r}\r\rint getNumericParameter( const char parameter[], char * argstr,\r unsigned long * rval, long low, unsigned long limit )\r{\r char * scanpt = argstr;\r unsigned long result = 0;\r size_t eqpt = strlen( parameter );\r if ( strncmp( parameter, argstr, eqpt ) == 0 ) \r {\r if ( argstr[ eqpt ] != '=' )\r { printf( "\t%s needs '=' in '%s'\n,", parameter, argstr );\r return INT_MIN | 16;\r }\r ++eqpt;\r scanpt += eqpt;\r result = strtoul( scanpt, &scanpt, 0 );\r if ( scanpt <= argstr + eqpt )\r { printf( "\tBad %s value specified in '%s'\n,", parameter, argstr );\r return INT_MIN | 32;\r }\r if ( ( result < low ) || ( result >= limit ) )\r { printf( "\t%s value %lu out of range in '%s', try %lu\n,", parameter, result, argstr, * rval );\r return INT_MIN | 64;\r }\r * rval = result;\r return 1;\r }\r return 0;\r}\r\r\rint main(int argc, char * argv[] )\r{\r FILE * input = stdin;\r FILE * output = stdout;\r int direction = 0;\r int errval = 0;\r unsigned long blocksize = 1024;\r unsigned long offset = 0;\r unsigned long count = UINT_MAX;\r int i;\r\r for ( i = 4; i < argc; ++i )\r { int berr = 0;\r int oerr = 0;\r int cerr = 0;\r if ( ( ( berr |= getNumericParameter( kBlockSize, argv[ i ], &blocksize, 1, 0x8000UL ) ) <= 0 )\r && ( ( oerr |= getNumericParameter( kBlockOffset, argv[ i ], &offset, 1, USHRT_MAX ) ) <= 0 )\r && ( ( cerr |= getNumericParameter( kBlockCount, argv[ i ], &count, 1, USHRT_MAX ) ) <= 0 ) )\r { printf( "Unrecognized %s\n", argv[ i ] );\r errval |= berr | oerr | cerr;\r }\r }\r if ( ( errval >= 0 ) && ( argc > 3 ) )\r {\r if ( strcmp( argv[ 1 ], kTo_ScreenStr ) == 0 )\r {\r direction = TO_SCREEN;\r }\r else if ( strcmp( argv[ 1 ], kTo_EOLN_textStr ) == 0 )\r {\r direction = TO_EOLN_TEXT;\r }\r if ( direction != 0 )\r {\r if ( strcmp( argv[ 2 ], "--" ) != 0 )\r {\r input = fopen( argv[ 2 ], "rb" );\r }\r if ( input == NULL )\r {\r printf( "Error opening file <%s> for input.\n", argv[ 2 ] );\r direction |= INT_MIN | 4;\r }\r if ( strcmp( argv[ 3 ], "--" ) != 0 )\r {\r output = fopen( argv[ 3 ], "wb" );\r }\r if ( output == NULL )\r {\r printf( "Error opening file <%s> for output.\n", argv[ 3 ] );\r fclose( input );\r direction |= INT_MIN | 8;\r }\r }\r }\r if ( direction < -1 )\r {\r printf( "*** %s quitting. ***\n", argv[ 0 ] );\r return EXIT_FAILURE;\r }\r else if ( direction == 0 )\r {\r puts( "usage:" );\r printf( "\t%s %s <infile> <outfile>\n", argv[ 0 ], kTo_ScreenStr );\r printf( "\t%s %s <infile> <outfile> [ %s=<block-size> ] [ %s=<offset> ] [ %s=<count> ]\n", \r argv[ 0 ], kTo_EOLN_textStr, kBlockSize, kBlockOffset, kBlockCount );\r printf( "** Default block size is 1024, compatible with Forth SCREENs.\n" );\r printf( "** Default count is length of input file.\n" );\r printf( "** 0xhexadecimal and 0octal permitted for size, etc.\n" );\r printf( "** Replace <file> with -- for stdfiles in pipes\n" );\r /* printf( "\t%s --to-image <filename> <imagename> <offset>\n", argv[ 0 ] ); */\r return EXIT_SUCCESS;\r }\r\r switch ( direction )\r {\r case TO_SCREEN:\r toScreens( input, output );\r break;\r case TO_EOLN_TEXT:\r toEOLNtext( input, output, blocksize, offset, count );\r break;\r }\r\r return EXIT_SUCCESS;\r}\r\r
\ No newline at end of file