www.pudn.com > doc2pdf-0_7_1.rar > printablecodec.c
// Code obtained from John Walkers qprint project // // http://www.fourmilab.ch/webtools/qprint // // Some minor modifications made by Matt Peterson #include#include #include #include #include #include #define TRUE 1 #define FALSE 0 #define LINELEN 72 #define MAXINLINE 256 #define ASCII_HORIZONTAL_TAB 9 #define ASCII_LINE_FEED 10 #define ASCII_CARRIAGE_RETURN 13 #define ASCII_SPACE 32 #define ASCII_0 48 #define ASCII_EQUAL_SIGN 61 #define ASCII_A 65 #define ASCII_LOWER_CASE_A 97 #define Character_is_printable_ISO_8859(c) (((((c) >=0x20) &&((c) <=0x7E) ) ||((c) >=0xA1) ) ) \ typedef unsigned char byte; static FILE*fi; static FILE*fo; typedef enum { Rule_1,Rule_2,Rule_3,Rule_4,Rule_EBCDIC } character_encoding_rule; static character_encoding_rule character_class[256]; static int current_line_length= 0; static int pending_white_space= 0; #if (SIZEOF_UNSIGNED_LONG == 8) || (SIZEOF_UNSIGNED_LONG_LONG == 0) typedef unsigned long file_address_type; #define FILE_ADDRESS_FORMAT_LENGTH "l" #else typedef unsigned long long file_address_type; #define FILE_ADDRESS_FORMAT_LENGTH "ll" #endif static file_address_type decode_input_stream_position= 0; static long decode_errors= 0; static int decoding= FALSE; static int encoding= FALSE; static int binary_input= FALSE; static int errcheck= TRUE; static int EBCDIC_out= FALSE; static int paranoid= FALSE; static int read_decode_character(void); static int hex_to_nybble(int ch); static void output_line_break(void) { static char line_break[3]= {ASCII_CARRIAGE_RETURN,ASCII_LINE_FEED,0}; fputs(line_break,fo); current_line_length= 0; } static void check_line_length(int chars_required) { if ((current_line_length+chars_required)>=(LINELEN-1)) { putc(ASCII_EQUAL_SIGN,fo); output_line_break(); } current_line_length+= chars_required; } static void emit_literally(int ch) { check_line_length(1); putc(ch,fo); } static void emit_hex_encoded(int ch) { static char hex[16]= {ASCII_0,ASCII_0+1,ASCII_0+2,ASCII_0+3, ASCII_0+4,ASCII_0+5,ASCII_0+6, ASCII_0+7,ASCII_0+8,ASCII_0+9, ASCII_A,ASCII_A+1,ASCII_A+2,ASCII_A+3, ASCII_A+4,ASCII_A+5}; check_line_length(3); putc(ASCII_EQUAL_SIGN,fo); putc(hex[(ch>>4)&0xF],fo); putc(hex[ch&0xF],fo); } static void encode(void) { int i,ch; for (i= 0;i<=255;i++) { character_class[i]= Rule_1; } for (i= 33;i<=60;i++) { character_class[i]= Rule_2; } for (i= 62;i<=126;i++) { character_class[i]= Rule_2; } character_class[ASCII_HORIZONTAL_TAB]= Rule_3; character_class[ASCII_SPACE]= Rule_3; character_class[ASCII_LINE_FEED]= Rule_4; character_class[ASCII_CARRIAGE_RETURN]= Rule_4; character_class[33]= character_class[34]= character_class[35]= character_class[36]= character_class[64]= character_class[91]= character_class[92]= character_class[93]= character_class[94]= character_class[96]= character_class[123]= character_class[124]= character_class[125]= character_class[126]= Rule_EBCDIC; while ((ch= getc(fi))!=EOF) { switch (character_class[ch]) { case Rule_1: if (pending_white_space!=0) { emit_literally(pending_white_space); pending_white_space= 0; } emit_hex_encoded(ch); break; case Rule_2: if (pending_white_space!=0) { emit_literally(pending_white_space); pending_white_space= 0; } if (paranoid) { emit_hex_encoded(ch); } else { emit_literally(ch); } break; case Rule_3: if (paranoid) { emit_hex_encoded(ch); } else { if (pending_white_space!=0) { emit_literally(pending_white_space); pending_white_space= 0; } pending_white_space= ch; } break; case Rule_4: if (binary_input) { if (pending_white_space!=0) { emit_literally(pending_white_space); pending_white_space= 0; } emit_hex_encoded(ch); } else { { int chn= getc(fi); if (chn!=EOF) { if ((chn==ASCII_LINE_FEED)||(chn==ASCII_CARRIAGE_RETURN)) { if (chn==ch) { ungetc(chn,fi); } } else { ungetc(chn,fi); } } } if (pending_white_space!=0) { emit_hex_encoded(pending_white_space); pending_white_space= 0; } output_line_break(); } break; case Rule_EBCDIC: if (pending_white_space!=0) { emit_literally(pending_white_space); pending_white_space= 0; } if (EBCDIC_out||paranoid) { emit_hex_encoded(ch); } else { emit_literally(ch); } break; } } if (pending_white_space!=0) { emit_literally(pending_white_space); pending_white_space= 0; } if (current_line_length> 0) { putc(ASCII_EQUAL_SIGN,fo); output_line_break(); } } static int is_end_of_line_sequence(int ch) { if(ch == EOF) { return TRUE; } if ((ch==ASCII_CARRIAGE_RETURN)||(ch==ASCII_LINE_FEED)) { int chn= getc(fi); if (chn!=EOF) { if ((chn==ASCII_LINE_FEED)||(chn==ASCII_CARRIAGE_RETURN)) { if (chn==ch) { ungetc(chn,fi); } } else { ungetc(chn,fi); } } return TRUE; } return FALSE; } static void decode(void) { int ch,ch1,ch2; while ((ch= read_decode_character())!=EOF) { switch (ch) { case ASCII_EQUAL_SIGN: ch1= read_decode_character(); while (((ch1==ASCII_SPACE)||(ch1==ASCII_HORIZONTAL_TAB))) { ch1= read_decode_character(); if (is_end_of_line_sequence(ch1)) { break; } if (!((ch1==ASCII_SPACE)||(ch1==ASCII_HORIZONTAL_TAB))) { if (errcheck) { if (('a'==0x61) && Character_is_printable_ISO_8859(ch1)) { fprintf(stderr, "Error: invalid character \"%c\" in soft line break sequence at byte %" FILE_ADDRESS_FORMAT_LENGTH "u (0x%" FILE_ADDRESS_FORMAT_LENGTH "X) of input.\n", ch1,decode_input_stream_position-1, decode_input_stream_position-1); } else { fprintf(stderr, "Error: invalid character \"0x%02X\" in soft line break sequence at byte %" FILE_ADDRESS_FORMAT_LENGTH "u (0x%" FILE_ADDRESS_FORMAT_LENGTH "X) of input.\n", ch1,decode_input_stream_position-1, decode_input_stream_position-1); } } decode_errors++; ch1= ASCII_SPACE; } } if (is_end_of_line_sequence(ch1)) { ch= EOF; } else { int n1,n2; n1= hex_to_nybble(ch1); ch2= read_decode_character(); n2= hex_to_nybble(ch2); if (n1==EOF||n2==EOF) { if (errcheck) { if (('a'==0x61) && Character_is_printable_ISO_8859(ch1)&& Character_is_printable_ISO_8859(ch2)) { fprintf(stderr, "Error: bad equal sign escape \"=%c%c\" at byte %" FILE_ADDRESS_FORMAT_LENGTH "u (0x%" FILE_ADDRESS_FORMAT_LENGTH "X) of input.\n", ch1,ch2,decode_input_stream_position-3, decode_input_stream_position-3); } else { fprintf(stderr, "Error: bad equal sign escape \"= 0x%02X 0x%02X\" at byte %" FILE_ADDRESS_FORMAT_LENGTH "u (0x%" FILE_ADDRESS_FORMAT_LENGTH "X) of input.\n", ch1,ch2,decode_input_stream_position-3, decode_input_stream_position-3); } } decode_errors++; } ch= (n1<<4)|n2; } if (ch!=EOF) { putc(ch,fo); } break; case ASCII_CARRIAGE_RETURN: case ASCII_LINE_FEED: { int chn= getc(fi); if (chn!=EOF) { if ((chn==ASCII_LINE_FEED)||(chn==ASCII_CARRIAGE_RETURN)) { if (chn==ch) { ungetc(chn,fi); } } else { ungetc(chn,fi); } } } putc('\n',fo); break; default: putc(ch,fo); break; } } } static int read_decode_character(void) { int ch; ch= getc(fi); if (ch!=EOF) { decode_input_stream_position++; } return ch; } static int hex_to_nybble(int ch) { if ((ch>=ASCII_0)&&(ch<=(ASCII_0+9))) { return ch-'0'; } else if ((ch>=ASCII_A)&&(ch<=(ASCII_A+5))) { return 10+(ch-ASCII_A); } else if ((ch>=ASCII_LOWER_CASE_A)&&(ch<=(ASCII_LOWER_CASE_A+5))) { return 10+(ch-ASCII_LOWER_CASE_A); } return EOF; } // returns zero on success int decode_quoted_printable(const char* infilename, const char* outfilename) { fi = fopen(infilename,"r"); if(fi == NULL) { return -1; } fo = fopen(outfilename,"w"); if(fo == NULL) { return -1; } decode(); fclose(fi); fclose(fo); return 0; }